Skip to content

Commit

Permalink
Add new server button
Browse files Browse the repository at this point in the history
  • Loading branch information
trungleduc committed Jan 16, 2024
1 parent 397ceff commit 0fc2311
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 32 deletions.
5 changes: 4 additions & 1 deletion frontend/src/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ export function encodeUriComponents(uri: string): string {
}

export function formatTime(time: string): string {
if(!time || time.length === 0){
return 'unknown'
}
const units: { [key: string]: number } = {
year: 24 * 60 * 60 * 1000 * 365,
month: (24 * 60 * 60 * 1000 * 365) / 12,
Expand All @@ -28,5 +31,5 @@ export function formatTime(time: string): string {
return rtf.format(Math.round(elapsed / units[u]), u as any);
}
}
return '';
return 'unknown';
}
13 changes: 12 additions & 1 deletion frontend/src/environments/EnvironmentList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const columns: GridColDef[] = [
flex: 1,
renderCell: params => {
return (
<a href={params.value} target="_blank">
<a title={params.value} href={params.value} target="_blank">
{params.value}
</a>
);
Expand Down Expand Up @@ -132,6 +132,17 @@ function _EnvironmentList(props: IEnvironmentListProps) {
checkboxSelection={Boolean(props.selectable)}
rowSelectionModel={props.rowSelectionModel}
onRowSelectionModelChange={props.setRowSelectionModel}
density='compact'
autoHeight
slots={{
noRowsOverlay: () => {
return (
<Box sx={{ textAlign: 'center', padding: '25px' }}>
No environment available
</Box>
);
}
}}
/>
</Box>
);
Expand Down
22 changes: 14 additions & 8 deletions frontend/src/environments/NewEnvironmentDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import { Box, Button, Typography } 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 { OutlinedTextFieldProps } from '@mui/material/TextField';
import {
Box,
Button,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
Divider,
OutlinedTextFieldProps,
Typography,
} from '@mui/material';
import { Fragment, memo, useCallback, useMemo, useState } from 'react';
import Divider from '@mui/material/Divider';
import { SmallTextField } from '../common/SmallTextField';

import { useAxios } from '../common/AxiosContext';
import { SmallTextField } from '../common/SmallTextField';
import { API_PREFIX } from './types';

export interface INewEnvironmentDialogProps {
default_cpu_limit: string;
default_mem_limit: string;
Expand Down
9 changes: 6 additions & 3 deletions frontend/src/servers/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { NewServerDialog } from './NewServerDialog';
import { IEnvironmentData } from '../environments/types';

export interface IAppProps {
images: IEnvironmentData[]
images: IEnvironmentData[];
server_data: IServerData[];
allow_named_servers: boolean;
named_server_limit_per_user: number;
Expand All @@ -25,13 +25,16 @@ export default function App(props: IAppProps) {
return new AxiosClient({ baseUrl, xsrfToken });
}, []);
console.log('props', props);

return (
<ThemeProvider theme={customTheme}>
<AxiosContext.Provider value={axios}>
<ScopedCssBaseline>
<Stack sx={{ padding: 1 }} spacing={1}>
<NewServerDialog images={props.images}/>
<NewServerDialog
images={props.images}
allowNamedServers={props.allow_named_servers}
/>
<ServerList servers={props.server_data} />
</Stack>
</ScopedCssBaseline>
Expand Down
50 changes: 41 additions & 9 deletions frontend/src/servers/NewServerDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,37 @@
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 {
Box,
Button,
Dialog,
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
OutlinedTextFieldProps
} from '@mui/material';
import { GridRowSelectionModel } from '@mui/x-data-grid';
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';
import { IEnvironmentData } from '../environments/types';
import { SmallTextField } from '../common/SmallTextField';

// import { useAxios } from '../common/AxiosContext';
export interface INewServerDialogProps {
images: IEnvironmentData[];
allowNamedServers: boolean;
}

const commonInputProps: OutlinedTextFieldProps = {
autoFocus: true,
required: true,
margin: 'dense',
fullWidth: true,
variant: 'outlined'
};
function _NewServerDialog(props: INewServerDialogProps) {
// const axios = useAxios();
const [open, setOpen] = useState(false);
const [serverName, setServerName] = useState<string>('');
const handleOpen = () => {
setOpen(true);
};
Expand Down Expand Up @@ -52,6 +67,20 @@ function _NewServerDialog(props: INewServerDialogProps) {
<Dialog open={open} onClose={handleClose} fullWidth maxWidth={'md'}>
<DialogTitle>Server Options</DialogTitle>
<DialogContent>
{props.allowNamedServers && (
<Box sx={{ padding: 1 }}>
<SmallTextField
{...commonInputProps}
id="server_name"
name="server_name"
label="Server name"
type="string"
required={true}
onChange={e => setServerName(e.target.value)}
value={serverName}
/>
</Box>
)}
<DialogContentText>Select an environment</DialogContentText>
<EnvironmentList
images={props.images}
Expand All @@ -69,7 +98,10 @@ function _NewServerDialog(props: INewServerDialogProps) {
<Button
variant="contained"
color="primary"
disabled={rowSelectionModel.length === 0}
disabled={
rowSelectionModel.length === 0 ||
(serverName.length === 0 && props.allowNamedServers)
}
>
Create Server
</Button>
Expand Down
12 changes: 9 additions & 3 deletions frontend/src/servers/ServersList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,15 @@ function _ServerList(props: IServerListProps) {
}}
pageSizeOptions={[100]}
disableRowSelectionOnClick
sx={{
'& .MuiDataGrid-virtualScroller::-webkit-scrollbar': {
overflow: rows.length > 0 ? 'auto' : 'hidden'
density='compact'
autoHeight
slots={{
noRowsOverlay: () => {
return (
<Box sx={{ textAlign: 'center', padding: '25px' }}>
No servers are running
</Box>
);
}
}}
/>
Expand Down
33 changes: 26 additions & 7 deletions tljh_repo2docker/servers.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from inspect import isawaitable
from typing import Any, Dict
from jupyterhub.orm import Spawner
from jupyterhub.handlers.base import BaseHandler
from tornado import web

Expand All @@ -22,14 +24,9 @@ async def get(self):
server_data = []
for sp in named_spawners:
server_data.append(
{
"name": sp.name,
"url": user.server_url(sp.name),
"last_activity": sp.last_activity.isoformat() + "Z",
"user_options": sp.user_options,
}
self._spawner_to_server_data(sp, user)
)

print('@@@@@@@@@@@@@', server_data)
result = self.render_template(
"servers.html",
images=images,
Expand All @@ -43,3 +40,25 @@ async def get(self):
self.write(await result)
else:
self.write(result)

def _spawner_to_server_data(self, sp: Spawner, user: Any) -> Dict:
data = {
"name": sp.name,
}
try:
data["url"] = user.server_url(sp.name)
except Exception:
data["url"] = ""
try:
data["last_activity"] = sp.last_activity.isoformat() + "Z"
except Exception:
data["last_activity"] = ""

try:
if sp.user_options:
data["user_options"] = sp.user_options
else:
data["user_options"] = {}
except:
data["user_options"] = {}
return data

0 comments on commit 0fc2311

Please sign in to comment.