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: emui small design tweaks based on team feedback #1897

Merged
merged 9 commits into from
Dec 7, 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
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ const theme = extendTheme({
const outline = theme.components.Button.variants!.outline(props);
return {
...outline,
_hover: { ...outline._hover, bg: "gray.700" },
_hover: { ...outline._hover, bg: "gray.600" },
color: `${props.colorScheme}.400`,
borderColor: "gray.300",
};
Expand Down
19 changes: 2 additions & 17 deletions enclave-manager/web/src/components/PackageSourceButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,14 @@ import { PropsWithChildren } from "react";
import { IoLogoGithub } from "react-icons/io";
import { useKurtosisPackageIndexerClient } from "../client/packageIndexer/KurtosisPackageIndexerClientContext";
import { isDefined, wrapResult } from "../utils";
import { CopyButton } from "./CopyButton";

type EnclaveSourceProps = PropsWithChildren<
ButtonProps & {
source: "loading" | string | null;
hideCopy?: boolean;
}
>;

export const PackageSourceButton = ({ source, hideCopy, children, ...buttonProps }: EnclaveSourceProps) => {
export const PackageSourceButton = ({ source, children, ...buttonProps }: EnclaveSourceProps) => {
const kurtosisIndexer = useKurtosisPackageIndexerClient();

if (!isDefined(source)) {
Expand Down Expand Up @@ -63,18 +61,5 @@ export const PackageSourceButton = ({ source, hideCopy, children, ...buttonProps
}
}

return (
<ButtonGroup>
{button}
{!hideCopy && (
<CopyButton
contentName={"package id"}
valueToCopy={source}
isIconButton
aria-label={"Copy package id"}
size={buttonProps.size || "xs"}
/>
)}
</ButtonGroup>
);
return <ButtonGroup>{button}</ButtonGroup>;
};
37 changes: 24 additions & 13 deletions enclave-manager/web/src/components/catalog/KurtosisPackageCard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Flex, Icon, Image, Text } from "@chakra-ui/react";
import { Box, Flex, Icon, Image, Text } from "@chakra-ui/react";
import { IoStar } from "react-icons/io5";
import { Link } from "react-router-dom";
import { useKurtosisClient } from "../../client/enclaveManager/KurtosisClientContext";
Expand Down Expand Up @@ -41,19 +41,30 @@ export const KurtosisPackageCard = ({ kurtosisPackage }: KurtosisPackageCardProp
<Text noOfLines={2} fontSize={"lg"}>
{readablePackageName(kurtosisPackage.name)}
</Text>
<Flex justifyContent={"space-between"} fontSize={"xs"}>
<Text as={"span"} textTransform={"capitalize"}>
{kurtosisPackage.repositoryMetadata?.owner.replaceAll("-", " ") || "Unknown owner"}
</Text>
<Flex gap={"4px"} alignItems={"center"}>
{kurtosisPackage.stars > 0 && (
<>
<Icon color="gray.500" as={IoStar} />
<Text as={"span"}>{kurtosisPackage.stars.toString()}</Text>
</>
)}
<Box
flex={"1"}
sx={{
containerType: "size",
containerName: "details-container",
"@container details-container (min-height: 30px)": {
"> div": { flexDirection: "column", justifyContent: "flex-end", height: "100%" },
},
}}
>
<Flex justifyContent={"space-between"} fontSize={"xs"} gap={"8px"}>
<Text as={"span"} textTransform={"capitalize"}>
{kurtosisPackage.repositoryMetadata?.owner.replaceAll("-", " ") || "Unknown owner"}
</Text>
<Flex gap={"4px"} alignItems={"center"}>
{kurtosisPackage.stars > 0 && (
<>
<Icon color="gray.500" as={IoStar} />
<Text as={"span"}>{kurtosisPackage.stars.toString()}</Text>
</>
)}
</Flex>
</Flex>
</Flex>
</Box>
</Flex>
</Flex>
<Flex gap={"16px"} width={"100%"}>
Expand Down
57 changes: 28 additions & 29 deletions enclave-manager/web/src/components/enclaves/logs/LogViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
Text,
Tooltip,
} from "@chakra-ui/react";
import { debounce, throttle } from "lodash";
import { throttle } from "lodash";
import { ChangeEvent, MutableRefObject, ReactElement, useCallback, useEffect, useMemo, useRef, useState } from "react";
import { FiSearch } from "react-icons/fi";
import { MdArrowBackIosNew, MdArrowForwardIos } from "react-icons/md";
Expand Down Expand Up @@ -98,7 +98,7 @@ export const LogViewer = ({
}
};

const handleSearchStateChange = (updater: ((prevState: SearchState) => SearchState) | SearchState) => {
const handleSearchStateChange = useCallback((updater: ((prevState: SearchState) => SearchState) | SearchState) => {
setSearchState((prevState) => {
const newState = typeof updater === "object" ? updater : updater(prevState);
if (
Expand All @@ -110,7 +110,7 @@ export const LogViewer = ({
}
return newState;
});
};
}, []);

const getLogsValue = () => {
return logLines
Expand Down Expand Up @@ -219,6 +219,8 @@ const SearchControls = ({ searchState, onChangeSearchState, logLines }: SearchCo
const searchRef: MutableRefObject<HTMLInputElement | null> = useRef(null);
const [showSearchForm, setShowSearchForm] = useState(false);

const maybeCurrentSearchIndex = searchState.type === "success" ? searchState.currentSearchIndex : null;

const updateMatches = useCallback(
(searchTerm: string) => {
if (isNotEmpty(searchTerm)) {
Expand Down Expand Up @@ -253,44 +255,38 @@ const SearchControls = ({ searchState, onChangeSearchState, logLines }: SearchCo
[logLines, onChangeSearchState],
);

const debouncedUpdateMatches = useMemo(() => debounce(updateMatches, 100), [updateMatches]);
const throttledUpdateMatches = useMemo(() => throttle(updateMatches, 300), [updateMatches]);

const handleOnChange = (e: ChangeEvent<HTMLInputElement>) => {
onChangeSearchState((state) => ({ ...state, rawSearchTerm: e.target.value }));
debouncedUpdateMatches(e.target.value);
throttledUpdateMatches(e.target.value);
};

const updateSearchIndexBounded = useCallback(
(newIndex: number) => {
if (searchState.type !== "success") {
return;
}
if (newIndex > searchState.searchMatchesIndices.length - 1) {
newIndex = 0;
}
if (newIndex < 0) {
newIndex = searchState.searchMatchesIndices.length - 1;
}
onChangeSearchState((state) => ({ ...state, currentSearchIndex: newIndex }));
onChangeSearchState((searchState) => {
if (searchState.type !== "success" || searchState.searchMatchesIndices.length === 0) {
return searchState;
}
if (newIndex > searchState.searchMatchesIndices.length - 1) {
newIndex = 0;
}
if (newIndex < 0) {
newIndex = searchState.searchMatchesIndices.length - 1;
}
return { ...searchState, currentSearchIndex: newIndex };
});
},
[onChangeSearchState, searchState],
[onChangeSearchState],
);

const handlePriorMatchClick = useCallback(() => {
updateSearchIndexBounded(
searchState.type === "success" && isDefined(searchState.currentSearchIndex)
? searchState.currentSearchIndex - 1
: 0,
);
}, [updateSearchIndexBounded, searchState]);
updateSearchIndexBounded(isDefined(maybeCurrentSearchIndex) ? maybeCurrentSearchIndex - 1 : 0);
}, [updateSearchIndexBounded, maybeCurrentSearchIndex]);

const handleNextMatchClick = useCallback(() => {
updateSearchIndexBounded(
searchState.type === "success" && isDefined(searchState.currentSearchIndex)
? searchState.currentSearchIndex + 1
: 0,
);
}, [updateSearchIndexBounded, searchState]);
updateSearchIndexBounded(isDefined(maybeCurrentSearchIndex) ? maybeCurrentSearchIndex + 1 : 0);
}, [updateSearchIndexBounded, maybeCurrentSearchIndex]);

const handleClearSearch = useCallback(() => {
onChangeSearchState({ type: "init", rawSearchTerm: "" });
Expand Down Expand Up @@ -319,9 +315,12 @@ const SearchControls = ({ searchState, onChangeSearchState, logLines }: SearchCo
searchRef.current.focus();
}
},
next: () => {
enter: () => {
handleNextMatchClick();
},
"shift-enter": () => {
handlePriorMatchClick();
},
escape: () => {
if (isDefined(searchRef.current) && searchRef.current === document.activeElement) {
handleClearSearch();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Button, Checkbox } from "@chakra-ui/react";
import { Button, Checkbox, Text } from "@chakra-ui/react";
import { ColumnDef, createColumnHelper } from "@tanstack/react-table";
import { FilesArtifactNameAndUuid, ServiceInfo } from "enclave-manager-sdk/build/api_container_service_pb";
import { EnclaveContainersStatus } from "enclave-manager-sdk/build/engine_service_pb";
Expand Down Expand Up @@ -93,7 +93,9 @@ export const EnclavesTable = ({ enclavesData, selection, onSelectionChange }: En
cell: (nameCell) => (
<Link to={`/enclave/${nameCell.row.original.uuid}/overview`}>
<Button size={"sm"} variant={"ghost"}>
{nameCell.row.original.name}
<Text as={"span"} maxW={"200px"} textOverflow={"ellipsis"} overflow={"hidden"}>
{nameCell.row.original.name}
</Text>
</Button>
</Link>
),
Expand Down
45 changes: 28 additions & 17 deletions enclave-manager/web/src/components/useKeyboardAction.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,44 @@
import { useEffect } from "react";
import { isDefined } from "../utils";

export type KeyboardActions = "escape" | "find" | "omniFind" | "next";
export type KeyboardActions = "escape" | "find" | "omniFind" | "enter" | "shift-enter";

export type OnCtrlPressHandlers = Partial<Record<KeyboardActions, () => void>>;

const eventIsType = (e: KeyboardEvent, type: KeyboardActions) => {
const getEventType = (e: KeyboardEvent): KeyboardActions | null => {
const ctrlOrMeta = e.ctrlKey || e.metaKey;

switch (type) {
case "find":
return ctrlOrMeta && e.keyCode === 70; // F
case "next":
return ctrlOrMeta && e.keyCode === 71; // G
case "omniFind":
return ctrlOrMeta && e.keyCode === 75; // K
case "escape":
return e.key === "Escape" || e.keyCode === 27;
if (ctrlOrMeta && e.keyCode === 70) {
// F
return "find";
}
if (e.shiftKey && e.keyCode === 13) {
// shift + enter
return "shift-enter";
}
if (e.keyCode === 13) {
// enter
return "enter";
}
if (ctrlOrMeta && e.keyCode === 75) {
// K
return "omniFind";
}
if (e.key === "Escape" || e.keyCode === 27) {
return "escape";
}
return null;
};

export const useKeyboardAction = (handlers: OnCtrlPressHandlers) => {
useEffect(() => {
const listener = function (e: KeyboardEvent) {
for (const [handlerType, handler] of Object.entries(handlers)) {
if (eventIsType(e, handlerType as KeyboardActions)) {
e.preventDefault();
handler();
return;
}
const eventType = getEventType(e);
const handler = isDefined(eventType) ? handlers[eventType] : null;
if (isDefined(handler)) {
e.preventDefault();
handler();
return;
}
};
window.addEventListener("keydown", listener);
Expand Down
11 changes: 0 additions & 11 deletions enclave-manager/web/src/emui/catalog/package/Package.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,6 @@ const PackageImpl = ({ kurtosisPackage }: PackageImplProps) => {
<KurtosisMarkdown>{kurtosisPackage.description}</KurtosisMarkdown>
</Box>
</TitledCard>
<TitledCard title={"ENTRYPOINT DESCRIPTION"}>
<Box p={"0 15px 15px 15px"}>
<KurtosisMarkdown>{kurtosisPackage.entrypointDescription}</KurtosisMarkdown>
</Box>
</TitledCard>
<TitledCard title={"RETURNS DESCRIPTION"}>
<Box p={"0 15px 15px 15px"}>
<KurtosisMarkdown>{kurtosisPackage.returnsDescription}</KurtosisMarkdown>
</Box>
</TitledCard>
</Flex>
<Flex flexDirection={"column"} gap={"16px"} flex={"1"}>
<RunKurtosisPackageButton kurtosisPackage={kurtosisPackage} size={"lg"} />
Expand All @@ -76,7 +66,6 @@ const PackageImpl = ({ kurtosisPackage }: PackageImplProps) => {
</InputGroup>
<PackageSourceButton
source={kurtosisPackage.name}
hideCopy
variant={"outline"}
color={"gray.100"}
size={"lg"}
Expand Down
6 changes: 3 additions & 3 deletions engine/server/webapp/asset-manifest.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"files": {
"main.js": "./static/js/main.76d5fae1.js",
"main.js": "./static/js/main.7141edba.js",
"index.html": "./index.html",
"main.76d5fae1.js.map": "./static/js/main.76d5fae1.js.map"
"main.7141edba.js.map": "./static/js/main.7141edba.js.map"
},
"entrypoints": [
"static/js/main.76d5fae1.js"
"static/js/main.7141edba.js"
]
}
2 changes: 1 addition & 1 deletion engine/server/webapp/index.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="./favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Kurtosis Enclave Manager"/><title>Kurtosis Enclave Manager</title><script defer="defer" src="./static/js/main.76d5fae1.js"></script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="./favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Kurtosis Enclave Manager"/><title>Kurtosis Enclave Manager</title><script defer="defer" src="./static/js/main.7141edba.js"></script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Loading