From 397ceff8d5960bc4514540d841bb94d8e148a6b9 Mon Sep 17 00:00:00 2001 From: Duc Trung LE Date: Tue, 16 Jan 2024 16:43:19 +0100 Subject: [PATCH] Add create new server button --- frontend/src/environments/EnvironmentList.tsx | 31 +++++-- frontend/src/servers/App.tsx | 6 +- frontend/src/servers/NewServerDialog.tsx | 82 +++++++++++++++++++ frontend/src/servers/RemoveServerButton.tsx | 46 +++++++++++ frontend/src/servers/ServersList.tsx | 44 +++++----- frontend/src/servers/main.tsx | 2 +- 6 files changed, 180 insertions(+), 31 deletions(-) create mode 100644 frontend/src/servers/NewServerDialog.tsx create mode 100644 frontend/src/servers/RemoveServerButton.tsx diff --git a/frontend/src/environments/EnvironmentList.tsx b/frontend/src/environments/EnvironmentList.tsx index db55a9b..2ae5310 100644 --- a/frontend/src/environments/EnvironmentList.tsx +++ b/frontend/src/environments/EnvironmentList.tsx @@ -1,5 +1,5 @@ import { IconButton } from '@mui/material'; -import { DataGrid, GridColDef } from '@mui/x-data-grid'; +import { DataGrid, GridColDef, GridRowSelectionModel } from '@mui/x-data-grid'; import { IEnvironmentData } from './types'; import { memo, useMemo } from 'react'; import CheckIcon from '@mui/icons-material/Check'; @@ -84,8 +84,13 @@ const columns: GridColDef[] = [ export interface IEnvironmentListProps { images: IEnvironmentData[]; - default_cpu_limit: string; - default_mem_limit: string; + default_cpu_limit?: string; + default_mem_limit?: string; + hideRemoveButton?: boolean; + pageSize?: number; + selectable?: boolean; + rowSelectionModel?: GridRowSelectionModel; + setRowSelectionModel?: (selected: GridRowSelectionModel) => void; } function _EnvironmentList(props: IEnvironmentListProps) { @@ -95,12 +100,11 @@ function _EnvironmentList(props: IEnvironmentListProps) { newItem.cpu_limit = newItem.cpu_limit.length > 0 ? newItem.cpu_limit - : props.default_cpu_limit; + : props.default_cpu_limit ?? '2'; newItem.mem_limit = newItem.mem_limit.length > 0 ? newItem.mem_limit - : props.default_mem_limit; - // newItem.status = 'building'; + : props.default_mem_limit ?? '2'; return newItem; }); }, [props]); @@ -113,12 +117,21 @@ function _EnvironmentList(props: IEnvironmentListProps) { initialState={{ pagination: { paginationModel: { - pageSize: 100 + pageSize: props.pageSize ?? 100 } } }} - pageSizeOptions={[100]} - disableRowSelectionOnClick + pageSizeOptions={[props.pageSize ?? 100]} + disableRowSelectionOnClick={!Boolean(props.selectable)} + sx={{ + '& .MuiDataGrid-virtualScroller::-webkit-scrollbar': { + overflow: rows.length > 0 ? 'auto' : 'hidden' + } + }} + columnVisibilityModel={{ remove: !Boolean(props.hideRemoveButton) }} + checkboxSelection={Boolean(props.selectable)} + rowSelectionModel={props.rowSelectionModel} + onRowSelectionModelChange={props.setRowSelectionModel} /> ); diff --git a/frontend/src/servers/App.tsx b/frontend/src/servers/App.tsx index a8ee0e2..baf2149 100644 --- a/frontend/src/servers/App.tsx +++ b/frontend/src/servers/App.tsx @@ -8,8 +8,11 @@ import { AxiosContext } from '../common/AxiosContext'; import { useMemo } from 'react'; import { AxiosClient } from '../common/axiosclient'; import { ServerList } from './ServersList'; +import { NewServerDialog } from './NewServerDialog'; +import { IEnvironmentData } from '../environments/types'; export interface IAppProps { + images: IEnvironmentData[] server_data: IServerData[]; allow_named_servers: boolean; named_server_limit_per_user: number; @@ -22,12 +25,13 @@ export default function App(props: IAppProps) { return new AxiosClient({ baseUrl, xsrfToken }); }, []); console.log('props', props); - + return ( + diff --git a/frontend/src/servers/NewServerDialog.tsx b/frontend/src/servers/NewServerDialog.tsx new file mode 100644 index 0000000..93a1529 --- /dev/null +++ b/frontend/src/servers/NewServerDialog.tsx @@ -0,0 +1,82 @@ +import { Box, Button, DialogContentText } from '@mui/material'; +import Dialog from '@mui/material/Dialog'; +import DialogActions from '@mui/material/DialogActions'; +import DialogContent from '@mui/material/DialogContent'; +import DialogTitle from '@mui/material/DialogTitle'; +import { Fragment, memo, useCallback, useState } from 'react'; + +// import { useAxios } from '../common/AxiosContext'; +import { IEnvironmentData } from '../environments/types'; +import { EnvironmentList } from '../environments/EnvironmentList'; +import { GridRowSelectionModel } from '@mui/x-data-grid'; + +export interface INewServerDialogProps { + images: IEnvironmentData[]; +} + +function _NewServerDialog(props: INewServerDialogProps) { + // const axios = useAxios(); + const [open, setOpen] = useState(false); + const handleOpen = () => { + setOpen(true); + }; + const handleClose = ( + event?: any, + reason?: 'backdropClick' | 'escapeKeyDown' + ) => { + if (reason && reason === 'backdropClick') { + return; + } + setOpen(false); + }; + + const [rowSelectionModel, setRowSelectionModel] = + useState([]); + const updateSelectedRow = useCallback( + (selected: GridRowSelectionModel) => { + if (selected.length > 1) { + setRowSelectionModel([selected[selected.length - 1]]); + } else { + setRowSelectionModel(selected); + } + }, + [setRowSelectionModel] + ); + return ( + + + + + + Server Options + + Select an environment + + + + + + + + + ); +} + +export const NewServerDialog = memo(_NewServerDialog); diff --git a/frontend/src/servers/RemoveServerButton.tsx b/frontend/src/servers/RemoveServerButton.tsx new file mode 100644 index 0000000..1388d9d --- /dev/null +++ b/frontend/src/servers/RemoveServerButton.tsx @@ -0,0 +1,46 @@ +import { Typography } from '@mui/material'; +import Box from '@mui/material/Box'; +import { memo, useCallback } from 'react'; + +import { useAxios } from '../common/AxiosContext'; +import { ButtonWithConfirm } from '../common/ButtonWithConfirm'; +import { API_PREFIX } from './types'; + +interface IRemoveServerButton { + user: string; + server: string; +} + +function _RemoveServerButton(props: IRemoveServerButton) { + const axios = useAxios(); + + const removeEnv = useCallback(async () => { + const response = await axios.request({ + method: 'delete', + path: API_PREFIX, + data: { name: props.server } + }); + if (response?.status === 'ok') { + window.location.reload(); + } else { + } + }, [props.server, axios]); + + return ( + + + Are you sure you want to stop the following server? + +
{props.server}
+ + } + action={removeEnv} + /> + ); +} + +export const RemoveServerButton = memo(_RemoveServerButton); diff --git a/frontend/src/servers/ServersList.tsx b/frontend/src/servers/ServersList.tsx index 3eb3f03..0d0dece 100644 --- a/frontend/src/servers/ServersList.tsx +++ b/frontend/src/servers/ServersList.tsx @@ -4,6 +4,8 @@ import { memo, useMemo } from 'react'; import { Box } from '@mui/system'; import { IServerData } from './types'; import { formatTime } from '../common/utils'; +import { RemoveServerButton } from './RemoveServerButton'; +import { Button } from '@mui/material'; const columns: GridColDef[] = [ { @@ -12,43 +14,40 @@ const columns: GridColDef[] = [ flex: 1 }, { - field: 'url', - headerName: 'URL', - flex: 1, - renderCell: params => { - return ( - - {params.value} - - ); - } + field: 'image', + headerName: 'Image', + flex: 1 }, { field: 'last_activity', headerName: 'Last activity', - flex: 1, - maxWidth: 150 - }, - { - field: 'image', - headerName: 'Image', - flex:1, + width: 150 }, { field: 'status', headerName: '', - width: 150, + width: 125, filterable: false, sortable: false, hideable: false, + renderCell: params => { + return ; + } }, { field: 'action', headerName: '', - width: 100, + width: 125, filterable: false, sortable: false, - hideable: false + hideable: false, + renderCell: params => { + return ( + + ); + } } ]; @@ -80,6 +79,11 @@ function _ServerList(props: IServerListProps) { }} pageSizeOptions={[100]} disableRowSelectionOnClick + sx={{ + '& .MuiDataGrid-virtualScroller::-webkit-scrollbar': { + overflow: rows.length > 0 ? 'auto' : 'hidden' + } + }} /> ); diff --git a/frontend/src/servers/main.tsx b/frontend/src/servers/main.tsx index 7b5afcd..5a23a00 100644 --- a/frontend/src/servers/main.tsx +++ b/frontend/src/servers/main.tsx @@ -10,10 +10,10 @@ import App, { IAppProps } from './App'; const rootElement = document.getElementById('servers-root'); const root = createRoot(rootElement!); -console.log('AAAAAAAAAA'); const dataElement = document.getElementById('tljh-page-data'); let configData: IAppProps = { + images: [], server_data: [], allow_named_servers: false, named_server_limit_per_user: 0