diff --git a/site/src/pages/WorkspacePage/ResourceMetadata.stories.tsx b/site/src/pages/WorkspacePage/ResourceMetadata.stories.tsx new file mode 100644 index 0000000000000..af443d507ec37 --- /dev/null +++ b/site/src/pages/WorkspacePage/ResourceMetadata.stories.tsx @@ -0,0 +1,51 @@ +import { MockWorkspaceResource } from "testHelpers/entities"; +import type { Meta, StoryObj } from "@storybook/react"; +import { ResourceMetadata } from "./ResourceMetadata"; + +const meta: Meta = { + title: "pages/WorkspacePage/ResourceMetadata", + component: ResourceMetadata, +}; + +export default meta; +type Story = StoryObj; + +export const Markdown: Story = { + args: { + resource: { + ...MockWorkspaceResource, + metadata: [ + { key: "text", value: "hello", sensitive: false }, + { key: "link", value: "[hello](#)", sensitive: false }, + { key: "b/i", value: "_hello_, **friend**!", sensitive: false }, + { key: "coder", value: "`beep boop`", sensitive: false }, + ], + }, + }, +}; + +export const WithLongStrings: Story = { + args: { + resource: { + ...MockWorkspaceResource, + metadata: [ + { + key: "xxxxxxxxxxxx", + value: "14", + sensitive: false, + }, + { + key: "Long", + value: "The quick brown fox jumped over the lazy dog", + sensitive: false, + }, + { + key: "Really long", + value: + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + sensitive: false, + }, + ], + }, + }, +}; diff --git a/site/src/pages/WorkspacePage/ResourceMetadata.tsx b/site/src/pages/WorkspacePage/ResourceMetadata.tsx new file mode 100644 index 0000000000000..c2385e8bc4a00 --- /dev/null +++ b/site/src/pages/WorkspacePage/ResourceMetadata.tsx @@ -0,0 +1,91 @@ +import { MemoizedInlineMarkdown } from "components/Markdown/Markdown"; +import { SensitiveValue } from "components/Resources/SensitiveValue"; +import { CopyableValue } from "components/CopyableValue/CopyableValue"; +import { WorkspaceResource } from "api/typesGenerated"; +import { Children, FC, HTMLAttributes, PropsWithChildren } from "react"; +import { Interpolation, Theme } from "@emotion/react"; + +type ResourceMetadataProps = Omit, "resource"> & { + resource: WorkspaceResource; +}; + +export const ResourceMetadata: FC = ({ + resource, + ...headerProps +}) => { + const metadata = resource.metadata ? [...resource.metadata] : []; + + if (resource.daily_cost > 0) { + metadata.push({ + key: "Daily cost", + value: resource.daily_cost.toString(), + sensitive: false, + }); + } + + if (metadata.length === 0) { + return null; + } + + return ( +
+ {metadata.map((meta) => { + return ( +
+
+ {meta.sensitive ? ( + + ) : ( + + {meta.value} + + )} +
+
{meta.key}
+
+ ); + })} +
+ ); +}; + +const MetaValue = ({ children }: PropsWithChildren) => { + const childrenArray = Children.toArray(children); + if (childrenArray.every((child) => typeof child === "string")) { + return ( + {children} + ); + } + return <>{children}; +}; + +const styles = { + root: (theme) => ({ + padding: 24, + display: "flex", + flexWrap: "wrap", + gap: 48, + rowGap: 24, + marginBottom: 24, + fontSize: 14, + background: `linear-gradient(180deg, ${theme.palette.background.default} 0%, rgba(0, 0, 0, 0) 100%)`, + }), + + item: () => ({ + lineHeight: "1.5", + }), + + label: (theme) => ({ + fontSize: 13, + color: theme.palette.text.secondary, + textOverflow: "ellipsis", + overflow: "hidden", + whiteSpace: "nowrap", + }), + + value: () => ({ + textOverflow: "ellipsis", + overflow: "hidden", + whiteSpace: "nowrap", + }), +} satisfies Record>; diff --git a/site/src/pages/WorkspacePage/Workspace.tsx b/site/src/pages/WorkspacePage/Workspace.tsx index 32310c4c8ed5a..c6f1b93fc717a 100644 --- a/site/src/pages/WorkspacePage/Workspace.tsx +++ b/site/src/pages/WorkspacePage/Workspace.tsx @@ -1,7 +1,7 @@ import { type Interpolation, type Theme } from "@emotion/react"; import Button from "@mui/material/Button"; import AlertTitle from "@mui/material/AlertTitle"; -import { PropsWithChildren, type FC, Children } from "react"; +import { type FC } from "react"; import { useNavigate } from "react-router-dom"; import type * as TypesGen from "api/typesGenerated"; import { Alert, AlertDetail } from "components/Alert/Alert"; @@ -21,9 +21,7 @@ import HubOutlined from "@mui/icons-material/HubOutlined"; import { ResourcesSidebar } from "./ResourcesSidebar"; import { WorkspacePermissions } from "./permissions"; import { resourceOptionValue, useResourcesNav } from "./useResourcesNav"; -import { MemoizedInlineMarkdown } from "components/Markdown/Markdown"; -import { SensitiveValue } from "components/Resources/SensitiveValue"; -import { CopyableValue } from "components/CopyableValue/CopyableValue"; +import { ResourceMetadata } from "./ResourceMetadata"; export interface WorkspaceProps { handleStart: (buildParameters?: TypesGen.WorkspaceBuildParameter[]) => void; @@ -187,7 +185,10 @@ export const Workspace: FC = ({
{selectedResource && ( - + )}
= ({ ); }; -const WorkspaceResourceData: FC<{ resource: TypesGen.WorkspaceResource }> = ({ - resource, -}) => { - const metadata = resource.metadata ? [...resource.metadata] : []; - - if (resource.daily_cost > 0) { - metadata.push({ - key: "Daily cost", - value: resource.daily_cost.toString(), - sensitive: false, - }); - } - - if (metadata.length === 0) { - return null; - } - - return ( -
- {metadata.map((meta) => { - return ( -
-
- {meta.sensitive ? ( - - ) : ( - - {meta.value} - - )} -
-
{meta.key}
-
- ); - })} -
- ); -}; - -const MetaValue = ({ children }: PropsWithChildren) => { - const childrenArray = Children.toArray(children); - if (childrenArray.every((child) => typeof child === "string")) { - return ( - {children} - ); - } - return <>{children}; -}; - const countAgents = (resource: TypesGen.WorkspaceResource) => { return resource.agents ? resource.agents.length : 0; }; @@ -365,34 +317,4 @@ const styles = { flexDirection: "column", }, }), - - resourceData: (theme) => ({ - padding: 24, - margin: "-48px 0 0 -48px", - display: "flex", - flexWrap: "wrap", - gap: 48, - rowGap: 24, - marginBottom: 24, - fontSize: 14, - background: `linear-gradient(180deg, ${theme.palette.background.default} 0%, rgba(0, 0, 0, 0) 100%)`, - }), - - resourceDataItem: () => ({ - lineHeight: "1.5", - }), - - resourceDataItemLabel: (theme) => ({ - fontSize: 13, - color: theme.palette.text.secondary, - textOverflow: "ellipsis", - overflow: "hidden", - whiteSpace: "nowrap", - }), - - resourceDataItemValue: () => ({ - textOverflow: "ellipsis", - overflow: "hidden", - whiteSpace: "nowrap", - }), } satisfies Record>;