Skip to content

Commit

Permalink
list instances on vlab pages
Browse files Browse the repository at this point in the history
  • Loading branch information
gpelouze committed Sep 20, 2023
1 parent 9180b98 commit b8fdebc
Show file tree
Hide file tree
Showing 5 changed files with 210 additions and 57 deletions.
54 changes: 4 additions & 50 deletions vre-panel/components/VLabDescription.tsx
Original file line number Diff line number Diff line change
@@ -1,52 +1,11 @@
import React, {useEffect, useState} from "react";
import getConfig from "next/config";
import {JWT} from "next-auth/jwt";
import {VLab} from "../types/vlab";

type Props = {
slug: string | string[] | undefined,
isAuthenticated: boolean,
token: JWT,
vlab: VLab,
backendError: boolean,
}

const VLabDescription: React.FC<Props> = ({slug, isAuthenticated, token}) => {

const {publicRuntimeConfig} = getConfig()

const vlabPlaceholder = {
title: "Loading ..",
slug: "",
description: "Loading ..",
endpoint: ""
}

const [vlab, setVlab] = useState(vlabPlaceholder)
const [backendError, setBackendError] = useState(false)

const fetchVlab = async () => {

var requestOptions: RequestInit = {
method: "GET",
headers: {
"Authorization": "Bearer: " + token.accessToken
},
};

const apiUrl = `${window.location.origin}/${publicRuntimeConfig.apiBasePath}`
const res = await fetch(`${apiUrl}/vlabs/${slug}`, requestOptions);
try {
const dat = await res.json()
setVlab(dat)
} catch (e) {
console.log(e)
setBackendError(true)
}
}

useEffect(() => {
if (isAuthenticated) {
Promise.all([fetchVlab()])
}
}, [isAuthenticated]);
const VLabDescription: React.FC<Props> = ({vlab, backendError}) => {

return (
<div>
Expand All @@ -57,11 +16,6 @@ const VLabDescription: React.FC<Props> = ({slug, isAuthenticated, token}) => {
) : (
<>
<p className="text-4xl font-sans">{vlab.title}</p>
<a target="blank" href={vlab.endpoint}>
<button className="bg-primary hover:bg-primaryDark text-onPrimary font-bold py-2 px-4 rounded mt-5">
Launch
</button>
</a>
<p className="mt-5 text-justify">{vlab.description}</p>
</>
)}
Expand Down
140 changes: 140 additions & 0 deletions vre-panel/components/VLabInstances.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import React, {useEffect, useState} from "react";
import getConfig from "next/config";
import {JWT} from "next-auth/jwt";
import {VLab} from "../types/vlab";
import {useSession} from "next-auth/react";

type Props = {
vlab: VLab,
slug: string | string[] | undefined,
isAuthenticated: boolean,
token: JWT,
}

interface VLabInstance {
vlab: string,
username: string,
}

const VLabInstances: React.FC<Props> = ({vlab, slug, isAuthenticated, token}) => {

const {publicRuntimeConfig} = getConfig()

const session = useSession()

const [vlabInstances, setVlabInstances] = useState<Array<VLabInstance>>([])
const [backendError, setBackendError] = useState(false)
const [hideInstance, setHideInstance] = useState(false)

const registerInstance = async () => {
if (
hideInstance
|| (session.status != "authenticated")
) {
return
}

const username = session.data.user.name

const requestOptions: RequestInit = {
method: "POST",
headers: {
"Authorization": "Bearer: " + token.accessToken,
"Content-Type": "application/json",
},
body: JSON.stringify({
"vlab": slug,
"username": username,
}),
}

const apiUrl = `${window.location.origin}/${publicRuntimeConfig.apiBasePath}`
return fetch(`${apiUrl}/vlab_instances/`, requestOptions);
}

const fetchVlabInstances = async () => {

var requestOptions: RequestInit = {
method: "GET",
headers: {
"Authorization": "Bearer: " + token.accessToken
},
};

const apiUrl = `${window.location.origin}/${publicRuntimeConfig.apiBasePath}`
const res = await fetch(`${apiUrl}/vlab_instances/?vlab_slug=${slug}`, requestOptions);
try {
const dat = await res.json()
setVlabInstances(dat)
} catch (e) {
console.log(e)
setBackendError(true)
}
}

useEffect(() => {
if (isAuthenticated) {
Promise.all([fetchVlabInstances()])
}
}, [isAuthenticated]);

return (
<div className="space-y-4">
<p className="text-2xl font-sans">Instances</p>
{backendError || (
<>
<p>
{vlabInstances.length} instance{vlabInstances.length != 1 && "s"}
</p>
<ul
className="flex flex-wrap"
>
{vlabInstances.map((vlab_instance) => {
return (
<li
key={vlab_instance.username}
className="rounded-full m-1 px-2 bg-quinary text-onTertiary"
>
{vlab_instance.username}
</li>
)
})}
</ul>
<div className="space-y-4 pt-4">
<div className="space-x-2">
<input
type="checkbox"
name="hideInstance"
checked={hideInstance}
onChange={
(e) => {
setHideInstance(e.target.checked)
}
}
/>
<label className="text-sm">
Hide my instance from this list
</label>
</div>
<div>
<a
target="blank"
href={vlab.endpoint}
onClick={registerInstance}
>
<button
className="bg-primary hover:bg-primaryDark text-onPrimary font-bold py-2 px-4 rounded"
>
Launch my instance
</button>
</a>
</div>
</div>

</>
)}
</div>
)
}

export default VLabInstances
60 changes: 53 additions & 7 deletions vre-panel/pages/vlabs/[slug].tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import {getToken} from "next-auth/jwt";
import {useRouter} from "next/router";
import VLabDescription from "../../components/VLabDescription";
import React from "react";
import React, {useEffect, useState} from "react";
import VLAbAssets from "../../components/VLAbAssets";
import PageLayout from "../../components/PageLayout";
import useAuth from "../auth/useAuth";
import VLabInstances from "../../components/VLabInstances";
import getConfig from "next/config";
import {VLab} from "../../types/vlab";


interface VLabDetailsProps {
Expand All @@ -13,20 +16,63 @@ interface VLabDetailsProps {

const VLabDetails: React.FC<VLabDetailsProps> = ({token}) => {

const {publicRuntimeConfig} = getConfig()

const vlabPlaceholder: VLab = {
title: "Loading ..",
slug: "",
description: "Loading ..",
endpoint: ""
}

const isAuthenticated = useAuth(true);
const router = useRouter();
const {slug} = router.query;

const [vlab, setVlab] = useState(vlabPlaceholder)
const [backendError, setBackendError] = useState(false)

const fetchVlab = async () => {

var requestOptions: RequestInit = {
method: "GET",
headers: {
"Authorization": "Bearer: " + token.accessToken
},
};

const apiUrl = `${window.location.origin}/${publicRuntimeConfig.apiBasePath}`
const res = await fetch(`${apiUrl}/vlabs/${slug}`, requestOptions);
try {
const dat = await res.json()
setVlab(dat)
} catch (e) {
console.log(e)
setBackendError(true)
}
}

useEffect(() => {
if (isAuthenticated) {
Promise.all([fetchVlab()])
}
}, [isAuthenticated]);


return (
<PageLayout>

<div className="rounded shadow-lg bg-white p-8">
<VLabDescription slug={slug} isAuthenticated={isAuthenticated} token={token}/>
</div>
<div className="rounded shadow-lg bg-white p-8">
<VLabDescription vlab={vlab} backendError={backendError}/>
</div>

<div className="rounded shadow-lg bg-white p-8">
<VLabInstances vlab={vlab} slug={slug} isAuthenticated={isAuthenticated} token={token}/>
</div>

<div className="rounded shadow-lg bg-white p-8">
<VLAbAssets slug={slug} isAuthenticated={isAuthenticated} token={token}/>
</div>
<div className="rounded shadow-lg bg-white p-8">
<VLAbAssets slug={slug} isAuthenticated={isAuthenticated} token={token}/>
</div>

</PageLayout>
)
Expand Down
6 changes: 6 additions & 0 deletions vre-panel/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ module.exports = {
onSecondary: '#ffffff',
secondaryContainer: '#FFBD85',
onSecondaryContainer: '#000000',
tertiary: '#009138',
onTertiary: '#ffffff',
quaternary: '#F4992B',
onQuaternary: '#000000',
quinary: '#009399',
onQuinary: '#ffffff',
surface: '#ffffff',
onSurface: '#333333',
surfaceContainer: '#f2f2f2',
Expand Down
7 changes: 7 additions & 0 deletions vre-panel/types/vlab.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

export interface VLab {
title: string,
slug: string,
description: string,
endpoint: string,
}

0 comments on commit b8fdebc

Please sign in to comment.