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

feat: new emui use monaco as json editor #1733

Merged
merged 10 commits into from
Nov 9, 2023
16 changes: 11 additions & 5 deletions enclave-manager/web/src/components/CodeEditor.tsx
Original file line number Diff line number Diff line change
@@ -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 = {
Expand All @@ -14,8 +14,12 @@ export const CodeEditor = ({ text, onTextChange, showLineNumbers }: CodeEditorPr
const isReadOnly = !isDefined(onTextChange);
const [editor, setEditor] = useState<editor.IStandaloneCodeEditor>();

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) => {
Expand All @@ -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 (
<Box width={"100%"} minHeight={`${editor?.getContentHeight() || 10}px`}>
<Box width={"100%"} minHeight={`${editor?.getLayoutInfo().height || 10}px`}>
<Editor
onMount={handleMount}
value={text}
Expand Down
5 changes: 3 additions & 2 deletions enclave-manager/web/src/components/CopyButton.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Button, ButtonProps, IconButton, IconButtonProps, useToast } from "@chakra-ui/react";
import { FiCopy } from "react-icons/fi";
import { isDefined } from "../utils";
import { SuccessToast } from "./Toasts";

type CopyButtonProps<IsIconButton extends boolean> = (IsIconButton extends true ? IconButtonProps : ButtonProps) & {
valueToCopy?: (() => string) | string | null;
Expand All @@ -23,8 +24,8 @@ export const CopyButton = <IsIconButton extends boolean>({
const v = typeof valueToCopy === "string" ? valueToCopy : valueToCopy();
navigator.clipboard.writeText(v);
toast({
title: `Copied ${contentName} to the clipboard`,
status: `success`,
position: "bottom",
render: () => <SuccessToast message={`Copied ${contentName} to the clipboard`} />,
});
}
};
Expand Down
25 changes: 13 additions & 12 deletions enclave-manager/web/src/components/DataTable.tsx
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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" {
Expand Down Expand Up @@ -80,20 +80,21 @@ export function DataTable<Data extends object>({
textAlign={!!meta?.centerAligned ? "center" : undefined}
>
{header.column.getCanSort() && (
<Button variant={"sortableHeader"} size={"xs"}>
<Button
variant={"sortableHeader"}
size={"xs"}
rightIcon={
header.column.getIsSorted() === "desc" ? (
<Icon as={BiDownArrowAlt} color={"gray.400"} />
) : header.column.getIsSorted() === "asc" ? (
<Icon as={BiUpArrowAlt} color={"gray.400"} />
) : undefined
}
>
{flexRender(header.column.columnDef.header, header.getContext())}
</Button>
)}
{!header.column.getCanSort() && flexRender(header.column.columnDef.header, header.getContext())}
{header.column.getIsSorted() && (
<chakra.span pl="4">
{header.column.getIsSorted() === "desc" ? (
<TriangleDownIcon aria-label="sorted descending" color={"gray.400"} />
) : (
<TriangleUpIcon aria-label="sorted ascending" color={"gray.400"} />
)}
</chakra.span>
)}
</Th>
);
})}
Expand Down
10 changes: 8 additions & 2 deletions enclave-manager/web/src/components/KurtosisBreadcrumbs.tsx
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -46,7 +46,13 @@ export const KurtosisBreadcrumbs = () => {
{matchCrumbs.map(({ name, destination }, i, arr) => (
<BreadcrumbItem key={i} isCurrentPage={i === arr.length - 1}>
<BreadcrumbLink as={i === arr.length - 1 ? undefined : Link} to={destination}>
{name}
{i === arr.length - 1 ? (
name
) : (
<Button variant={"breadcrumb"} size={"sm"}>
{name}
</Button>
)}
</BreadcrumbLink>
</BreadcrumbItem>
))}
Expand Down
14 changes: 12 additions & 2 deletions enclave-manager/web/src/components/KurtosisThemeProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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",
}),
Expand All @@ -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",
Expand All @@ -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",
Expand Down
17 changes: 17 additions & 0 deletions enclave-manager/web/src/components/Toasts.tsx
Original file line number Diff line number Diff line change
@@ -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<ToastProps, "div">(({ message }: ToastProps, ref) => {
return (
<Flex ref={ref} bg={"rgba(0, 194, 35, 0.24)"} p={"6px 16px"} borderRadius={"6px"} gap={"12px"}>
<Icon height={"24px"} width={"24px"} as={CheckCircleIcon} color={"kurtosisGreen.400"} />
<Text fontWeight={"bold"} fontSize={"lg"}>
{message}
</Text>
</Flex>
);
});
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
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<KurtosisArgumentTypeInputProps, "type">) => {
const { register } = useEnclaveConfigurationFormContext();
const { control } = useEnclaveConfigurationFormContext();

return (
<Textarea
{...register(props.name, {
disabled: props.disabled,
<Controller
render={({ field }) => <CodeEditor text={field.value} onTextChange={field.onChange} />}
name={props.name}
defaultValue={"{}"}
rules={{
required: props.isRequired,
value: "{}",
validate: (value: string) => {
try {
JSON.parse(value);
} catch (err: any) {
return `This is not valid JSON. ${stringifyError(err)}`;
}
},
})}
}}
disabled={props.disabled}
/>
);
};
15 changes: 1 addition & 14 deletions enclave-manager/web/src/components/theme/Fonts.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,8 @@
import { Global } from "@emotion/react";

/*
* Source: https://fonts.googleapis.com/css2?family=Inter:wght@500&display=swap
* */
const Fonts = () => (
<Global
styles={`
@font-face {
font-family: 'Inter';
font-stretch: 75% 125%;
font-style: normal;
font-weight: 150 900;
font-display: swap;
src: url(https://fonts.gstatic.com/s/inter/v13/UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa2JL7SUc.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
`}
styles={`@import url('https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap');`}
/>
);

Expand Down
5 changes: 4 additions & 1 deletion enclave-manager/web/src/components/theme/tabsTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@ export const tabsTheme = defineMultiStyleConfig({
fontStyle: "normal",
fontWeight: "medium",
fontSize: "lg",
color: "gray.200",
color: "gray.100",
lineHeight: "28px",
_hover: {
bg: `gray.700`,
},
_selected: {
fontWeight: "semibold",
color: `${props.colorScheme}.400`,
Expand Down
4 changes: 3 additions & 1 deletion enclave-manager/web/src/components/theme/tagsTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ const { defineMultiStyleConfig } = createMultiStyleConfigHelpers(tagAnatomy.keys

// export the component theme
export const tagTheme = defineMultiStyleConfig({
baseStyle: {
container: { textTransform: "uppercase" },
},
variants: {
asText: (props: StyleFunctionProps) => ({
container: {
Expand All @@ -24,7 +27,6 @@ export const tagTheme = defineMultiStyleConfig({
fontSize: "xs",
lineHeight: "16px",
borderRadius: "2px",
textTransform: "uppercase",
fontWeight: "bold",
minHeight: "unset",
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { CircularProgress } from "@chakra-ui/react";
import { CircularProgress, Icon } from "@chakra-ui/react";
import { StarlarkRunResponseLine } from "enclave-manager-sdk/build/api_container_service_pb";
import { useEffect, useState } from "react";
import { FiCheck, FiX } from "react-icons/fi";
import { Location, useLocation, useNavigate, useRevalidator } from "react-router-dom";
import { LogLineProps } from "../../../../components/enclaves/logs/LogLine";
import { LogViewer } from "../../../../components/enclaves/logs/LogViewer";
Expand Down Expand Up @@ -139,7 +140,7 @@ const ProgressSummary = ({ progress }: ProgressSummaryProps) => {
<CircularProgress
size={"18px"}
value={(100 * progress.step + 1) / (progress.totalSteps + 1)}
color={"green"}
color={"kurtosisGreen.400"}
/>
<span>
{progress.step} / {progress.totalSteps}
Expand All @@ -148,15 +149,15 @@ const ProgressSummary = ({ progress }: ProgressSummaryProps) => {
)}
{progress.stage === "done" && (
<>
<CircularProgress size={"18px"} value={100} color={"green"} />
<Icon as={FiCheck} size={"18px"} color={"kurtosisGreen.400"} />
<span>
{progress.totalSteps} / {progress.totalSteps}
</span>
</>
)}
{progress.stage === "failed" && (
<>
<CircularProgress size={"18px"} value={100} color={"red"} />
<Icon as={FiX} size={"18px"} color={"red.400"} />
<span>Failed</span>
</>
)}
Expand Down