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: implement minor emui feedback tweaks #1827

Merged
merged 9 commits into from
Nov 17, 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions enclave-manager/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@
"prebuild": "rm -rf ../../engine/server/webapp",
"clean": "rm -rf build",
"cleanInstall": "rm -rf node_modules; yarn install",
"start": "react-scripts start",
"start": "REACT_APP_VERSION=$(git fetch origin --tags -q && git describe --dirty --match '[0-9]*' --tags)-development react-scripts start",
"start:prod": "serve -s build",
"build": "react-scripts build",
"build": "REACT_APP_VERSION=$(git fetch origin --tags -q && git describe --dirty --match '[0-9]*' --tags) react-scripts build",
"postbuild": "cp -r build/ ../../engine/server/webapp",
"prettier": "prettier . --check",
"prettier:fix": "prettier . --write",
Expand Down
2 changes: 1 addition & 1 deletion enclave-manager/web/src/components/AppLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const AppLayout = ({ Nav, children }: AppLayoutProps) => {
<Flex
as="main"
w={"100%"}
h={"100%"}
minH={"calc(100vh - 40px)"}
justifyContent={"flex-start"}
p={"20px 40px 20px 112px"}
className={"app-container"}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const IntegerArgumentInput = (props: KurtosisArgumentTypeInputImplProps)
placeholder={props.placeholder}
width={props.width}
size={props.size || "lg"}
tabIndex={props.tabIndex}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type KurtosisArgumentTypeInputProps = {
disabled?: boolean;
width?: CSS.Property.Width;
size?: string;
tabIndex?: number;
};

export type KurtosisArgumentTypeInputImplProps = Omit<KurtosisArgumentTypeInputProps, "type" | "subType1" | "subType2">;
Expand All @@ -36,6 +37,7 @@ export const KurtosisArgumentTypeInput = ({
disabled,
width,
size,
tabIndex,
}: KurtosisArgumentTypeInputProps) => {
const childProps: KurtosisArgumentTypeInputImplProps = {
name,
Expand All @@ -45,6 +47,7 @@ export const KurtosisArgumentTypeInput = ({
disabled,
width,
size,
tabIndex,
};

switch (type) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const StringArgumentInput = (props: KurtosisArgumentTypeInputImplProps) =
placeholder={props.placeholder}
width={props.width}
size={props.size || "lg"}
tabIndex={props.tabIndex}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ export const LogViewer = ({
};

return (
<Flex flexDirection={"column"} gap={"32px"}>
<Flex flexDirection={"column"} position={"relative"} bg={"gray.800"}>
<Flex flexDirection={"column"} gap={"32px"} h={"100%"}>
<Flex flexDirection={"column"} position={"relative"} bg={"gray.800"} h={"100%"}>
{isDefined(ProgressWidget) && (
<Box
display={"inline-flex"}
Expand All @@ -82,7 +82,7 @@ export const LogViewer = ({
followOutput={automaticScroll}
atBottomStateChange={handleBottomStateChange}
isScrolling={setUserIsScrolling}
style={{ height: "660px" }}
style={{ height: "100%" }}
data={logLines.filter(({ message }) => isDefined(message))}
itemContent={(_, line) => <LogLine {...line} />}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import {
ModalHeader,
ModalOverlay,
Text,
Tooltip, useToast,
Tooltip,
useToast,
} from "@chakra-ui/react";
import { EnclaveMode } from "enclave-manager-sdk/build/engine_service_pb";
import { useMemo, useRef, useState } from "react";
Expand Down Expand Up @@ -168,7 +169,9 @@ export const ConfigureEnclaveModal = ({
}
} catch (err) {
toast({
title: `An error occurred while preparing data for running package. The package arguments were not proper JSON: ${stringifyError(err)}`,
title: `An error occurred while preparing data for running package. The package arguments were not proper JSON: ${stringifyError(
err,
)}`,
colorScheme: "red",
});
return;
Expand Down Expand Up @@ -277,7 +280,7 @@ export const ConfigureEnclaveModal = ({
<CopyButton contentName={"url"} valueToCopy={getLinkToCurrentConfig} text={"Copy link"} />
</Tooltip>
</Flex>
<KurtosisArgumentFormControl name={"enclaveName"} label={"Enclave name"} type={"string"}>
<KurtosisArgumentFormControl name={"enclaveName"} label={"Enclave name"} type={"text"}>
<StringArgumentInput
name={"enclaveName"}
disabled={isDefined(existingEnclave)}
Expand All @@ -286,6 +289,7 @@ export const ConfigureEnclaveModal = ({
return `The enclave name must match ${allowedEnclaveNamePattern}`;
}
}}
tabIndex={1}
/>
</KurtosisArgumentFormControl>
{kurtosisPackage.args.map((arg, i) => (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Button, Tooltip } from "@chakra-ui/react";
import { useEffect, useState } from "react";
import { useState } from "react";
import { FiTrash2 } from "react-icons/fi";
import { useNavigate } from "react-router-dom";
import { useEmuiAppContext } from "../../../emui/EmuiAppContext";
Expand All @@ -11,28 +11,15 @@ type DeleteEnclavesButtonProps = {
};

export const DeleteEnclavesButton = ({ enclaves }: DeleteEnclavesButtonProps) => {
const { destroyEnclave } = useEmuiAppContext();
const { destroyEnclaves } = useEmuiAppContext();
const navigator = useNavigate();

const [showModal, setShowModal] = useState(false);
const [isLoading, setIsLoading] = useState(false);

const enclaveUUIDsKey = enclaves.map(({ enclaveUuid }) => enclaveUuid).join(",");

useEffect(
() => {
setIsLoading(false);
setShowModal(false);
},
// These deps are defined this way to detect whether or not the enclaves in props are actually different
[enclaveUUIDsKey],
);

const handleDelete = async () => {
setIsLoading(true);
for (const enclaveUUID of enclaves.map(({ enclaveUuid }) => enclaveUuid)) {
await destroyEnclave(enclaveUUID);
}
await destroyEnclaves(enclaves.map(({ enclaveUuid }) => enclaveUuid));
navigator("/enclaves");
setIsLoading(false);
setShowModal(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const DownloadFileArtifactButton = ({ file, enclave }: DownloadFileButton
setIsLoading(true);
// todo: get tgz download instead
const fileParts = await kurtosisClient.downloadFilesArtifact(enclave, file);
const writableStream = streamsaver.createWriteStream(`${enclave.name}-${file.fileName}.tgz`);
const writableStream = streamsaver.createWriteStream(`${enclave.name}--${file.fileName}.tgz`);
const writer = writableStream.getWriter();

for await (const part of fileParts) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Tag } from "@chakra-ui/react";
import { Tag, Tooltip } from "@chakra-ui/react";
import { EnclaveContainersStatus } from "enclave-manager-sdk/build/engine_service_pb";

export function enclaveStatusToString(status: EnclaveContainersStatus) {
Expand All @@ -12,31 +12,31 @@ export function enclaveStatusToString(status: EnclaveContainersStatus) {
}
}

export function enclaveStatusToColorScheme(status: EnclaveContainersStatus) {
switch (status) {
case EnclaveContainersStatus.EnclaveContainersStatus_RUNNING:
return "green";
case EnclaveContainersStatus.EnclaveContainersStatus_STOPPED:
return "red";
case EnclaveContainersStatus.EnclaveContainersStatus_EMPTY:
return "gray";
}
}

type EnclaveStatusProps = {
status: EnclaveContainersStatus;
variant?: string;
};

export const EnclaveStatus = ({ status, variant }: EnclaveStatusProps) => {
const display = enclaveStatusToString(status);
switch (status) {
case EnclaveContainersStatus.EnclaveContainersStatus_RUNNING:
return (
<Tag variant={variant} colorScheme={"green"}>
{display}
</Tag>
);
case EnclaveContainersStatus.EnclaveContainersStatus_STOPPED:
return (
<Tag variant={variant} colorScheme={"red"}>
{display}
</Tag>
);
case EnclaveContainersStatus.EnclaveContainersStatus_EMPTY:
return (
<Tag variant={variant} colorScheme={"gray"}>
{display}
</Tag>
);
}
const colorScheme = enclaveStatusToColorScheme(status);

return (
<Tooltip closeDelay={1000} label={"This is the status of the container running the enclave"}>
<Tag variant={variant} colorScheme={colorScheme}>
{display}
</Tag>
</Tooltip>
);
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Tag } from "@chakra-ui/react";
import { Tag, Tooltip } from "@chakra-ui/react";
import { ServiceStatus } from "enclave-manager-sdk/build/api_container_service_pb";

export function serviceStatusToString(status: ServiceStatus) {
Expand All @@ -12,31 +12,31 @@ export function serviceStatusToString(status: ServiceStatus) {
}
}

export function serviceStatusToColorScheme(status: ServiceStatus) {
switch (status) {
case ServiceStatus.RUNNING:
return "green";
case ServiceStatus.STOPPED:
return "red";
case ServiceStatus.UNKNOWN:
return "orange";
}
}

type ServiceStatusTagProps = {
status: ServiceStatus;
variant?: string;
};

export const ServiceStatusTag = ({ status, variant }: ServiceStatusTagProps) => {
const display = serviceStatusToString(status);
switch (status) {
case ServiceStatus.RUNNING:
return (
<Tag variant={variant} colorScheme={"green"}>
{display}
</Tag>
);
case ServiceStatus.STOPPED:
return (
<Tag variant={variant} colorScheme={"red"}>
{display}
</Tag>
);
case ServiceStatus.UNKNOWN:
return (
<Tag variant={variant} colorScheme={"orange"}>
{display}
</Tag>
);
}
const colorScheme = serviceStatusToColorScheme(status);

return (
<Tooltip label={"The status of the container providing this service."} openDelay={1000}>
<Tag variant={variant} colorScheme={colorScheme}>
{display}
</Tag>
</Tooltip>
);
};
7 changes: 7 additions & 0 deletions enclave-manager/web/src/components/theme/tabsTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ export const tabsTheme = defineMultiStyleConfig({
},
variants: {
"soft-rounded": (props: StyleFunctionProps) => ({
root: {
height: "100%",
},
tab: {
fontStyle: "normal",
fontWeight: "medium",
Expand All @@ -27,8 +30,12 @@ export const tabsTheme = defineMultiStyleConfig({
},
textTransform: "capitalize",
},
tabpanels: {
height: "100%",
},
tabpanel: {
padding: "32px 0px",
height: "100%",
},
}),
},
Expand Down
23 changes: 23 additions & 0 deletions enclave-manager/web/src/emui/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,29 @@ import { EmuiAppContextProvider } from "./EmuiAppContext";
import { enclaveRoutes } from "./enclaves/EnclaveRoutes";
import { Navbar } from "./Navbar";

const logLogo = (t: string) => console.log(`%c ${t}`, "background: black; color: #00C223");
logLogo(`
///////////////////
////////// ///////////////////
.//// ,/// ///// ////*
///// /// ///// /////
,//// ,//// *//// ////*
// ///// ///// /////
*//// *//// ////*
///// ///// /////
*//// ///// /////
.//// ///// /////
./// ///// ////* //
///. ///// ////// /////
//// ////*.//// *////
//// ///// ///// /////
///// *////* .//// *////
////////////// ////////////////////

`);

console.log(`Kurtosis web UI version: ${process.env.REACT_APP_VERSION || "Unknown"}`);

export const EmuiApp = () => {
return (
<KurtosisThemeProvider>
Expand Down
26 changes: 17 additions & 9 deletions enclave-manager/web/src/emui/EmuiAppContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export type EmuiAppState = {
productionMode?: boolean,
apiContainerVersionTag?: string,
) => Promise<Result<CreateEnclaveResponse, string>>;
destroyEnclave: (enclaveUUID: string) => Promise<Result<Empty, string>>;
destroyEnclaves: (enclaveUUIDs: string[]) => Promise<Result<Empty, string>[]>;
runStarlarkPackage: (
apicInfo: RemoveFunctions<EnclaveAPIContainerInfo>,
packageId: string,
Expand All @@ -64,7 +64,7 @@ const EmuiAppContext = createContext<EmuiAppState>({
refreshFilesAndArtifacts: () => null as any,
refreshStarlarkRun: () => null as any,
createEnclave: () => null as any,
destroyEnclave: () => null as any,
destroyEnclaves: () => null as any,
runStarlarkPackage: () => null as any,
});

Expand Down Expand Up @@ -153,18 +153,26 @@ export const EmuiAppContextProvider = ({ children }: PropsWithChildren) => {
[kurtosisClient],
);

const destroyEnclave = useCallback(
async (enclaveUUID: string) => {
const resp = await kurtosisClient.destroy(enclaveUUID);
if (resp.isOk) {
const destroyEnclaves = useCallback(
async (enclaveUUIDs: string[]) => {
const responses: Result<Empty, string>[] = [];
const destroyedEnclaves = new Set<string>();
for (const enclaveUUID of enclaveUUIDs) {
const resp = await kurtosisClient.destroy(enclaveUUID);
if (resp.isOk) {
destroyedEnclaves.add(enclaveUUID);
}
responses.push(resp);
}
if (destroyedEnclaves.size > 0) {
setState((state) => ({
...state,
enclaves: state.enclaves.isOk
? Result.ok(state.enclaves.value.filter((enclave) => enclave.enclaveUuid !== enclaveUUID))
? Result.ok(state.enclaves.value.filter((enclave) => !destroyedEnclaves.has(enclave.enclaveUuid)))
: state.enclaves,
}));
}
return resp;
return responses;
},
[kurtosisClient],
);
Expand Down Expand Up @@ -205,7 +213,7 @@ export const EmuiAppContextProvider = ({ children }: PropsWithChildren) => {
refreshFilesAndArtifacts,
refreshServices,
createEnclave,
destroyEnclave,
destroyEnclaves,
runStarlarkPackage,
}}
>
Expand Down
Loading