Skip to content

Commit

Permalink
Start new server
Browse files Browse the repository at this point in the history
  • Loading branch information
trungleduc committed Jan 17, 2024
1 parent 0fc2311 commit 4585624
Show file tree
Hide file tree
Showing 14 changed files with 110 additions and 34 deletions.
20 changes: 20 additions & 0 deletions frontend/src/common/JupyterhubContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { createContext, useContext } from 'react';

export interface IJupyterhubData {
baseUrl: string;
prefix: string;
user: string;
adminAccess: boolean;
xsrfToken: string;
}
export const JupyterhubContext = createContext<IJupyterhubData>({
baseUrl: '',
prefix: '',
user: '',
adminAccess: false,
xsrfToken: ''
});

export const useJupyterhub = () => {
return useContext(JupyterhubContext);
};
12 changes: 10 additions & 2 deletions frontend/src/common/axiosclient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import urlJoin from 'url-join';
import { encodeUriComponents } from './utils';
import axios, { AxiosInstance } from 'axios';

export const API_PREFIX = 'api';
export const SPAWN_PREFIX = 'spawn';
export class AxiosClient {
constructor(options: AxiosClient.IOptions) {
this._baseUrl = options.baseUrl ?? '';
Expand All @@ -13,13 +15,19 @@ export class AxiosClient {

async request<T = any>(args: {
method: 'get' | 'post' | 'put' | 'option' | 'delete';
prefix: 'api' | 'spawn';
path: string;
data?: { [key: string]: any };
query?: string;
data?: { [key: string]: any } | FormData;
}): Promise<T> {
const { method, path } = args;

const data = args.data ?? {};
let url = urlJoin('api', encodeUriComponents(path));
let url = urlJoin(args.prefix, encodeUriComponents(path));
if (args.query) {
const sep = url.indexOf('?') === -1 ? '?' : '&';
url = `${url}${sep}${args.query}`;
}
if (this._xsrfToken) {
const sep = url.indexOf('?') === -1 ? '?' : '&';
url = `${url}${sep}_xsrf=${this._xsrfToken}`;
Expand Down
9 changes: 5 additions & 4 deletions frontend/src/environments/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,20 @@ import { NewEnvironmentDialog } from './NewEnvironmentDialog';
import { AxiosContext } from '../common/AxiosContext';
import { useMemo } from 'react';
import { AxiosClient } from '../common/axiosclient';
import { useJupyterhub } from '../common/JupyterhubContext';

export interface IAppProps {
images: IEnvironmentData[];
default_cpu_limit: string;
default_mem_limit: string;
}
export default function App(props: IAppProps) {
const jhData = useJupyterhub();
const axios = useMemo(() => {
const jhData = (window as any).jhdata;
const baseUrl = jhData.base_url;
const xsrfToken = jhData.xsrf_token;
const baseUrl = jhData.baseUrl;
const xsrfToken = jhData.xsrfToken;
return new AxiosClient({ baseUrl, xsrfToken });
}, []);
}, [jhData]);
return (
<ThemeProvider theme={customTheme}>
<AxiosContext.Provider value={axios}>
Expand Down
6 changes: 4 additions & 2 deletions frontend/src/environments/NewEnvironmentDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import { Fragment, memo, useCallback, useMemo, useState } from 'react';

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

export interface INewEnvironmentDialogProps {
default_cpu_limit: string;
Expand Down Expand Up @@ -98,7 +99,8 @@ function _NewEnvironmentDialog(props: INewEnvironmentDialogProps) {
data.password = data.password ?? '';
const response = await axios.request({
method: 'post',
path: API_PREFIX,
prefix: API_PREFIX,
path: ENV_PREFIX,
data
});
if (response?.status === 'ok') {
Expand Down
6 changes: 4 additions & 2 deletions frontend/src/environments/RemoveEnvironmentButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { memo, useCallback } from 'react';

import { useAxios } from '../common/AxiosContext';
import { ButtonWithConfirm } from '../common/ButtonWithConfirm';
import { API_PREFIX } from './types';
import { ENV_PREFIX } from './types';
import { API_PREFIX } from '../common/axiosclient';

interface IRemoveEnvironmentButton {
name: string;
Expand All @@ -17,7 +18,8 @@ function _RemoveEnvironmentButton(props: IRemoveEnvironmentButton) {
const removeEnv = useCallback(async () => {
const response = await axios.request({
method: 'delete',
path: API_PREFIX,
prefix: API_PREFIX,
path: ENV_PREFIX,
data: { name: props.image }
});
if (response?.status === 'ok') {
Expand Down
16 changes: 14 additions & 2 deletions frontend/src/environments/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import '@fontsource/roboto/700.css';

import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';

import { JupyterhubContext } from '../common/JupyterhubContext';
import App, { IAppProps } from './App';

const rootElement = document.getElementById('environments-root');
Expand All @@ -19,9 +19,21 @@ let configData: IAppProps = {
if (dataElement) {
configData = JSON.parse(dataElement.textContent || '') as IAppProps;
}
const jhData = (window as any).jhdata;
const { base_url, xsrf_token, user, prefix, admin_access } = jhData;

root.render(
<StrictMode>
<App {...configData} />
<JupyterhubContext.Provider
value={{
baseUrl: base_url,
xsrfToken: xsrf_token,
user,
prefix,
adminAccess: admin_access
}}
>
<App {...configData} />
</JupyterhubContext.Provider>
</StrictMode>
);
2 changes: 1 addition & 1 deletion frontend/src/environments/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const API_PREFIX = 'environments';
export const ENV_PREFIX = 'environments';
export interface IEnvironmentData {
image_name: string;
cpu_limit: string;
Expand Down
9 changes: 5 additions & 4 deletions frontend/src/servers/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { AxiosClient } from '../common/axiosclient';
import { ServerList } from './ServersList';
import { NewServerDialog } from './NewServerDialog';
import { IEnvironmentData } from '../environments/types';
import { useJupyterhub } from '../common/JupyterhubContext';

export interface IAppProps {
images: IEnvironmentData[];
Expand All @@ -18,12 +19,12 @@ export interface IAppProps {
named_server_limit_per_user: number;
}
export default function App(props: IAppProps) {
const jhData = useJupyterhub();
const axios = useMemo(() => {
const jhData = (window as any).jhdata;
const baseUrl = jhData.base_url;
const xsrfToken = jhData.xsrf_token;
const baseUrl = jhData.baseUrl;
const xsrfToken = jhData.xsrfToken;
return new AxiosClient({ baseUrl, xsrfToken });
}, []);
}, [jhData]);
console.log('props', props);

return (
Expand Down
22 changes: 20 additions & 2 deletions frontend/src/servers/NewServerDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import { EnvironmentList } from '../environments/EnvironmentList';
import { IEnvironmentData } from '../environments/types';
import { SmallTextField } from '../common/SmallTextField';

// import { useAxios } from '../common/AxiosContext';
import { useAxios } from '../common/AxiosContext';
import { SPAWN_PREFIX } from '../common/axiosclient';
import { useJupyterhub } from '../common/JupyterhubContext';
export interface INewServerDialogProps {
images: IEnvironmentData[];
allowNamedServers: boolean;
Expand All @@ -29,7 +31,8 @@ const commonInputProps: OutlinedTextFieldProps = {
variant: 'outlined'
};
function _NewServerDialog(props: INewServerDialogProps) {
// const axios = useAxios();
const axios = useAxios();
const jhData = useJupyterhub();
const [open, setOpen] = useState(false);
const [serverName, setServerName] = useState<string>('');
const handleOpen = () => {
Expand Down Expand Up @@ -57,6 +60,20 @@ function _NewServerDialog(props: INewServerDialogProps) {
},
[setRowSelectionModel]
);

const createServer = useCallback(async () => {
const imageName = props.images[rowSelectionModel[0] as number].image_name;
console.log('serverName', serverName, imageName);
const data = new FormData();
data.append('image', imageName);
const res = await axios.request({
method: 'post',
prefix: SPAWN_PREFIX,
path: `${jhData.user}/${serverName}`,
data
});
console.log('AAAAA', res)
}, [serverName, rowSelectionModel, props.images]);
return (
<Fragment>
<Box sx={{ display: 'flex', flexDirection: 'row-reverse' }}>
Expand Down Expand Up @@ -102,6 +119,7 @@ function _NewServerDialog(props: INewServerDialogProps) {
rowSelectionModel.length === 0 ||
(serverName.length === 0 && props.allowNamedServers)
}
onClick={createServer}
>
Create Server
</Button>
Expand Down
22 changes: 12 additions & 10 deletions frontend/src/servers/RemoveServerButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,27 @@ import { memo, useCallback } from 'react';

import { useAxios } from '../common/AxiosContext';
import { ButtonWithConfirm } from '../common/ButtonWithConfirm';
import { API_PREFIX } from './types';
import { useJupyterhub } from '../common/JupyterhubContext';
import { API_PREFIX } from '../common/axiosclient';

interface IRemoveServerButton {
user: string;
server: string;
}

function _RemoveServerButton(props: IRemoveServerButton) {
const axios = useAxios();

const jhData = useJupyterhub();
const removeEnv = useCallback(async () => {
const response = await axios.request({
method: 'delete',
path: API_PREFIX,
data: { name: props.server }
});
if (response?.status === 'ok') {
try {
await axios.request({
method: 'delete',
prefix: API_PREFIX,
path: `users/${jhData.user}/servers/${props.server}`,
data: { remove: true }
});
window.location.reload();
} else {
} catch (e: any) {
console.error(e);
}
}, [props.server, axios]);

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/servers/ServersList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const columns: GridColDef[] = [
sortable: false,
hideable: false,
renderCell: params => {
return <RemoveServerButton server={params.row.name} user={'alice'} />;
return <RemoveServerButton server={params.row.name}/>;
}
},
{
Expand Down
16 changes: 14 additions & 2 deletions frontend/src/servers/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import '@fontsource/roboto/700.css';
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';

import { JupyterhubContext } from '../common/JupyterhubContext';
import App, { IAppProps } from './App';

const rootElement = document.getElementById('servers-root');
Expand All @@ -21,9 +22,20 @@ let configData: IAppProps = {
if (dataElement) {
configData = JSON.parse(dataElement.textContent || '') as IAppProps;
}

const jhData = (window as any).jhdata;
const { base_url, xsrf_token, user, prefix, admin_access } = jhData;
root.render(
<StrictMode>
<App {...configData} />
<JupyterhubContext.Provider
value={{
baseUrl: base_url,
xsrfToken: xsrf_token,
user,
prefix,
adminAccess: admin_access
}}
>
<App {...configData} />
</JupyterhubContext.Provider>
</StrictMode>
);
1 change: 0 additions & 1 deletion frontend/src/servers/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export const API_PREFIX = 'spawn';
export interface IServerData {
name: string;
url: string;
Expand Down
1 change: 0 additions & 1 deletion tljh_repo2docker/servers.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ async def get(self):
server_data.append(
self._spawner_to_server_data(sp, user)
)
print('@@@@@@@@@@@@@', server_data)
result = self.render_template(
"servers.html",
images=images,
Expand Down

0 comments on commit 4585624

Please sign in to comment.