Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add navigation bar for the kurtosis frontend #940

Merged
merged 10 commits into from Jul 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 6 additions & 15 deletions engine/frontend/src/App.js
@@ -1,23 +1,14 @@
import './App.css';
import Home from './components/Home';
import Services from "./components/Services"
import ServiceInfo from "./components/ServiceInfo"
import CreateEnclave from './components/CreateEnclave';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import Home from './component/Home';
Peeeekay marked this conversation as resolved.
Show resolved Hide resolved
import { BrowserRouter as Router } from 'react-router-dom';

const App = () => {
return (
<Router>
<div className="h-screen w-screen">
<Routes>
<Route exact path="/" element={<Home />} />
<Route path="/create" element={<CreateEnclave />} />
<Route path="/enclaves/:name/services/:uuid" element={<ServiceInfo/>} />
<Route path="/enclaves/:name" element={<Services/>} />
</Routes>
</div>
</Router>

<Router>
<Home />
</Router>
</div>
)
}

Expand Down
25 changes: 19 additions & 6 deletions engine/frontend/src/api/container.js
Expand Up @@ -4,14 +4,15 @@ import {ApiContainerServicePromiseClient} from 'kurtosis-sdk/build/core/kurtosis

const TransportProtocolEnum = ["tcp", "sctp", "udp"];

export const runStarlarkPackage = async (url, packageId) => {
export const runStarlarkPackage = async (url, packageId, args) => {
console.log(typeof args)
const containerClient = new ApiContainerServicePromiseClient(url);
const runStarlarkPackageArgs = new RunStarlarkPackageArgs();

runStarlarkPackageArgs.setDryRun(false);
runStarlarkPackageArgs.setRemote(true);
runStarlarkPackageArgs.setPackageId(packageId);
runStarlarkPackageArgs.setSerializedParams("{}")
runStarlarkPackageArgs.setSerializedParams(args)
const stream = containerClient.runStarlarkPackage(runStarlarkPackageArgs, null);
return stream;
}
Expand All @@ -22,12 +23,24 @@ const getDataFromApiContainer = async (request, process) => {
}

export const getEnclaveInformation = async (url) => {
const containerClient = new ApiContainerServicePromiseClient(url);
console.log("url ", url)
if (url === "") {
return {
services: [],
artifacts: []
}
}

const containerClient = new ApiContainerServicePromiseClient(url);
const makeGetServiceRequest = async () => {
const serviceArgs = new GetServicesArgs();
const responseFromGrpc = await containerClient.getServices(serviceArgs, null)
return responseFromGrpc.toObject()
try {
const serviceArgs = new GetServicesArgs();
const responseFromGrpc = await containerClient.getServices(serviceArgs, null)
console.log(responseFromGrpc.toObject())
return responseFromGrpc.toObject()
} catch (error) {
return {serviceInfoMap:[]}
}
}

const makeFileArtifactRequest = async () => {
Expand Down
4 changes: 2 additions & 2 deletions engine/frontend/src/api/enclave.js
Expand Up @@ -57,7 +57,7 @@ export const createEnclave = async () => {
return {enclave, apiClient}
}

export const runStarlark = async(apiClient, packageId) => {
const stream = await runStarlarkPackage(apiClient, packageId)
export const runStarlark = async(apiClient, packageId, args) => {
const stream = await runStarlarkPackage(apiClient, packageId, args)
return stream;
}
28 changes: 28 additions & 0 deletions engine/frontend/src/component/CreateEnclave.js
@@ -0,0 +1,28 @@
import React, { useState} from 'react';

import {CreateEnclaveModal} from "./CreateEnclaveModal";
import {CreateEnclaveView} from "./CreateEnclaveView";
import { Route, Routes, useNavigate } from 'react-router-dom';

const CreateEnclave = () => {
const navigate = useNavigate()
const [name, setName] = useState('');
const [args, setArgs] = useState('{}')
const [enclaveInfo, setEnlaveInfo] = useState(null);

const handleModalSubmit = (enclaveInfo) => {
setEnlaveInfo(enclaveInfo)
navigate("/enclave/progress")
}

return (
<div className='h-full w-full flex'>
<Routes>
<Route path="/create" element={<CreateEnclaveModal name={name} setName={setName} args={args} setArgs={setArgs} handleSubmit={handleModalSubmit}/>}/>
<Route path="/progress" element={<CreateEnclaveView args={args} packageId={name} enclaveInfo={enclaveInfo}/>} />
</Routes>
</div>
)
}

export default CreateEnclave;
Peeeekay marked this conversation as resolved.
Show resolved Hide resolved
@@ -1,39 +1,50 @@
import React, { useState } from 'react';
import React, {useState}from 'react';
import {createEnclave} from "../api/enclave";

export const CreateEnclaveModal = ({handleSubmit, name, setName}) => {
export const CreateEnclaveModal = ({handleSubmit, name, setName, args, setArgs}) => {
const [jsonError, setJsonError] = useState("")

const handleFormSubmit = (e) => {
e.preventDefault();
const fetch = async () => {
const enclaveInfo = await createEnclave();
handleSubmit(enclaveInfo);
}
fetch();

try {
setJsonError("")
JSON.parse(args)
fetch();
} catch (error) {
setJsonError("Invalid Json")
}
};



return (
<div className="flex justify-center items-center h-full">
<form onSubmit={handleFormSubmit} className="bg-gray-100 p-6 rounded-lg shadow-md">
<div className="flex justify-center w-full h-fit m-14">
<form onSubmit={handleFormSubmit} className="bg-gray-100 p-6 rounded-lg shadow-md w-1/3">
<div className="text-center">
<h2 className="text-2xl mb-4">{name}</h2>
<label className="block mb-4">
Name:
<label className="block mb-4 text-2xl">
Package Id:
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
className="block w-full rounded-md border-gray-300 py-2 px-3 mt-1 focus:outline-none focus:ring-blue-500 focus:border-blue-500"
/>
</label>
{/* <label className="block mb-4">
Args (JSON format):
<label className="block mb-4">
Args: (Json)
<textarea
value={args}
onChange={(e) => setArgs(e.target.value)}
onChange={(e) => { setArgs(e.target.value); setJsonError("")}}
className="block w-full rounded-md border-gray-300 py-2 px-3 mt-1 resize-none focus:outline-none focus:ring-blue-500 focus:border-blue-500"
rows={4}
></textarea>
</label> */}
<p className='text-red-300 font-bold'>{jsonError}</p>
</label>
<button
type="submit"
className="bg-blue-500 text-white py-2 px-4 rounded-md hover:bg-blue-600 focus:outline-none focus:ring-blue-500 focus:ring-2 focus:ring-offset-2"
Expand Down
@@ -1,32 +1,38 @@
import { useEffect, useState } from "react";
import { LeftView } from "./LeftView";

import RightPanel from "./RightPanel";
import LeftPanel from "./LeftPanel";
import Heading from "./Heading";
import { LogView } from "./LogView";
import {useNavigate} from "react-router-dom";

import {useNavigate} from "react-router-dom";
import {runStarlark} from "../api/enclave";
import {getEnclaveInformation} from "../api/container";

const SERVICE_IS_ADDED = "added with service";

export const CreateEnclaveView = ({packageId, enclaveInfo}) => {
export const CreateEnclaveView = ({packageId, enclaveInfo, args}) => {
const navigate = useNavigate();
const [loading, setLoading] = useState(false)
const [logs, setLogs] = useState([])
const [enclave, setEnclave] = useState("")
const [services, setServices] = useState([])

const getServices = async (apiClient) => {
const {services} = await getEnclaveInformation(apiClient);
setServices(services)
const {services: newServices} = await getEnclaveInformation(apiClient);
if (newServices.length > services.length) {
setServices(newServices)
}
}

useEffect(() => {
setLoading(true)
let stream;
const fetch = async () => {
stream = await runStarlark(enclaveInfo.apiClient, packageId);
stream = await runStarlark(enclaveInfo.apiClient, packageId, args);
setEnclave(enclave);
stream.on("data", data => {
const result = data.toObject();
console.log(result);
if (result.instruction && result.instruction.executableInstruction) {
setLogs(logs => [...logs, result.instruction.executableInstruction])
}
Expand Down Expand Up @@ -59,7 +65,7 @@ export const CreateEnclaveView = ({packageId, enclaveInfo}) => {
});

stream.on("end", () => {
//navigate("/");
setLoading(false)
});
}

Expand All @@ -71,32 +77,40 @@ export const CreateEnclaveView = ({packageId, enclaveInfo}) => {
};
}, [packageId])

const renderServices = () => {
const handleServiceClick = (service) => {
navigate(`/enclaves/${enclaveInfo.enclave.name}/services/${service.uuid}`, {state: {services, selected: service}})
}

const renderServices = (services, handleClick) => {
return services.map(service => {
return (
<div
className={`cursor-default flex text-white items-center justify-center h-14 rounded-md border-4 bg-green-700`}
key={service.uuid}>
{service.name}
<div className={`flex items-center justify-center h-14 text-base bg-green-700`} key={service.name} onClick={()=>handleClick(service)}>
<div className='cursor-default text-lg text-white'> {service.name} </div>
</div>
)
})
)
})
}

return (
<div className="grid grid-cols-6 h-full w-full">
<LeftView
heading={"Services"}
renderList={() => renderServices()}
/>
<div className="col-span-5">
<div className='flex flex-col h-screen space-y-5'>
<div className="text-3xl text-center">
{enclaveInfo.enclave.name}
</div>
<LogView classAttr={"flex flex-col p-2 h-fit"} heading={"Starlark Logs"} logs={logs}/>
</div>
</div>
<div className="flex h-full w-full bg-white">
<div className="flex h-full">
<LeftPanel
home={false}
heading={"Services"}
isServiceInfo={true}
renderList={ ()=> renderServices(services, handleServiceClick)}
/>
<div className="flex h-full w-[calc(100vw-24rem)] flex-col space-y-5">
<div className='flex flex-col h-full space-y-1 bg-white'>
<LogView
heading={`Starlark Logs: ${enclaveInfo.enclave.name}`}
logs={logs}
size={"h-full"}
/>
</div>
</div>
<RightPanel home={false} isServiceInfo={true} enclaveName={enclaveInfo.enclave.name}/>
</div>
</div>
)
}