mirror of
https://github.com/coder/coder.git
synced 2026-09-22 13:10:21 +08:00
feat: Add metadata support to the UI (#3431)
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
import IconButton from "@material-ui/core/IconButton"
|
||||
import { makeStyles } from "@material-ui/core/styles"
|
||||
import Tooltip from "@material-ui/core/Tooltip"
|
||||
import VisibilityOffOutlined from "@material-ui/icons/VisibilityOffOutlined"
|
||||
import VisibilityOutlined from "@material-ui/icons/VisibilityOutlined"
|
||||
import { WorkspaceResource } from "api/typesGenerated"
|
||||
import { FC, useState } from "react"
|
||||
import { TableCellData, TableCellDataPrimary } from "../TableCellData/TableCellData"
|
||||
import { ResourceAvatar } from "./ResourceAvatar"
|
||||
|
||||
const Language = {
|
||||
showLabel: "Show value",
|
||||
hideLabel: "Hide value",
|
||||
}
|
||||
|
||||
const SensitiveValue: React.FC<{ value: string }> = ({ value }) => {
|
||||
const [shouldDisplay, setShouldDisplay] = useState(false)
|
||||
const styles = useStyles()
|
||||
const displayValue = shouldDisplay ? value : "••••••••"
|
||||
const buttonLabel = shouldDisplay ? Language.hideLabel : Language.showLabel
|
||||
const icon = shouldDisplay ? <VisibilityOffOutlined /> : <VisibilityOutlined />
|
||||
|
||||
return (
|
||||
<div className={styles.sensitiveValue}>
|
||||
{displayValue}
|
||||
<Tooltip title={buttonLabel}>
|
||||
<IconButton
|
||||
className={styles.button}
|
||||
onClick={() => {
|
||||
setShouldDisplay((value) => !value)
|
||||
}}
|
||||
size="small"
|
||||
aria-label={buttonLabel}
|
||||
>
|
||||
{icon}
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export interface ResourceAvatarDataProps {
|
||||
resource: WorkspaceResource
|
||||
}
|
||||
|
||||
export const ResourceAvatarData: FC<ResourceAvatarDataProps> = ({ resource }) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
<div className={styles.avatarWrapper}>
|
||||
<ResourceAvatar type={resource.type} />
|
||||
</div>
|
||||
|
||||
<TableCellData>
|
||||
<TableCellDataPrimary highlight>{resource.name}</TableCellDataPrimary>
|
||||
<div className={styles.data}>
|
||||
{resource.metadata?.map((metadata) => (
|
||||
<div key={metadata.key} className={styles.dataRow}>
|
||||
<strong>{metadata.key}:</strong>
|
||||
{metadata.sensitive ? (
|
||||
<SensitiveValue value={metadata.value} />
|
||||
) : (
|
||||
<div>{metadata.value}</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</TableCellData>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
root: {
|
||||
display: "flex",
|
||||
},
|
||||
|
||||
avatarWrapper: {
|
||||
marginRight: theme.spacing(3),
|
||||
paddingTop: theme.spacing(0.5),
|
||||
},
|
||||
|
||||
data: {
|
||||
color: theme.palette.text.secondary,
|
||||
fontSize: 14,
|
||||
marginTop: theme.spacing(0.75),
|
||||
display: "grid",
|
||||
gridAutoFlow: "row",
|
||||
whiteSpace: "nowrap",
|
||||
gap: theme.spacing(0.75),
|
||||
},
|
||||
|
||||
dataRow: {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
|
||||
"& strong": {
|
||||
marginRight: theme.spacing(1),
|
||||
},
|
||||
},
|
||||
|
||||
sensitiveValue: {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
},
|
||||
|
||||
button: {
|
||||
marginLeft: theme.spacing(0.5),
|
||||
color: "inherit",
|
||||
|
||||
"& .MuiSvgIcon-root": {
|
||||
width: 16,
|
||||
height: 16,
|
||||
},
|
||||
},
|
||||
}))
|
||||
@@ -9,7 +9,6 @@ import useTheme from "@material-ui/styles/useTheme"
|
||||
import { ErrorSummary } from "components/ErrorSummary/ErrorSummary"
|
||||
import { FC } from "react"
|
||||
import { Workspace, WorkspaceResource } from "../../api/typesGenerated"
|
||||
import { AvatarData } from "../../components/AvatarData/AvatarData"
|
||||
import { getDisplayAgentStatus } from "../../util/workspace"
|
||||
import { AppLink } from "../AppLink/AppLink"
|
||||
import { SSHButton } from "../SSHButton/SSHButton"
|
||||
@@ -18,7 +17,7 @@ import { TableHeaderRow } from "../TableHeaders/TableHeaders"
|
||||
import { TerminalLink } from "../TerminalLink/TerminalLink"
|
||||
import { AgentHelpTooltip } from "../Tooltips/AgentHelpTooltip"
|
||||
import { ResourcesHelpTooltip } from "../Tooltips/ResourcesHelpTooltip"
|
||||
import { ResourceAvatar } from "./ResourceAvatar"
|
||||
import { ResourceAvatarData } from "./ResourceAvatarData"
|
||||
|
||||
const Language = {
|
||||
resources: "Resources",
|
||||
@@ -73,14 +72,7 @@ export const Resources: FC<ResourcesProps> = ({
|
||||
/* We need to initialize the agents to display the resource */
|
||||
}
|
||||
const agents = resource.agents ?? [null]
|
||||
const resourceName = (
|
||||
<AvatarData
|
||||
avatar={<ResourceAvatar type={resource.type} />}
|
||||
title={resource.name}
|
||||
subtitle={resource.type}
|
||||
highlightTitle
|
||||
/>
|
||||
)
|
||||
const resourceName = <ResourceAvatarData resource={resource} />
|
||||
|
||||
return agents.map((agent, agentIndex) => {
|
||||
{
|
||||
|
||||
@@ -287,12 +287,20 @@ export const MockWorkspaceResource: TypesGen.WorkspaceResource = {
|
||||
name: "a-workspace-resource",
|
||||
type: "google_compute_disk",
|
||||
workspace_transition: "start",
|
||||
metadata: [
|
||||
{ key: "type", value: "a-workspace-resource", sensitive: false },
|
||||
{ key: "api_key", value: "12345678", sensitive: true },
|
||||
],
|
||||
}
|
||||
|
||||
export const MockWorkspaceResource2 = {
|
||||
...MockWorkspaceResource,
|
||||
id: "test-workspace-resource-2",
|
||||
name: "another-workspace-resource",
|
||||
metadata: [
|
||||
{ key: "type", value: "google_compute_disk", sensitive: false },
|
||||
{ key: "size", value: "32GB", sensitive: false },
|
||||
],
|
||||
}
|
||||
|
||||
export const MockUserAgent: Types.UserAgent = {
|
||||
|
||||
Reference in New Issue
Block a user