feat: Show custom resource icons in the UI (#4020)

This commit is contained in:
Bruno Quaresma
2022-09-13 11:32:59 -03:00
committed by GitHub
parent 83c35bb916
commit 214e59452f
60 changed files with 282 additions and 220 deletions
+1
View File
@@ -637,6 +637,7 @@ export interface WorkspaceResource {
readonly type: string
readonly name: string
readonly hide: boolean
readonly icon: string
readonly agents?: WorkspaceAgent[]
readonly metadata?: WorkspaceResourceMetadata[]
}
@@ -1,4 +1,5 @@
import { Story } from "@storybook/react"
import { MockWorkspaceResource } from "testHelpers/entities"
import { ResourceAvatar, ResourceAvatarProps } from "./ResourceAvatar"
export default {
@@ -10,25 +11,40 @@ const Template: Story<ResourceAvatarProps> = (args) => <ResourceAvatar {...args}
export const VolumeResource = Template.bind({})
VolumeResource.args = {
type: "docker_volume",
resource: {
...MockWorkspaceResource,
type: "docker_volume",
},
}
export const ComputeResource = Template.bind({})
ComputeResource.args = {
type: "docker_container",
resource: {
...MockWorkspaceResource,
type: "docker_container",
},
}
export const ImageResource = Template.bind({})
ImageResource.args = {
type: "docker_image",
resource: {
...MockWorkspaceResource,
type: "docker_image",
},
}
export const NullResource = Template.bind({})
NullResource.args = {
type: "null_resource",
resource: {
...MockWorkspaceResource,
type: "null_resource",
},
}
export const UnknownResource = Template.bind({})
UnknownResource.args = {
type: "noexistentvalue",
resource: {
...MockWorkspaceResource,
type: "noexistentvalue",
},
}
@@ -1,51 +1,47 @@
import Avatar from "@material-ui/core/Avatar"
import { makeStyles } from "@material-ui/core/styles"
import FolderIcon from "@material-ui/icons/FolderOutlined"
import ImageIcon from "@material-ui/icons/ImageOutlined"
import MemoryIcon from "@material-ui/icons/MemoryOutlined"
import WidgetsIcon from "@material-ui/icons/WidgetsOutlined"
import React from "react"
import { WorkspaceResource } from "../../api/typesGenerated"
// For this special case, we need to apply a different style because how this
// particular icon has been designed
const AdjustedMemoryIcon: typeof MemoryIcon = ({ style, ...props }) => {
return <MemoryIcon style={{ ...style, fontSize: 24 }} {...props} />
}
// NOTE@jsjoeio, @BrunoQuaresma
// NOTE @jsjoeio, @BrunoQuaresma
// These resources (i.e. docker_image, kubernetes_deployment) map to Terraform
// resource types. These are the most used ones and are based on user usage.
// We may want to update from time-to-time.
const iconByResource: Record<WorkspaceResource["type"], typeof MemoryIcon | undefined> = {
docker_volume: FolderIcon,
docker_container: AdjustedMemoryIcon,
docker_image: ImageIcon,
kubernetes_persistent_volume_claim: FolderIcon,
kubernetes_pod: AdjustedMemoryIcon,
google_compute_disk: FolderIcon,
google_compute_instance: AdjustedMemoryIcon,
aws_instance: AdjustedMemoryIcon,
kubernetes_deployment: AdjustedMemoryIcon,
null_resource: WidgetsIcon,
const iconPathByResource: Record<WorkspaceResource["type"], string> = {
docker_volume: "/icon/folder.svg",
docker_container: "/icon/memory.svg",
docker_image: "/icon/image.svg",
kubernetes_persistent_volume_claim: "/icon/folder.svg",
kubernetes_pod: "/icon/memory.svg",
google_compute_disk: "/icon/folder.svg",
google_compute_instance: "/icon/memory.svg",
aws_instance: "/icon/memory.svg",
kubernetes_deployment: "/icon/memory.svg",
null_resource: "/icon/widgets.svg",
}
export type ResourceAvatarProps = { type: WorkspaceResource["type"] }
export type ResourceAvatarProps = { resource: WorkspaceResource }
export const ResourceAvatar: React.FC<ResourceAvatarProps> = ({ type }) => {
const IconComponent = iconByResource[type] ?? WidgetsIcon
export const ResourceAvatar: React.FC<ResourceAvatarProps> = ({ resource }) => {
const hasIcon = resource.icon && resource.icon !== ""
const avatarSrc = hasIcon
? resource.icon
: // resource.type is dynamic so iconPathByResource[resource.type] can be null
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
iconPathByResource[resource.type] ?? iconPathByResource["null_resource"]
const styles = useStyles()
return (
<Avatar className={styles.resourceAvatar}>
<IconComponent style={{ fontSize: 20 }} />
</Avatar>
)
return <Avatar className={styles.resourceAvatar} src={avatarSrc} />
}
const useStyles = makeStyles((theme) => ({
resourceAvatar: {
color: theme.palette.info.contrastText,
backgroundColor: theme.palette.info.main,
"& img": {
width: 20,
height: 20,
},
},
}))
@@ -49,7 +49,7 @@ export const ResourceAvatarData: FC<ResourceAvatarDataProps> = ({ resource }) =>
return (
<div className={styles.root}>
<div className={styles.avatarWrapper}>
<ResourceAvatar type={resource.type} />
<ResourceAvatar resource={resource} />
</div>
<TableCellData>
@@ -61,7 +61,7 @@ export const TemplateResourcesTable: FC<React.PropsWithChildren<TemplateResource
title={resource.name}
subtitle={resource.type}
highlightTitle
avatar={<ResourceAvatar type={resource.type} />}
avatar={<ResourceAvatar resource={resource} />}
/>
</TableCell>
<TableCell colSpan={3}></TableCell>
@@ -79,7 +79,7 @@ export const TemplateResourcesTable: FC<React.PropsWithChildren<TemplateResource
title={resource.name}
subtitle={resource.type}
highlightTitle
avatar={<ResourceAvatar type={resource.type} />}
avatar={<ResourceAvatar resource={resource} />}
/>
</TableCell>
)}
+3
View File
@@ -394,6 +394,7 @@ export const MockWorkspaceResource: TypesGen.WorkspaceResource = {
type: "google_compute_disk",
workspace_transition: "start",
hide: false,
icon: "",
metadata: [
{ key: "type", value: "a-workspace-resource", sensitive: false },
{ key: "api_key", value: "12345678", sensitive: true },
@@ -409,6 +410,7 @@ export const MockWorkspaceResource2: TypesGen.WorkspaceResource = {
type: "google_compute_disk",
workspace_transition: "start",
hide: false,
icon: "",
metadata: [
{ key: "type", value: "google_compute_disk", sensitive: false },
{ key: "size", value: "32GB", sensitive: false },
@@ -424,6 +426,7 @@ export const MockWorkspaceResource3: TypesGen.WorkspaceResource = {
type: "google_compute_disk",
workspace_transition: "start",
hide: true,
icon: "",
metadata: [
{ key: "type", value: "google_compute_disk", sensitive: false },
{ key: "size", value: "32GB", sensitive: false },
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48" fill="#FFF"><path d="M24 22q-8.05 0-13.025-2.45T6 14q0-3.15 4.975-5.575Q15.95 6 24 6t13.025 2.425Q42 10.85 42 14q0 3.1-4.975 5.55Q32.05 22 24 22Zm0 10q-7.3 0-12.65-2.2Q6 27.6 6 24.5v-5q0 1.95 1.875 3.375t4.65 2.35q2.775.925 5.9 1.35Q21.55 27 24 27q2.5 0 5.6-.425 3.1-.425 5.875-1.325 2.775-.9 4.65-2.325Q42 21.5 42 19.5v5q0 3.1-5.35 5.3Q31.3 32 24 32Zm0 10q-7.3 0-12.65-2.2Q6 37.6 6 34.5v-5q0 1.95 1.875 3.375t4.65 2.35q2.775.925 5.9 1.35Q21.55 37 24 37q2.5 0 5.6-.425 3.1-.425 5.875-1.325 2.775-.9 4.65-2.325Q42 31.5 42 29.5v5q0 3.1-5.35 5.3Q31.3 42 24 42Z"/></svg>

After

Width:  |  Height:  |  Size: 630 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48" fill="#FFF"><path d="M7.05 40q-1.2 0-2.1-.925-.9-.925-.9-2.075V11q0-1.15.9-2.075Q5.85 8 7.05 8h14l3 3h17q1.15 0 2.075.925.925.925.925 2.075v23q0 1.15-.925 2.075Q42.2 40 41.05 40Zm0-29v26h34V14H22.8l-3-3H7.05Zm0 0v26Z"/></svg>

After

Width:  |  Height:  |  Size: 289 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48" fill="#FFF"><path d="M9 42q-1.2 0-2.1-.9Q6 40.2 6 39V9q0-1.2.9-2.1Q7.8 6 9 6h30q1.2 0 2.1.9.9.9.9 2.1v30q0 1.2-.9 2.1-.9.9-2.1.9Zm0-3h30V9H9v30Zm2.8-4.85h24.45l-7.35-9.8-6.6 8.55-4.65-6.35ZM9 39V9v30Z"/></svg>

After

Width:  |  Height:  |  Size: 273 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48" fill="#FFF"><path d="M18.85 29.15V18.9H29.1v10.25Zm3-3h4.25V21.9h-4.25ZM18 42v-4h-5q-1.2 0-2.1-.9-.9-.9-.9-2.1v-5H6v-3h4v-6.2H6v-3h4v-5q0-1.2.9-2.1.9-.9 2.1-.9h5V6h3v3.8h6.2V6h3v3.8h5q1.2 0 2.1.9.9.9.9 2.1v5H42v3h-3.8V27H42v3h-3.8v5q0 1.2-.9 2.1-.9.9-2.1.9h-5v4h-3v-4H21v4Zm17.2-7V12.8H13V35ZM24 24Z"/></svg>

After

Width:  |  Height:  |  Size: 372 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48" fill="#FFF"><path d="M33.95 24.7 23.3 14.05 33.95 3.4 44.6 14.05ZM6 21.1V6.05h15.05V21.1ZM26.9 42V26.95h15.05V42ZM6 42V26.95h15.05V42Zm3-23.9h9.05V9.05H9Zm25.1 2.55 6.45-6.45-6.45-6.45-6.45 6.45ZM29.9 39h9.05v-9.05H29.9ZM9 39h9.05v-9.05H9Zm9.05-20.9Zm9.6-3.9Zm-9.6 15.75Zm11.85 0Z"/></svg>

After

Width:  |  Height:  |  Size: 353 B