mirror of
https://github.com/coder/coder.git
synced 2026-09-23 05:43:53 +08:00
refactor(site): Remove version and add template link in workspaces page (#5990)
This commit is contained in:
@@ -4,7 +4,7 @@ import { Stack } from "components/Stack/Stack"
|
||||
import { makeStyles } from "@material-ui/core/styles"
|
||||
|
||||
export interface AvatarDataProps {
|
||||
title: string
|
||||
title: string | JSX.Element
|
||||
subtitle?: string
|
||||
src?: string
|
||||
avatar?: React.ReactNode
|
||||
|
||||
@@ -1,13 +1,31 @@
|
||||
import { makeStyles, Theme, useTheme } from "@material-ui/core/styles"
|
||||
import { FC } from "react"
|
||||
|
||||
import Icon from "@material-ui/icons/Brightness1"
|
||||
import dayjs from "dayjs"
|
||||
import relativeTime from "dayjs/plugin/relativeTime"
|
||||
import { colors } from "theme/colors"
|
||||
import { Stack } from "components/Stack/Stack"
|
||||
|
||||
dayjs.extend(relativeTime)
|
||||
|
||||
type CircleProps = { color: string; variant?: "solid" | "outlined" }
|
||||
|
||||
const Circle: FC<CircleProps> = ({ color, variant = "solid" }) => {
|
||||
const styles = useCircleStyles({ color, variant })
|
||||
return <div className={styles.root} />
|
||||
}
|
||||
|
||||
const useCircleStyles = makeStyles((theme) => ({
|
||||
root: {
|
||||
width: theme.spacing(1),
|
||||
height: theme.spacing(1),
|
||||
backgroundColor: (props: CircleProps) =>
|
||||
props.variant === "solid" ? props.color : undefined,
|
||||
border: (props: CircleProps) =>
|
||||
props.variant === "outlined" ? `1px solid ${props.color}` : undefined,
|
||||
borderRadius: 9999,
|
||||
},
|
||||
}))
|
||||
|
||||
interface LastUsedProps {
|
||||
lastUsedAt: string
|
||||
}
|
||||
@@ -15,55 +33,44 @@ interface LastUsedProps {
|
||||
export const LastUsed: FC<LastUsedProps> = ({ lastUsedAt }) => {
|
||||
const theme: Theme = useTheme()
|
||||
const styles = useStyles()
|
||||
|
||||
const t = dayjs(lastUsedAt)
|
||||
const now = dayjs()
|
||||
|
||||
let color = theme.palette.text.secondary
|
||||
let message = t.fromNow()
|
||||
let displayCircle = true
|
||||
let circle: JSX.Element = (
|
||||
<Circle color={theme.palette.text.secondary} variant="outlined" />
|
||||
)
|
||||
|
||||
if (t.isAfter(now.subtract(1, "hour"))) {
|
||||
color = colors.green[9]
|
||||
circle = <Circle color={colors.green[9]} />
|
||||
// Since the agent reports on a 10m interval,
|
||||
// the last_used_at can be inaccurate when recent.
|
||||
message = "Now"
|
||||
} else if (t.isAfter(now.subtract(3, "day"))) {
|
||||
color = theme.palette.text.secondary
|
||||
circle = <Circle color={theme.palette.text.secondary} />
|
||||
} else if (t.isAfter(now.subtract(1, "month"))) {
|
||||
color = theme.palette.warning.light
|
||||
circle = <Circle color={theme.palette.warning.light} />
|
||||
} else if (t.isAfter(now.subtract(100, "year"))) {
|
||||
color = colors.red[10]
|
||||
circle = <Circle color={colors.red[10]} />
|
||||
} else {
|
||||
// color = theme.palette.error.light
|
||||
message = "Never"
|
||||
displayCircle = false
|
||||
}
|
||||
|
||||
return (
|
||||
<span className={styles.root}>
|
||||
<span
|
||||
style={{
|
||||
color: color,
|
||||
display: displayCircle ? undefined : "none",
|
||||
}}
|
||||
>
|
||||
<Icon className={styles.icon} />
|
||||
</span>
|
||||
<Stack
|
||||
className={styles.root}
|
||||
direction="row"
|
||||
spacing={1}
|
||||
alignItems="center"
|
||||
>
|
||||
{circle}
|
||||
<span data-chromatic="ignore">{message}</span>
|
||||
</span>
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
root: {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
icon: {
|
||||
marginRight: 8,
|
||||
width: 10,
|
||||
height: 10,
|
||||
},
|
||||
}))
|
||||
|
||||
@@ -198,7 +198,7 @@ export const HelpTooltipLinksGroup: FC<PropsWithChildren<unknown>> = ({
|
||||
const getButtonSpacingFromSize = (size?: Size): number => {
|
||||
switch (size) {
|
||||
case "small":
|
||||
return 2.75
|
||||
return 2.5
|
||||
case "medium":
|
||||
default:
|
||||
return 3
|
||||
@@ -208,7 +208,7 @@ const getButtonSpacingFromSize = (size?: Size): number => {
|
||||
const getIconSpacingFromSize = (size?: Size): number => {
|
||||
switch (size) {
|
||||
case "small":
|
||||
return 1.75
|
||||
return 1.5
|
||||
case "medium":
|
||||
default:
|
||||
return 2
|
||||
|
||||
@@ -6,12 +6,15 @@ import { AvatarData } from "components/AvatarData/AvatarData"
|
||||
import { WorkspaceStatusBadge } from "components/WorkspaceStatusBadge/WorkspaceStatusBadge"
|
||||
import { useClickable } from "hooks/useClickable"
|
||||
import { FC } from "react"
|
||||
import { useNavigate } from "react-router-dom"
|
||||
import { useNavigate, Link as RouterLink } from "react-router-dom"
|
||||
import { getDisplayWorkspaceTemplateName } from "util/workspace"
|
||||
import { LastUsed } from "../LastUsed/LastUsed"
|
||||
import { Workspace } from "api/typesGenerated"
|
||||
import { OutdatedHelpTooltip } from "components/Tooltips/OutdatedHelpTooltip"
|
||||
import { Avatar } from "components/Avatar/Avatar"
|
||||
import { Stack } from "components/Stack/Stack"
|
||||
import TemplateLinkIcon from "@material-ui/icons/OpenInNewOutlined"
|
||||
import Link from "@material-ui/core/Link"
|
||||
|
||||
export const WorkspacesRow: FC<{
|
||||
workspace: Workspace
|
||||
@@ -36,7 +39,18 @@ export const WorkspacesRow: FC<{
|
||||
>
|
||||
<TableCell>
|
||||
<AvatarData
|
||||
title={workspace.name}
|
||||
title={
|
||||
<Stack direction="row" spacing={0} alignItems="center">
|
||||
{workspace.name}
|
||||
{workspace.outdated && (
|
||||
<OutdatedHelpTooltip
|
||||
onUpdateVersion={() => {
|
||||
onUpdateWorkspace(workspace)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Stack>
|
||||
}
|
||||
subtitle={workspace.owner_name}
|
||||
avatar={
|
||||
hasTemplateIcon && (
|
||||
@@ -46,19 +60,21 @@ export const WorkspacesRow: FC<{
|
||||
/>
|
||||
</TableCell>
|
||||
|
||||
<TableCell>{displayTemplateName}</TableCell>
|
||||
|
||||
<TableCell>
|
||||
<div className={styles.version}>
|
||||
{workspace.latest_build.template_version_name}
|
||||
{workspace.outdated && (
|
||||
<OutdatedHelpTooltip
|
||||
onUpdateVersion={() => {
|
||||
onUpdateWorkspace(workspace)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<Link
|
||||
component={RouterLink}
|
||||
to={`/templates/${workspace.template_name}`}
|
||||
className={styles.templateLink}
|
||||
title={`Go to ${displayTemplateName} page`}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
}}
|
||||
>
|
||||
<Stack direction="row" alignItems="center" spacing={1}>
|
||||
<TemplateLinkIcon className={styles.templateLinkIcon} />
|
||||
<span>{displayTemplateName}</span>
|
||||
</Stack>
|
||||
</Link>
|
||||
</TableCell>
|
||||
|
||||
<TableCell>
|
||||
@@ -99,18 +115,17 @@ const useStyles = makeStyles((theme) => ({
|
||||
paddingLeft: theme.spacing(2),
|
||||
},
|
||||
|
||||
templateIconWrapper: {
|
||||
// Same size then the avatar component
|
||||
width: 36,
|
||||
height: 36,
|
||||
padding: 2,
|
||||
templateLink: {
|
||||
color: theme.palette.text.secondary,
|
||||
|
||||
"& img": {
|
||||
width: "100%",
|
||||
"&:hover": {
|
||||
color: theme.palette.text.primary,
|
||||
textDecoration: "none",
|
||||
},
|
||||
},
|
||||
|
||||
version: {
|
||||
display: "flex",
|
||||
templateLinkIcon: {
|
||||
width: theme.spacing(1.5),
|
||||
height: theme.spacing(1.5),
|
||||
},
|
||||
}))
|
||||
|
||||
@@ -12,7 +12,6 @@ const Language = {
|
||||
name: "Name",
|
||||
template: "Template",
|
||||
lastUsed: "Last Used",
|
||||
version: "Version",
|
||||
status: "Status",
|
||||
lastBuiltBy: "Last Built By",
|
||||
}
|
||||
@@ -33,12 +32,11 @@ export const WorkspacesTable: FC<WorkspacesTableProps> = ({
|
||||
<Table>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell width="30%">{Language.name}</TableCell>
|
||||
<TableCell width="40%">{Language.name}</TableCell>
|
||||
<TableCell width="25%">{Language.template}</TableCell>
|
||||
<TableCell width="25%">{Language.version}</TableCell>
|
||||
<TableCell width="20%">{Language.lastUsed}</TableCell>
|
||||
<TableCell width="20%">{Language.status}</TableCell>
|
||||
<TableCell width="1%"></TableCell>
|
||||
<TableCell width="15%">{Language.status}</TableCell>
|
||||
<TableCell width="1%" />
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
|
||||
Reference in New Issue
Block a user