-
This commit is contained in:
@ -1,21 +1,21 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import {
|
||||
Card,
|
||||
Group,
|
||||
Text,
|
||||
Badge,
|
||||
Stack,
|
||||
Table,
|
||||
Button,
|
||||
Stack,
|
||||
Title,
|
||||
Modal,
|
||||
Select,
|
||||
TextInput,
|
||||
Pagination,
|
||||
Container,
|
||||
Alert,
|
||||
Loader,
|
||||
Code,
|
||||
Group,
|
||||
ActionIcon,
|
||||
Modal,
|
||||
Badge,
|
||||
Card,
|
||||
Text,
|
||||
Loader,
|
||||
Alert,
|
||||
Code,
|
||||
ScrollArea,
|
||||
Flex,
|
||||
} from '@mantine/core';
|
||||
@ -183,19 +183,39 @@ const ExecutionList: React.FC = () => {
|
||||
|
||||
if (loading && executions.length === 0) {
|
||||
return (
|
||||
<Container size="xl">
|
||||
<Flex justify="center" align="center" h={200}>
|
||||
<Stack gap="lg">
|
||||
<Group justify="space-between">
|
||||
<Title order={2}>Function Executions</Title>
|
||||
<Button
|
||||
leftSection={<IconRefresh size={16} />}
|
||||
onClick={handleRefresh}
|
||||
loading={loading}
|
||||
>
|
||||
Refresh
|
||||
</Button>
|
||||
</Group>
|
||||
|
||||
<Stack align="center" justify="center" h={200}>
|
||||
<Loader size="lg" />
|
||||
</Flex>
|
||||
</Container>
|
||||
<Text>Loading executions...</Text>
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Container size="xl">
|
||||
<Stack gap="md">
|
||||
<Card>
|
||||
<Group justify="space-between" mb="md">
|
||||
<Stack gap="lg">
|
||||
<Group justify="space-between">
|
||||
<Title order={2}>Function Executions</Title>
|
||||
<Button
|
||||
leftSection={<IconRefresh size={16} />}
|
||||
onClick={handleRefresh}
|
||||
loading={loading}
|
||||
>
|
||||
Refresh
|
||||
</Button>
|
||||
</Group>
|
||||
|
||||
<Group>
|
||||
<TextInput
|
||||
placeholder="Search executions..."
|
||||
@ -216,24 +236,30 @@ const ExecutionList: React.FC = () => {
|
||||
style={{ width: 200 }}
|
||||
/>
|
||||
</Group>
|
||||
<Button leftSection={<IconRefresh size={16} />} onClick={handleRefresh} loading={loading}>
|
||||
Refresh
|
||||
</Button>
|
||||
</Group>
|
||||
|
||||
{error && (
|
||||
<Alert color="red" mb="md">
|
||||
<Alert color="red" title="Error">
|
||||
{error}
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
{filteredExecutions.length === 0 ? (
|
||||
<Text c="dimmed" ta="center" py="xl">
|
||||
<Card shadow="sm" radius="md" withBorder p="xl">
|
||||
<Stack align="center" gap="md">
|
||||
<IconClock size={48} color="gray" />
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
<Text fw={500} mb="xs">
|
||||
No executions found
|
||||
</Text>
|
||||
<Text size="sm" c="dimmed">
|
||||
There are no function executions matching your current filters
|
||||
</Text>
|
||||
</div>
|
||||
</Stack>
|
||||
</Card>
|
||||
) : (
|
||||
<ScrollArea>
|
||||
<Table striped highlightOnHover>
|
||||
<Card shadow="sm" radius="md" withBorder>
|
||||
<Table>
|
||||
<Table.Thead>
|
||||
<Table.Tr>
|
||||
<Table.Th>Function</Table.Th>
|
||||
@ -250,11 +276,11 @@ const ExecutionList: React.FC = () => {
|
||||
<Table.Td>
|
||||
<Stack gap={2}>
|
||||
<Text fw={500}>{getFunctionName(execution.function_id)}</Text>
|
||||
<Code size="xs">{execution.id.slice(0, 8)}...</Code>
|
||||
<Code style={{ fontSize: '12px' }}>{execution.id.slice(0, 8)}...</Code>
|
||||
</Stack>
|
||||
</Table.Td>
|
||||
<Table.Td>
|
||||
<Badge color={getStatusColor(execution.status)} variant="filled">
|
||||
<Badge color={getStatusColor(execution.status)} variant="light">
|
||||
{execution.status}
|
||||
</Badge>
|
||||
</Table.Td>
|
||||
@ -300,11 +326,11 @@ const ExecutionList: React.FC = () => {
|
||||
))}
|
||||
</Table.Tbody>
|
||||
</Table>
|
||||
</ScrollArea>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{totalPages > 1 && (
|
||||
<Group justify="center" mt="md">
|
||||
<Group justify="center">
|
||||
<Pagination
|
||||
value={page}
|
||||
onChange={setPage}
|
||||
@ -313,8 +339,6 @@ const ExecutionList: React.FC = () => {
|
||||
/>
|
||||
</Group>
|
||||
)}
|
||||
</Card>
|
||||
</Stack>
|
||||
|
||||
{/* Logs Modal */}
|
||||
<Modal
|
||||
@ -378,7 +402,7 @@ const ExecutionList: React.FC = () => {
|
||||
</div>
|
||||
</Stack>
|
||||
</Modal>
|
||||
</Container>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -1,18 +1,18 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import {
|
||||
Table,
|
||||
Badge,
|
||||
Button,
|
||||
Group,
|
||||
Text,
|
||||
ActionIcon,
|
||||
Menu,
|
||||
Paper,
|
||||
Stack,
|
||||
Title,
|
||||
Alert,
|
||||
Group,
|
||||
ActionIcon,
|
||||
Badge,
|
||||
Card,
|
||||
Text,
|
||||
Loader,
|
||||
Center,
|
||||
Alert,
|
||||
Tooltip,
|
||||
Menu,
|
||||
} from '@mantine/core';
|
||||
import {
|
||||
IconPlayerPlay,
|
||||
@ -114,40 +114,21 @@ export const FunctionList: React.FC<FunctionListProps> = ({
|
||||
}
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
if (loading && functions.length === 0) {
|
||||
return (
|
||||
<Center py={60}>
|
||||
<Loader size="lg" />
|
||||
</Center>
|
||||
);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<Alert icon={<IconExclamationCircle size={16} />} title="Error" color="red" mb="md">
|
||||
{error}
|
||||
<Button variant="light" size="xs" mt="sm" onClick={loadFunctions}>
|
||||
Retry
|
||||
</Button>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Paper shadow="xs" p="md">
|
||||
<Group justify="space-between" mb="md">
|
||||
<Stack gap="lg">
|
||||
<Group justify="space-between">
|
||||
<Title order={2}>Functions</Title>
|
||||
<Group>
|
||||
<Button
|
||||
leftSection={<IconRefresh size={14} />}
|
||||
variant="light"
|
||||
leftSection={<IconRefresh size={16} />}
|
||||
onClick={loadFunctions}
|
||||
loading={loading}
|
||||
>
|
||||
Refresh
|
||||
</Button>
|
||||
<Button
|
||||
leftSection={<IconPlus size={14} />}
|
||||
leftSection={<IconPlus size={16} />}
|
||||
onClick={onCreateFunction}
|
||||
>
|
||||
Create Function
|
||||
@ -155,26 +136,67 @@ export const FunctionList: React.FC<FunctionListProps> = ({
|
||||
</Group>
|
||||
</Group>
|
||||
|
||||
{functions.length === 0 ? (
|
||||
<Center py={40}>
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
<IconCode size={48} color="gray" />
|
||||
<Text size="lg" mt="md" c="dimmed">
|
||||
No functions found
|
||||
</Text>
|
||||
<Text size="sm" c="dimmed" mb="md">
|
||||
Create your first serverless function to get started
|
||||
</Text>
|
||||
<Stack align="center" justify="center" h={200}>
|
||||
<Loader size="lg" />
|
||||
<Text>Loading functions...</Text>
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack gap="lg">
|
||||
<Group justify="space-between">
|
||||
<Title order={2}>Functions</Title>
|
||||
<Group>
|
||||
<Button
|
||||
leftSection={<IconPlus size={14} />}
|
||||
leftSection={<IconRefresh size={16} />}
|
||||
onClick={loadFunctions}
|
||||
loading={loading}
|
||||
>
|
||||
Refresh
|
||||
</Button>
|
||||
<Button
|
||||
leftSection={<IconPlus size={16} />}
|
||||
onClick={onCreateFunction}
|
||||
>
|
||||
Create Function
|
||||
</Button>
|
||||
</Group>
|
||||
</Group>
|
||||
|
||||
{error && (
|
||||
<Alert color="red" title="Error">
|
||||
{error}
|
||||
<Button variant="light" size="xs" mt="sm" onClick={loadFunctions}>
|
||||
Retry
|
||||
</Button>
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
{functions.length === 0 ? (
|
||||
<Card shadow="sm" radius="md" withBorder p="xl">
|
||||
<Stack align="center" gap="md">
|
||||
<IconCode size={48} color="gray" />
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
<Text fw={500} mb="xs">
|
||||
No functions found
|
||||
</Text>
|
||||
<Text size="sm" c="dimmed">
|
||||
Create your first serverless function to get started
|
||||
</Text>
|
||||
</div>
|
||||
</Center>
|
||||
<Button
|
||||
leftSection={<IconPlus size={16} />}
|
||||
onClick={onCreateFunction}
|
||||
>
|
||||
Create Function
|
||||
</Button>
|
||||
</Stack>
|
||||
</Card>
|
||||
) : (
|
||||
<Table striped>
|
||||
<Card shadow="sm" radius="md" withBorder>
|
||||
<Table>
|
||||
<Table.Thead>
|
||||
<Table.Tr>
|
||||
<Table.Th>Name</Table.Th>
|
||||
@ -192,7 +214,7 @@ export const FunctionList: React.FC<FunctionListProps> = ({
|
||||
<Table.Tr key={func.id}>
|
||||
<Table.Td>
|
||||
<Text fw={500}>{func.name}</Text>
|
||||
<Text size="xs" c="dimmed">{func.handler}</Text>
|
||||
<Text size="xs" c="dimmed">{func.description || ''}</Text>
|
||||
</Table.Td>
|
||||
<Table.Td>
|
||||
<Badge color={getRuntimeColor(func.runtime)} variant="light">
|
||||
@ -201,33 +223,28 @@ export const FunctionList: React.FC<FunctionListProps> = ({
|
||||
</Table.Td>
|
||||
<Table.Td>
|
||||
<Text size="sm" c="dimmed">
|
||||
{func.image}
|
||||
{func.image || ''}
|
||||
</Text>
|
||||
</Table.Td>
|
||||
<Table.Td>
|
||||
<Text size="sm">{func.memory} MB</Text>
|
||||
<Text size="sm">{func.memoryLimit || 'N/A'} MB</Text>
|
||||
</Table.Td>
|
||||
<Table.Td>
|
||||
<Text size="sm">{func.timeout}</Text>
|
||||
<Text size="sm">{func.timeout || 'N/A'}</Text>
|
||||
</Table.Td>
|
||||
<Table.Td>
|
||||
<Text size="sm">N/A</Text>
|
||||
</Table.Td>
|
||||
<Table.Td>
|
||||
<Text size="sm">
|
||||
{func.owner?.name || 'Unknown'}
|
||||
{func.owner?.type && (
|
||||
<Text size="xs" c="dimmed">({func.owner.type})</Text>
|
||||
)}
|
||||
</Text>
|
||||
</Table.Td>
|
||||
<Table.Td>
|
||||
<Text size="sm">
|
||||
{func.created_at ? new Date(func.created_at).toLocaleDateString() : 'N/A'}
|
||||
{func.createdAt ? new Date(func.createdAt).toLocaleDateString() : 'N/A'}
|
||||
</Text>
|
||||
</Table.Td>
|
||||
<Table.Td>
|
||||
<Group gap="xs">
|
||||
<Tooltip label="Execute Function">
|
||||
<ActionIcon
|
||||
variant="light"
|
||||
variant="subtle"
|
||||
color="green"
|
||||
size="sm"
|
||||
onClick={() => onExecuteFunction(func)}
|
||||
@ -237,7 +254,7 @@ export const FunctionList: React.FC<FunctionListProps> = ({
|
||||
</Tooltip>
|
||||
<Menu position="bottom-end">
|
||||
<Menu.Target>
|
||||
<ActionIcon variant="light" size="sm">
|
||||
<ActionIcon variant="subtle" size="sm">
|
||||
<IconDots size={16} />
|
||||
</ActionIcon>
|
||||
</Menu.Target>
|
||||
@ -269,7 +286,8 @@ export const FunctionList: React.FC<FunctionListProps> = ({
|
||||
))}
|
||||
</Table.Tbody>
|
||||
</Table>
|
||||
</Card>
|
||||
)}
|
||||
</Paper>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
@ -75,16 +75,16 @@ services:
|
||||
- ./migrations:/app/migrations:ro,Z
|
||||
restart: unless-stopped
|
||||
|
||||
frontend:
|
||||
build:
|
||||
context: ./kms-frontend
|
||||
dockerfile: Dockerfile
|
||||
container_name: kms-frontend
|
||||
ports:
|
||||
- "3000:80"
|
||||
networks:
|
||||
- kms-network
|
||||
restart: unless-stopped
|
||||
# frontend:
|
||||
# build:
|
||||
# context: ./kms-frontend
|
||||
# dockerfile: Dockerfile
|
||||
# container_name: kms-frontend
|
||||
# ports:
|
||||
# - "3000:80"
|
||||
# networks:
|
||||
# - kms-network
|
||||
# restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
|
||||
Reference in New Issue
Block a user