diff --git a/enclave-manager/web/src/components/CodeEditor.tsx b/enclave-manager/web/src/components/CodeEditor.tsx index 669d918b10..50c6319a3c 100644 --- a/enclave-manager/web/src/components/CodeEditor.tsx +++ b/enclave-manager/web/src/components/CodeEditor.tsx @@ -1,7 +1,7 @@ import { Box } from "@chakra-ui/react"; import { Editor, OnChange, OnMount } from "@monaco-editor/react"; import { editor } from "monaco-editor"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import { isDefined } from "../utils"; type CodeEditorProps = { @@ -14,8 +14,12 @@ export const CodeEditor = ({ text, onTextChange, showLineNumbers }: CodeEditorPr const isReadOnly = !isDefined(onTextChange); const [editor, setEditor] = useState(); - const handleContentSizeChange = (e: editor.IContentSizeChangedEvent) => { - editor?.layout({ width: 500, height: e.contentHeight }); + const resizeEditorBasedOnContent = () => { + if (isDefined(editor)) { + const contentHeight = Math.min(750, editor.getContentHeight() || 10); + editor.layout({ width: 500, height: contentHeight }); + editor.layout(); + } }; const handleMount: OnMount = (editor, monaco) => { @@ -27,17 +31,19 @@ export const CodeEditor = ({ text, onTextChange, showLineNumbers }: CodeEditorPr colors: {}, }); monaco.editor.setTheme("kurtosis-theme"); - editor.onDidContentSizeChange(handleContentSizeChange); }; + useEffect(() => resizeEditorBasedOnContent(), [editor]); + const handleChange: OnChange = (value, ev) => { if (isDefined(value) && onTextChange) { onTextChange(value); + resizeEditorBasedOnContent(); } }; return ( - + = (IsIconButton extends true ? IconButtonProps : ButtonProps) & { valueToCopy?: (() => string) | string | null; @@ -23,8 +24,8 @@ export const CopyButton = ({ const v = typeof valueToCopy === "string" ? valueToCopy : valueToCopy(); navigator.clipboard.writeText(v); toast({ - title: `Copied ${contentName} to the clipboard`, - status: `success`, + position: "bottom", + render: () => , }); } }; diff --git a/enclave-manager/web/src/components/DataTable.tsx b/enclave-manager/web/src/components/DataTable.tsx index 3df1aea31c..c5ef09abbf 100644 --- a/enclave-manager/web/src/components/DataTable.tsx +++ b/enclave-manager/web/src/components/DataTable.tsx @@ -1,5 +1,4 @@ -import { TriangleDownIcon, TriangleUpIcon } from "@chakra-ui/icons"; -import { Button, chakra, Table, Tbody, Td, Th, Thead, Tr } from "@chakra-ui/react"; +import { Button, Icon, Table, Tbody, Td, Th, Thead, Tr } from "@chakra-ui/react"; import { ColumnDef, flexRender, @@ -13,6 +12,7 @@ import { import { type RowSelectionState } from "@tanstack/table-core/src/features/RowSelection"; import { type OnChangeFn } from "@tanstack/table-core/src/types"; import { useState } from "react"; +import { BiDownArrowAlt, BiUpArrowAlt } from "react-icons/bi"; import { assertDefined, isDefined } from "../utils"; declare module "@tanstack/table-core" { @@ -80,20 +80,21 @@ export function DataTable({ textAlign={!!meta?.centerAligned ? "center" : undefined} > {header.column.getCanSort() && ( - )} {!header.column.getCanSort() && flexRender(header.column.columnDef.header, header.getContext())} - {header.column.getIsSorted() && ( - - {header.column.getIsSorted() === "desc" ? ( - - ) : ( - - )} - - )} ); })} diff --git a/enclave-manager/web/src/components/KurtosisBreadcrumbs.tsx b/enclave-manager/web/src/components/KurtosisBreadcrumbs.tsx index ad5bca2e55..097857db90 100644 --- a/enclave-manager/web/src/components/KurtosisBreadcrumbs.tsx +++ b/enclave-manager/web/src/components/KurtosisBreadcrumbs.tsx @@ -1,5 +1,5 @@ import { ChevronRightIcon } from "@chakra-ui/icons"; -import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, Flex } from "@chakra-ui/react"; +import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, Button, Flex } from "@chakra-ui/react"; import { useEffect, useState } from "react"; import { Link, Params, UIMatch, useMatches } from "react-router-dom"; import { isDefined } from "../utils"; @@ -46,7 +46,13 @@ export const KurtosisBreadcrumbs = () => { {matchCrumbs.map(({ name, destination }, i, arr) => ( - {name} + {i === arr.length - 1 ? ( + name + ) : ( + + )} ))} diff --git a/enclave-manager/web/src/components/KurtosisThemeProvider.tsx b/enclave-manager/web/src/components/KurtosisThemeProvider.tsx index 822d181d32..4f82b28c59 100644 --- a/enclave-manager/web/src/components/KurtosisThemeProvider.tsx +++ b/enclave-manager/web/src/components/KurtosisThemeProvider.tsx @@ -97,7 +97,8 @@ const theme = extendTheme({ }, variants: { outline: (props: StyleFunctionProps) => ({ - _hover: { borderColor: `${props.colorScheme}.400` }, + _hover: { borderColor: `${props.colorScheme}.400`, bg: `gray.700` }, + _active: { bg: `gray.800` }, color: `${props.colorScheme}.400`, borderColor: "gray.300", }), @@ -114,7 +115,8 @@ const theme = extendTheme({ const outline = theme.components.Button.variants!.outline(props); return { ...outline, - _hover: { ...outline._hover, bg: "gray.700" }, + _hover: { ...outline._hover, bg: "gray.700", borderColor: "gray.300", cursor: "unset" }, + _active: { ...outline._active, bg: "gray.700", borderColor: "gray.300", cursor: "unset" }, bg: "gray.700", color: `${props.colorScheme}.100`, borderColor: "gray.300", @@ -137,6 +139,14 @@ const theme = extendTheme({ textTransform: "uppercase", }; }, + breadcrumb: (props: StyleFunctionProps) => { + const ghost = theme.components.Button.variants!.ghost(props); + return { + ...ghost, + color: "gray.100", + fontWeight: "normal", + }; + }, nav: { _active: { bg: "gray.600", diff --git a/enclave-manager/web/src/components/Toasts.tsx b/enclave-manager/web/src/components/Toasts.tsx new file mode 100644 index 0000000000..bbf59f9d0e --- /dev/null +++ b/enclave-manager/web/src/components/Toasts.tsx @@ -0,0 +1,17 @@ +import { CheckCircleIcon } from "@chakra-ui/icons"; +import { Flex, forwardRef, Icon, Text } from "@chakra-ui/react"; + +type ToastProps = { + message: string; +}; + +export const SuccessToast = forwardRef(({ message }: ToastProps, ref) => { + return ( + + + + {message} + + + ); +}); diff --git a/enclave-manager/web/src/components/enclaves/configuration/inputs/JSONArgumentInput.tsx b/enclave-manager/web/src/components/enclaves/configuration/inputs/JSONArgumentInput.tsx index 05c4a2642e..7c9e519482 100644 --- a/enclave-manager/web/src/components/enclaves/configuration/inputs/JSONArgumentInput.tsx +++ b/enclave-manager/web/src/components/enclaves/configuration/inputs/JSONArgumentInput.tsx @@ -1,17 +1,19 @@ -import { Textarea } from "@chakra-ui/react"; +import { Controller } from "react-hook-form"; import { stringifyError } from "../../../../utils"; +import { CodeEditor } from "../../../CodeEditor"; import { useEnclaveConfigurationFormContext } from "../EnclaveConfigurationForm"; import { KurtosisArgumentTypeInputProps } from "./KurtosisArgumentTypeInput"; export const JSONArgumentInput = (props: Omit) => { - const { register } = useEnclaveConfigurationFormContext(); + const { control } = useEnclaveConfigurationFormContext(); return ( -