Skip to content

Commit

Permalink
feat: emui improvements (#1808)
Browse files Browse the repository at this point in the history
## Description:
EMUI improvements from the post devconnect burndown. The following
changes are included:
* Fix for the autoscroll behaviour breaking on long log lines

https://github.com/kurtosis-tech/kurtosis/assets/4419574/67ea042e-466b-429c-bead-9fa9d49e1180
* Make hover appearance clearer with outline buttons (consistent with
ghost buttons)

![image](https://github.com/kurtosis-tech/kurtosis/assets/4419574/02b3d79b-f8cf-416a-a752-be07fbf43db3)
* Clear deletion selection count when enclaves deleted
* Use default package argument values in form placeholder

![image](https://github.com/kurtosis-tech/kurtosis/assets/4419574/4320e7f0-6f55-4012-9858-3486e73f9d4a)
* Implement ports summary feedback (table copy and summary count
appearance)

![image](https://github.com/kurtosis-tech/kurtosis/assets/4419574/3eefffad-6163-4ad3-ae94-6afae21310a9)
* Tooltips on edit, delete and create enclave buttons
* Consistent date time formats in the RelativeTime component tooltip

![image](https://github.com/kurtosis-tech/kurtosis/assets/4419574/5f393d33-663c-4573-bc03-464921ded21c)
* Breadcrumb menus

![image](https://github.com/kurtosis-tech/kurtosis/assets/4419574/bd8c0860-3247-4c31-9dfe-b1c19c2756ab)

![image](https://github.com/kurtosis-tech/kurtosis/assets/4419574/73668ae7-7c93-445a-810a-c8bf65607bc3)

## Is this change user facing?
YES
  • Loading branch information
Dartoxian authored Nov 16, 2023
1 parent 7c34582 commit 4e77667
Show file tree
Hide file tree
Showing 24 changed files with 266 additions and 156 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { createConnectTransport } from "@connectrpc/connect-web";
import { asyncResult } from "../../utils";
import { KURTOSIS_PACKAGE_INDEXER_URL } from "../constants";
import { KurtosisPackageIndexer } from "./api/kurtosis_package_indexer_connect";
import { ReadPackageRequest } from "./api/kurtosis_package_indexer_pb";
import { PackageRepository, ReadPackageRequest } from "./api/kurtosis_package_indexer_pb";

export class KurtosisPackageIndexerClient {
private client: PromiseClient<typeof KurtosisPackageIndexer>;
Expand All @@ -21,25 +21,25 @@ export class KurtosisPackageIndexerClient {
});
};

parsePackageUrl(packageUrl: string) {
const components = packageUrl.split("/");
if (components.length < 3) {
throw Error(`Illegal url, invalid number of components: ${packageUrl}`);
}
if (components[1].length < 1 || components[2].length < 1) {
throw Error(`Illegal url, empty components: ${packageUrl}`);
}
return new PackageRepository({
baseUrl: "github.com",
owner: components[1],
name: components[2],
rootPath: components.filter((v, i) => i > 2 && v.length > 0).join("/") + "/",
});
}

readPackage = async (packageUrl: string) => {
return asyncResult(() => {
const components = packageUrl.split("/");
if (components.length < 3) {
throw Error(`Illegal url, invalid number of components: ${packageUrl}`);
}
if (components[1].length < 1 || components[2].length < 1) {
throw Error(`Illegal url, empty components: ${packageUrl}`);
}
return this.client.readPackage(
new ReadPackageRequest({
repositoryMetadata: {
baseUrl: "github.com",
owner: components[1],
name: components[2],
rootPath: components.filter((v, i) => i > 2 && v.length > 0).join("/") + "/",
},
}),
);
return this.client.readPackage(new ReadPackageRequest({ repositoryMetadata: this.parsePackageUrl(packageUrl) }));
});
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,6 @@ export const KurtosisPackageIndexer = {
O: ReadPackageResponse,
kind: MethodKind.Unary,
},
},
}
} as const;

Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,11 @@ export class PackageArg extends Message<PackageArg> {
*/
typeV2?: PackageArgumentType;

/**
* @generated from field: optional string defaultValue = 6;
*/
defaultValue?: string;

constructor(data?: PartialMessage<PackageArg>) {
super();
proto3.util.initPartial(data, this);
Expand All @@ -296,6 +301,7 @@ export class PackageArg extends Message<PackageArg> {
{ no: 2, name: "is_required", kind: "scalar", T: 8 /* ScalarType.BOOL */ },
{ no: 4, name: "description", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 5, name: "typeV2", kind: "message", T: PackageArgumentType },
{ no: 6, name: "defaultValue", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true },
]);

static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): PackageArg {
Expand Down
2 changes: 1 addition & 1 deletion enclave-manager/web/src/components/FormatDateTime.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const FormatDateTime = ({ dateTime, format, ...textProps }: FormatDateTim
}

return (
<Tooltip label={dateTime.toISO()}>
<Tooltip label={dateTime.toLocal().toFormat("yyyy-MM-dd HH:mm:ss ZZZZ")}>
<Text as={"span"} {...textProps}>
{formattedDateTime}
</Text>
Expand Down
81 changes: 69 additions & 12 deletions enclave-manager/web/src/components/KurtosisBreadcrumbs.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,35 @@
import { ChevronRightIcon } from "@chakra-ui/icons";
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, Button, Flex } from "@chakra-ui/react";
import { useEffect, useState } from "react";
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
Button,
ButtonGroup,
Flex,
Icon,
IconButton,
Menu,
MenuButton,
MenuItem,
MenuList,
} from "@chakra-ui/react";
import { ReactElement, useEffect, useState } from "react";
import { MdFilterList } from "react-icons/md";
import { Link, Params, UIMatch, useMatches } from "react-router-dom";
import { EmuiAppState, useEmuiAppContext } from "../emui/EmuiAppContext";
import { isDefined } from "../utils";
import { RemoveFunctions } from "../utils/types";

type KurtosisBreadcrumbMenuItem = {
name: string;
destination: string;
icon?: ReactElement;
};

export type KurtosisBreadcrumb = {
name: string;
destination: string;
alternatives?: KurtosisBreadcrumbMenuItem[];
};

export const KurtosisBreadcrumbs = () => {
Expand Down Expand Up @@ -50,21 +71,57 @@ export const KurtosisBreadcrumbs = () => {
return (
<Flex h="40px" p={"4px 0"} alignItems={"center"}>
<Breadcrumb variant={"topNavigation"} separator={<ChevronRightIcon h={"20px"} w={"24px"} />}>
{matchCrumbs.map(({ name, destination }, i, arr) => (
{matchCrumbs.map((crumb, i, arr) => (
<BreadcrumbItem key={i} isCurrentPage={i === arr.length - 1}>
<BreadcrumbLink as={i === arr.length - 1 ? undefined : Link} to={destination}>
{i === arr.length - 1 ? (
name
) : (
<Button variant={"breadcrumb"} size={"sm"}>
{name}
</Button>
)}
</BreadcrumbLink>
<KurtosisBreadcrumbItem {...crumb} key={i} isLastItem={i === arr.length - 1} />
</BreadcrumbItem>
))}
</Breadcrumb>
&nbsp;
</Flex>
);
};

type KurtosisBreadcrumbItemProps = KurtosisBreadcrumb & {
isLastItem: boolean;
};

const KurtosisBreadcrumbItem = ({ name, destination, alternatives, isLastItem }: KurtosisBreadcrumbItemProps) => {
if (isLastItem) {
return <BreadcrumbLink>{name}</BreadcrumbLink>;
}

const baseLink = (
<BreadcrumbLink as={Link} to={destination}>
<Button variant={"breadcrumb"} size={"sm"}>
{name}
</Button>
</BreadcrumbLink>
);

if (isDefined(alternatives) && alternatives.length > 0) {
// Render with menu
return (
<ButtonGroup isAttached>
{baseLink}
<Menu>
<MenuButton
as={IconButton}
variant={"breadcrumb"}
aria-label={"Other options"}
icon={<Icon as={MdFilterList} />}
size={"sm"}
/>
<MenuList>
{alternatives.map(({ name, destination, icon }) => (
<MenuItem key={destination} as={Link} to={destination} icon={icon}>
{name}
</MenuItem>
))}
</MenuList>
</Menu>
</ButtonGroup>
);
}
return baseLink;
};
4 changes: 2 additions & 2 deletions enclave-manager/web/src/components/KurtosisThemeProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ const theme = extendTheme({
},
variants: {
outline: (props: StyleFunctionProps) => ({
_hover: { borderColor: `${props.colorScheme}.400`, bg: `gray.700` },
_active: { bg: `gray.800` },
_hover: { borderColor: `${props.colorScheme}.400`, bg: `gray.650` },
_active: { bg: `gray.700` },
color: `${props.colorScheme}.400`,
borderColor: "gray.300",
}),
Expand Down
22 changes: 12 additions & 10 deletions enclave-manager/web/src/components/enclaves/CreateEnclaveButton.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Button, Menu, MenuButton } from "@chakra-ui/react";
import { Button, Menu, MenuButton, Tooltip } from "@chakra-ui/react";
import { FiPlus } from "react-icons/fi";
import { useNavigate } from "react-router-dom";
import { KURTOSIS_CREATE_ENCLAVE_URL_ARG } from "../constants";
Expand All @@ -8,15 +8,17 @@ export const CreateEnclaveButton = () => {
return (
<>
<Menu matchWidth>
<MenuButton
as={Button}
colorScheme={"kurtosisGreen"}
leftIcon={<FiPlus />}
size={"md"}
onClick={() => navigate(`#${KURTOSIS_CREATE_ENCLAVE_URL_ARG}`)}
>
New Enclave
</MenuButton>
<Tooltip label={"Create a new enclave"} openDelay={1000}>
<MenuButton
as={Button}
colorScheme={"kurtosisGreen"}
leftIcon={<FiPlus />}
size={"md"}
onClick={() => navigate(`#${KURTOSIS_CREATE_ENCLAVE_URL_ARG}`)}
>
New Enclave
</MenuButton>
</Tooltip>
{/*<MenuList>*/}
{/* <MenuItem onClick={() => navigate(`#${KURTOSIS_CREATE_ENCLAVE_URL_ARG}`)} icon={<FiSettings />}>*/}
{/* Manual*/}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,14 @@ export const EditEnclaveButton = ({ enclave }: EditEnclaveButtonProps) => {

return (
<>
<Button onClick={() => setShowPackageLoader(true)} colorScheme={"blue"} leftIcon={<FiEdit2 />} size={"md"}>
Edit
</Button>
<Tooltip
label={"Edit this enclave. From here you can edit the enclave configuration and update it."}
openDelay={1000}
>
<Button onClick={() => setShowPackageLoader(true)} colorScheme={"blue"} leftIcon={<FiEdit2 />} size={"md"}>
Edit
</Button>
</Tooltip>
{showPackageLoader && (
<PackageLoadingModal packageId={enclave.starlarkRun.value.packageId} onPackageLoaded={handlePackageLoaded} />
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export const KurtosisPackageArgumentInput = ({ argument, disabled }: KurtosisPac
subType1={argument.typeV2?.innerType1}
subType2={argument.typeV2?.innerType2}
name={fieldName}
placeholder={argument.defaultValue}
isRequired={argument.isRequired}
/>
</KurtosisArgumentFormControl>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Radio, RadioGroup, Stack, Switch } from "@chakra-ui/react";
import { useEnclaveConfigurationFormContext } from "../EnclaveConfigurationForm";
import { KurtosisArgumentTypeInputProps } from "./KurtosisArgumentTypeInput";
import { KurtosisArgumentTypeInputImplProps } from "./KurtosisArgumentTypeInput";

type BooleanArgumentInputProps = Omit<KurtosisArgumentTypeInputProps, "type"> & {
type BooleanArgumentInputProps = KurtosisArgumentTypeInputImplProps & {
inputType?: "radio" | "switch";
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import { CopyButton } from "../../../CopyButton";
import { PasteButton } from "../../../PasteButton";
import { KurtosisArgumentSubtypeFormControl } from "../KurtosisArgumentFormControl";
import { ConfigureEnclaveForm } from "../types";
import { KurtosisArgumentTypeInput, KurtosisArgumentTypeInputProps } from "./KurtosisArgumentTypeInput";
import { KurtosisArgumentTypeInput, KurtosisArgumentTypeInputImplProps } from "./KurtosisArgumentTypeInput";

type DictArgumentInputProps = Omit<KurtosisArgumentTypeInputProps, "type"> & {
type DictArgumentInputProps = KurtosisArgumentTypeInputImplProps & {
keyType: ArgumentValueType;
valueType: ArgumentValueType;
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Input } from "@chakra-ui/react";
import { isDefined } from "../../../../utils";
import { useEnclaveConfigurationFormContext } from "../EnclaveConfigurationForm";
import { KurtosisArgumentTypeInputProps } from "./KurtosisArgumentTypeInput";
import { KurtosisArgumentTypeInputImplProps } from "./KurtosisArgumentTypeInput";

export const IntegerArgumentInput = (props: Omit<KurtosisArgumentTypeInputProps, "type">) => {
export const IntegerArgumentInput = (props: KurtosisArgumentTypeInputImplProps) => {
const { register } = useEnclaveConfigurationFormContext();

return (
Expand All @@ -22,6 +22,7 @@ export const IntegerArgumentInput = (props: Omit<KurtosisArgumentTypeInputProps,
}
},
})}
placeholder={props.placeholder}
width={props.width}
size={props.size || "lg"}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Controller } from "react-hook-form";
import { isDefined, stringifyError } from "../../../../utils";
import { CodeEditor } from "../../../CodeEditor";
import { KurtosisArgumentTypeInputProps } from "./KurtosisArgumentTypeInput";
import { KurtosisArgumentTypeInputImplProps } from "./KurtosisArgumentTypeInput";

export const JSONArgumentInput = (props: Omit<KurtosisArgumentTypeInputProps, "type">) => {
export const JSONArgumentInput = (props: KurtosisArgumentTypeInputImplProps) => {
return (
<Controller
render={({ field }) => <CodeEditor text={field.value} onTextChange={field.onChange} />}
Expand Down
Loading

0 comments on commit 4e77667

Please sign in to comment.