nice
This commit is contained in:
26
faas/web/package-lock.json
generated
26
faas/web/package-lock.json
generated
@ -10,11 +10,13 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mantine/code-highlight": "^7.0.0",
|
"@mantine/code-highlight": "^7.0.0",
|
||||||
"@mantine/core": "^7.0.0",
|
"@mantine/core": "^7.0.0",
|
||||||
|
"@mantine/dates": "^7.0.0",
|
||||||
"@mantine/form": "^7.0.0",
|
"@mantine/form": "^7.0.0",
|
||||||
"@mantine/hooks": "^7.0.0",
|
"@mantine/hooks": "^7.0.0",
|
||||||
"@mantine/notifications": "^7.0.0",
|
"@mantine/notifications": "^7.0.0",
|
||||||
"@tabler/icons-react": "^2.40.0",
|
"@tabler/icons-react": "^2.40.0",
|
||||||
"axios": "^1.6.0",
|
"axios": "^1.11.0",
|
||||||
|
"dayjs": "^1.11.13",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-router-dom": "^6.8.0"
|
"react-router-dom": "^6.8.0"
|
||||||
@ -736,6 +738,22 @@
|
|||||||
"react-dom": "^18.x || ^19.x"
|
"react-dom": "^18.x || ^19.x"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@mantine/dates": {
|
||||||
|
"version": "7.17.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@mantine/dates/-/dates-7.17.8.tgz",
|
||||||
|
"integrity": "sha512-KYog/YL83PnsMef7EZagpOFq9I2gfnK0eYSzC8YvV9Mb6t/x9InqRssGWVb0GIr+TNILpEkhKoGaSKZNy10Q1g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"clsx": "^2.1.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@mantine/core": "7.17.8",
|
||||||
|
"@mantine/hooks": "7.17.8",
|
||||||
|
"dayjs": ">=1.0.0",
|
||||||
|
"react": "^18.x || ^19.x",
|
||||||
|
"react-dom": "^18.x || ^19.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@mantine/form": {
|
"node_modules/@mantine/form": {
|
||||||
"version": "7.17.8",
|
"version": "7.17.8",
|
||||||
"resolved": "https://registry.npmjs.org/@mantine/form/-/form-7.17.8.tgz",
|
"resolved": "https://registry.npmjs.org/@mantine/form/-/form-7.17.8.tgz",
|
||||||
@ -2052,6 +2070,12 @@
|
|||||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/dayjs": {
|
||||||
|
"version": "1.11.18",
|
||||||
|
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.18.tgz",
|
||||||
|
"integrity": "sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
"version": "4.4.1",
|
"version": "4.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
|
||||||
|
|||||||
@ -3,16 +3,18 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mantine/core": "^7.0.0",
|
|
||||||
"@mantine/hooks": "^7.0.0",
|
|
||||||
"@mantine/notifications": "^7.0.0",
|
|
||||||
"@mantine/form": "^7.0.0",
|
|
||||||
"@mantine/code-highlight": "^7.0.0",
|
|
||||||
"@tabler/icons-react": "^2.40.0",
|
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-router-dom": "^6.8.0",
|
"react-router-dom": "^6.8.0",
|
||||||
"axios": "^1.6.0"
|
"@mantine/core": "^7.0.0",
|
||||||
|
"@mantine/hooks": "^7.0.0",
|
||||||
|
"@mantine/notifications": "^7.0.0",
|
||||||
|
"@mantine/dates": "^7.0.0",
|
||||||
|
"@mantine/form": "^7.0.0",
|
||||||
|
"@mantine/code-highlight": "^7.0.0",
|
||||||
|
"@tabler/icons-react": "^2.40.0",
|
||||||
|
"axios": "^1.11.0",
|
||||||
|
"dayjs": "^1.11.13"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.22.0",
|
"@babel/core": "^7.22.0",
|
||||||
@ -32,6 +34,6 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "webpack serve --mode development",
|
"start": "webpack serve --mode development",
|
||||||
"build": "webpack --mode production",
|
"build": "webpack --mode production",
|
||||||
"dev": "npm start"
|
"dev": "webpack serve --mode development"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,26 +1,60 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { MantineProvider, AppShell, Title, Group, Badge, Text } from '@mantine/core';
|
import { Box, Title, Tabs, Stack, ActionIcon, Group, Select } from '@mantine/core';
|
||||||
import { Notifications } from '@mantine/notifications';
|
import {
|
||||||
import { IconFunction } from '@tabler/icons-react';
|
IconFunction,
|
||||||
|
IconPlayerPlay,
|
||||||
|
IconStar,
|
||||||
|
IconStarFilled
|
||||||
|
} from '@tabler/icons-react';
|
||||||
import { FunctionList } from './components/FunctionList';
|
import { FunctionList } from './components/FunctionList';
|
||||||
import { FunctionForm } from './components/FunctionForm';
|
import { FunctionForm } from './components/FunctionForm';
|
||||||
import { ExecutionModal } from './components/ExecutionModal';
|
import { ExecutionModal } from './components/ExecutionModal';
|
||||||
import { FunctionDefinition } from './types';
|
import { FunctionDefinition } from './types';
|
||||||
|
|
||||||
// Default Mantine theme
|
|
||||||
const theme: any = {
|
|
||||||
colorScheme: 'light',
|
|
||||||
};
|
|
||||||
|
|
||||||
const App: React.FC = () => {
|
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 [functionFormOpened, setFunctionFormOpened] = useState(false);
|
||||||
const [executionModalOpened, setExecutionModalOpened] = useState(false);
|
const [executionModalOpened, setExecutionModalOpened] = useState(false);
|
||||||
const [editingFunction, setEditingFunction] = useState<FunctionDefinition | null>(null);
|
const [editingFunction, setEditingFunction] = useState<FunctionDefinition | null>(null);
|
||||||
const [executingFunction, setExecutingFunction] = useState<FunctionDefinition | null>(null);
|
const [executingFunction, setExecutingFunction] = useState<FunctionDefinition | null>(null);
|
||||||
const [refreshKey, setRefreshKey] = useState(0);
|
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 = () => {
|
const handleCreateFunction = () => {
|
||||||
console.log('handleCreateFunction called');
|
|
||||||
setEditingFunction(null);
|
setEditingFunction(null);
|
||||||
setFunctionFormOpened(true);
|
setFunctionFormOpened(true);
|
||||||
};
|
};
|
||||||
@ -49,49 +83,121 @@ const App: React.FC = () => {
|
|||||||
setExecutingFunction(null);
|
setExecutingFunction(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
const toggleFavorite = () => {
|
||||||
<MantineProvider theme={theme}>
|
setIsFavorited(prev => !prev);
|
||||||
<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>
|
|
||||||
|
|
||||||
<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
|
<FunctionList
|
||||||
key={refreshKey}
|
key={refreshKey}
|
||||||
onCreateFunction={handleCreateFunction}
|
onCreateFunction={handleCreateFunction}
|
||||||
onEditFunction={handleEditFunction}
|
onEditFunction={handleEditFunction}
|
||||||
onExecuteFunction={handleExecuteFunction}
|
onExecuteFunction={handleExecuteFunction}
|
||||||
/>
|
/>
|
||||||
|
);
|
||||||
<FunctionForm
|
case 'executions':
|
||||||
opened={functionFormOpened}
|
return <div>Executions view coming soon...</div>;
|
||||||
onClose={handleFormClose}
|
default:
|
||||||
onSuccess={handleFormSuccess}
|
return (
|
||||||
editFunction={editingFunction}
|
<FunctionList
|
||||||
|
key={refreshKey}
|
||||||
|
onCreateFunction={handleCreateFunction}
|
||||||
|
onEditFunction={handleEditFunction}
|
||||||
|
onExecuteFunction={handleExecuteFunction}
|
||||||
/>
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
<ExecutionModal
|
return (
|
||||||
opened={executionModalOpened}
|
<Box w="100%" pos="relative">
|
||||||
onClose={handleExecutionClose}
|
<Stack gap="lg">
|
||||||
function={executingFunction}
|
<div>
|
||||||
/>
|
<Group justify="space-between" align="flex-start">
|
||||||
</AppShell.Main>
|
<div>
|
||||||
</AppShell>
|
<Group align="center" gap="sm" mb="xs">
|
||||||
</MantineProvider>
|
<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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
211
faas/web/src/App.tsx.backup
Normal file
211
faas/web/src/App.tsx.backup
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { Box, Title, Tabs, Stack, ActionIcon, Group, Select } from '@mantine/core';
|
||||||
|
import {
|
||||||
|
IconFunction,
|
||||||
|
IconPlay,
|
||||||
|
IconDashboard,
|
||||||
|
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';
|
||||||
|
|
||||||
|
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 'dashboard';
|
||||||
|
};
|
||||||
|
|
||||||
|
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 = value === 'dashboard' ? basePath : `${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 = () => {
|
||||||
|
setEditingFunction(null);
|
||||||
|
setFunctionFormOpened(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEditFunction = (func: FunctionDefinition) => {
|
||||||
|
setEditingFunction(func);
|
||||||
|
setFunctionFormOpened(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleExecuteFunction = (func: FunctionDefinition) => {
|
||||||
|
setExecutingFunction(func);
|
||||||
|
setExecutionModalOpened(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFormSuccess = () => {
|
||||||
|
setRefreshKey(prev => prev + 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFormClose = () => {
|
||||||
|
setFunctionFormOpened(false);
|
||||||
|
setEditingFunction(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleExecutionClose = () => {
|
||||||
|
setExecutionModalOpened(false);
|
||||||
|
setExecutingFunction(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
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 = () => {
|
||||||
|
switch (currentRoute) {
|
||||||
|
case 'functions':
|
||||||
|
return (
|
||||||
|
<FunctionList
|
||||||
|
key={refreshKey}
|
||||||
|
onCreateFunction={handleCreateFunction}
|
||||||
|
onEditFunction={handleEditFunction}
|
||||||
|
onExecuteFunction={handleExecuteFunction}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
case 'executions':
|
||||||
|
return <div>Executions view coming soon...</div>;
|
||||||
|
default:
|
||||||
|
return (
|
||||||
|
<FunctionList
|
||||||
|
key={refreshKey}
|
||||||
|
onCreateFunction={handleCreateFunction}
|
||||||
|
onEditFunction={handleEditFunction}
|
||||||
|
onExecuteFunction={handleExecuteFunction}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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="dashboard"
|
||||||
|
leftSection={<IconDashboard size={16} />}
|
||||||
|
>
|
||||||
|
Dashboard
|
||||||
|
</Tabs.Tab>
|
||||||
|
<Tabs.Tab
|
||||||
|
value="functions"
|
||||||
|
leftSection={<IconFunction size={16} />}
|
||||||
|
>
|
||||||
|
Functions
|
||||||
|
</Tabs.Tab>
|
||||||
|
<Tabs.Tab
|
||||||
|
value="executions"
|
||||||
|
leftSection={<IconPlay 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>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default App;
|
||||||
@ -18,7 +18,7 @@ import {
|
|||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconPlayerPlay, IconPlayerStop, IconRefresh, IconCopy } from '@tabler/icons-react';
|
import { IconPlayerPlay, IconPlayerStop, IconRefresh, IconCopy } from '@tabler/icons-react';
|
||||||
import { notifications } from '@mantine/notifications';
|
import { notifications } from '@mantine/notifications';
|
||||||
import { functionApi, executionApi } from '../services/api';
|
import { functionApi, executionApi } from '../services/apiService';
|
||||||
import { FunctionDefinition, ExecuteFunctionResponse, FunctionExecution } from '../types';
|
import { FunctionDefinition, ExecuteFunctionResponse, FunctionExecution } from '../types';
|
||||||
|
|
||||||
interface ExecutionModalProps {
|
interface ExecutionModalProps {
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import {
|
|||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { useForm } from '@mantine/form';
|
import { useForm } from '@mantine/form';
|
||||||
import { notifications } from '@mantine/notifications';
|
import { notifications } from '@mantine/notifications';
|
||||||
import { functionApi, runtimeApi } from '../services/api';
|
import { functionApi, runtimeApi } from '../services/apiService';
|
||||||
import { FunctionDefinition, CreateFunctionRequest, UpdateFunctionRequest, RuntimeType } from '../types';
|
import { FunctionDefinition, CreateFunctionRequest, UpdateFunctionRequest, RuntimeType } from '../types';
|
||||||
|
|
||||||
interface FunctionFormProps {
|
interface FunctionFormProps {
|
||||||
|
|||||||
@ -26,7 +26,7 @@ import {
|
|||||||
IconExclamationCircle,
|
IconExclamationCircle,
|
||||||
} from '@tabler/icons-react';
|
} from '@tabler/icons-react';
|
||||||
import { notifications } from '@mantine/notifications';
|
import { notifications } from '@mantine/notifications';
|
||||||
import { functionApi } from '../services/api';
|
import { functionApi } from '../services/apiService';
|
||||||
import { FunctionDefinition } from '../types';
|
import { FunctionDefinition } from '../types';
|
||||||
|
|
||||||
interface FunctionListProps {
|
interface FunctionListProps {
|
||||||
|
|||||||
@ -1,9 +1,21 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { createRoot } from 'react-dom/client';
|
import ReactDOM from 'react-dom/client';
|
||||||
|
import { BrowserRouter } from 'react-router-dom';
|
||||||
|
import { MantineProvider } from '@mantine/core';
|
||||||
|
import { Notifications } from '@mantine/notifications';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
|
|
||||||
const container = document.getElementById('root');
|
const root = ReactDOM.createRoot(
|
||||||
if (container) {
|
document.getElementById('root') as HTMLElement
|
||||||
const root = createRoot(container);
|
);
|
||||||
root.render(<App />);
|
|
||||||
}
|
root.render(
|
||||||
|
<React.StrictMode>
|
||||||
|
<MantineProvider>
|
||||||
|
<Notifications />
|
||||||
|
<BrowserRouter>
|
||||||
|
<App />
|
||||||
|
</BrowserRouter>
|
||||||
|
</MantineProvider>
|
||||||
|
</React.StrictMode>
|
||||||
|
);
|
||||||
21
faas/web/src/index.tsx.backup
Normal file
21
faas/web/src/index.tsx.backup
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom/client';
|
||||||
|
import { BrowserRouter } from 'react-router-dom';
|
||||||
|
import { MantineProvider } from '@mantine/core';
|
||||||
|
import { Notifications } from '@mantine/notifications';
|
||||||
|
import App from './App';
|
||||||
|
|
||||||
|
const root = ReactDOM.createRoot(
|
||||||
|
document.getElementById('root') as HTMLElement
|
||||||
|
);
|
||||||
|
|
||||||
|
root.render(
|
||||||
|
<React.StrictMode>
|
||||||
|
<MantineProvider>
|
||||||
|
<Notifications />
|
||||||
|
<BrowserRouter>
|
||||||
|
<App />
|
||||||
|
</BrowserRouter>
|
||||||
|
</MantineProvider>
|
||||||
|
</React.StrictMode>
|
||||||
|
);
|
||||||
64
faas/web/src/types.ts
Normal file
64
faas/web/src/types.ts
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
export interface FunctionDefinition {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
description?: string;
|
||||||
|
runtime: RuntimeType;
|
||||||
|
code: string;
|
||||||
|
status: 'active' | 'inactive';
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
tags?: string[];
|
||||||
|
timeout?: number;
|
||||||
|
memoryLimit?: number;
|
||||||
|
image?: string;
|
||||||
|
env_vars?: Record<string, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FunctionExecution {
|
||||||
|
id: string;
|
||||||
|
functionId: string;
|
||||||
|
input: string;
|
||||||
|
output?: string;
|
||||||
|
error?: string;
|
||||||
|
status: 'pending' | 'running' | 'completed' | 'failed';
|
||||||
|
startTime: string;
|
||||||
|
endTime?: string;
|
||||||
|
duration?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type RuntimeType = 'nodejs18' | 'python3.9' | 'go1.20';
|
||||||
|
|
||||||
|
export interface CreateFunctionRequest {
|
||||||
|
name: string;
|
||||||
|
description?: string;
|
||||||
|
runtime: RuntimeType;
|
||||||
|
code: string;
|
||||||
|
image?: string;
|
||||||
|
timeout?: number;
|
||||||
|
memory_limit?: number;
|
||||||
|
env_vars?: Record<string, string>;
|
||||||
|
tags?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateFunctionRequest extends Partial<CreateFunctionRequest> {}
|
||||||
|
|
||||||
|
export interface ExecuteFunctionRequest {
|
||||||
|
function_id: string;
|
||||||
|
input?: any;
|
||||||
|
async?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ExecuteFunctionResponse {
|
||||||
|
execution_id: string;
|
||||||
|
output?: any;
|
||||||
|
error?: string;
|
||||||
|
status: 'pending' | 'running' | 'completed' | 'failed';
|
||||||
|
duration?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RuntimeInfo {
|
||||||
|
runtime: RuntimeType;
|
||||||
|
image: string;
|
||||||
|
version: string;
|
||||||
|
available: boolean;
|
||||||
|
}
|
||||||
@ -1,22 +1,16 @@
|
|||||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||||
const { ModuleFederationPlugin } = require('webpack').container;
|
const { ModuleFederationPlugin } = require('webpack').container;
|
||||||
|
const webpack = require('webpack');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
mode: 'development',
|
mode: 'development',
|
||||||
entry: './src/index.tsx',
|
entry: './src/index.tsx',
|
||||||
devServer: {
|
devServer: {
|
||||||
port: 3003,
|
port: 3003,
|
||||||
historyApiFallback: true,
|
|
||||||
static: {
|
|
||||||
directory: './public',
|
|
||||||
},
|
|
||||||
headers: {
|
headers: {
|
||||||
'Access-Control-Allow-Origin': '*',
|
'Access-Control-Allow-Origin': '*',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
output: {
|
|
||||||
publicPath: 'auto',
|
|
||||||
},
|
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions: ['.tsx', '.ts', '.js', '.jsx'],
|
extensions: ['.tsx', '.ts', '.js', '.jsx'],
|
||||||
},
|
},
|
||||||
@ -46,43 +40,46 @@ module.exports = {
|
|||||||
name: 'faas',
|
name: 'faas',
|
||||||
filename: 'remoteEntry.js',
|
filename: 'remoteEntry.js',
|
||||||
exposes: {
|
exposes: {
|
||||||
'./FaaSApp': './src/App',
|
'./App': './src/App.tsx',
|
||||||
},
|
},
|
||||||
shared: {
|
shared: {
|
||||||
react: {
|
react: {
|
||||||
singleton: true,
|
singleton: true,
|
||||||
requiredVersion: '^18.2.0',
|
requiredVersion: '^18.2.0',
|
||||||
eager: true,
|
eager: false,
|
||||||
},
|
},
|
||||||
'react-dom': {
|
'react-dom': {
|
||||||
singleton: true,
|
singleton: true,
|
||||||
requiredVersion: '^18.2.0',
|
requiredVersion: '^18.2.0',
|
||||||
eager: true,
|
eager: false,
|
||||||
},
|
},
|
||||||
'@mantine/core': {
|
'@mantine/core': {
|
||||||
singleton: true,
|
singleton: true,
|
||||||
requiredVersion: '^7.0.0',
|
requiredVersion: '^7.0.0',
|
||||||
eager: true,
|
eager: false,
|
||||||
},
|
},
|
||||||
'@mantine/hooks': {
|
'@mantine/hooks': {
|
||||||
singleton: true,
|
singleton: true,
|
||||||
requiredVersion: '^7.0.0',
|
requiredVersion: '^7.0.0',
|
||||||
eager: true,
|
eager: false,
|
||||||
},
|
},
|
||||||
'@mantine/notifications': {
|
'@mantine/notifications': {
|
||||||
singleton: true,
|
singleton: true,
|
||||||
requiredVersion: '^7.0.0',
|
requiredVersion: '^7.0.0',
|
||||||
eager: true,
|
eager: false,
|
||||||
},
|
},
|
||||||
'@tabler/icons-react': {
|
'@tabler/icons-react': {
|
||||||
singleton: true,
|
singleton: true,
|
||||||
requiredVersion: '^2.40.0',
|
requiredVersion: '^2.40.0',
|
||||||
eager: true,
|
eager: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
new HtmlWebpackPlugin({
|
new HtmlWebpackPlugin({
|
||||||
template: './public/index.html',
|
template: './public/index.html',
|
||||||
}),
|
}),
|
||||||
|
new webpack.DefinePlugin({
|
||||||
|
'process.env': JSON.stringify(process.env),
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
85
faas/web/webpack.config.js.backup
Normal file
85
faas/web/webpack.config.js.backup
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||||
|
const { ModuleFederationPlugin } = require('webpack').container;
|
||||||
|
const webpack = require('webpack');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
mode: 'development',
|
||||||
|
entry: './src/index.tsx',
|
||||||
|
devServer: {
|
||||||
|
port: 3003,
|
||||||
|
headers: {
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.tsx', '.ts', '.js', '.jsx'],
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.(js|jsx|ts|tsx)$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
use: {
|
||||||
|
loader: 'babel-loader',
|
||||||
|
options: {
|
||||||
|
presets: [
|
||||||
|
'@babel/preset-react',
|
||||||
|
'@babel/preset-typescript',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.css$/,
|
||||||
|
use: ['style-loader', 'css-loader'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new ModuleFederationPlugin({
|
||||||
|
name: 'faas',
|
||||||
|
filename: 'remoteEntry.js',
|
||||||
|
exposes: {
|
||||||
|
'./App': './src/App.tsx',
|
||||||
|
},
|
||||||
|
shared: {
|
||||||
|
react: {
|
||||||
|
singleton: true,
|
||||||
|
requiredVersion: '^18.2.0',
|
||||||
|
eager: false,
|
||||||
|
},
|
||||||
|
'react-dom': {
|
||||||
|
singleton: true,
|
||||||
|
requiredVersion: '^18.2.0',
|
||||||
|
eager: false,
|
||||||
|
},
|
||||||
|
'@mantine/core': {
|
||||||
|
singleton: true,
|
||||||
|
requiredVersion: '^7.0.0',
|
||||||
|
eager: false,
|
||||||
|
},
|
||||||
|
'@mantine/hooks': {
|
||||||
|
singleton: true,
|
||||||
|
requiredVersion: '^7.0.0',
|
||||||
|
eager: false,
|
||||||
|
},
|
||||||
|
'@mantine/notifications': {
|
||||||
|
singleton: true,
|
||||||
|
requiredVersion: '^7.0.0',
|
||||||
|
eager: false,
|
||||||
|
},
|
||||||
|
'@tabler/icons-react': {
|
||||||
|
singleton: true,
|
||||||
|
requiredVersion: '^2.40.0',
|
||||||
|
eager: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
new HtmlWebpackPlugin({
|
||||||
|
template: './public/index.html',
|
||||||
|
}),
|
||||||
|
new webpack.DefinePlugin({
|
||||||
|
'process.env': JSON.stringify(process.env),
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
};
|
||||||
@ -6,7 +6,7 @@ import Breadcrumbs from './Breadcrumbs';
|
|||||||
|
|
||||||
const DemoApp = React.lazy(() => import('demo/App'));
|
const DemoApp = React.lazy(() => import('demo/App'));
|
||||||
const KMSApp = React.lazy(() => import('kms/App'));
|
const KMSApp = React.lazy(() => import('kms/App'));
|
||||||
const FaaSApp = React.lazy(() => import('faas/FaaSApp'));
|
const FaaSApp = React.lazy(() => import('faas/App'));
|
||||||
|
|
||||||
const AppLoader: React.FC = () => {
|
const AppLoader: React.FC = () => {
|
||||||
const { appName } = useParams<{ appName: string }>();
|
const { appName } = useParams<{ appName: string }>();
|
||||||
|
|||||||
Reference in New Issue
Block a user