Skip to content

Commit cf8500f

Browse files
BrunoQuaresmaammario
authored andcommitted
refactor(site): Improve workspaces filtering (coder#7681)
1 parent 58adc7d commit cf8500f

29 files changed

+1148
-183
lines changed

coderd/apidoc/docs.go

+4-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

+6-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

codersdk/deployment.go

+3
Original file line numberDiff line numberDiff line change
@@ -1682,6 +1682,9 @@ const (
16821682
// https://github.com/coder/coder/milestone/19
16831683
ExperimentWorkspaceActions Experiment = "workspace_actions"
16841684

1685+
// New workspace filter
1686+
ExperimentWorkspaceFilter Experiment = "workspace_filter"
1687+
16851688
// Add new experiments here!
16861689
// ExperimentExample Experiment = "example"
16871690
)

docs/api/schemas.md

+1
Original file line numberDiff line numberDiff line change
@@ -2561,6 +2561,7 @@ CreateParameterRequest is a structure used to create a new parameter value for a
25612561
| ------------------- |
25622562
| `moons` |
25632563
| `workspace_actions` |
2564+
| `workspace_filter` |
25642565

25652566
## codersdk.Feature
25662567

site/.eslintrc.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ rules:
136136
"object-curly-spacing": "off"
137137
react-hooks/exhaustive-deps: warn
138138
react-hooks/rules-of-hooks: error
139+
react/display-name: "off"
139140
react/jsx-no-script-url:
140141
- error
141142
- - name: Link

site/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@
111111
"@testing-library/user-event": "14.4.3",
112112
"@types/jest": "29.4.0",
113113
"@types/node": "14.18.22",
114-
"@types/react": "18.0.15",
115-
"@types/react-dom": "18.0.6",
114+
"@types/react": "18.2.6",
115+
"@types/react-dom": "18.2.4",
116116
"@types/react-helmet": "6.1.5",
117117
"@types/react-syntax-highlighter": "15.5.5",
118118
"@types/react-virtualized-auto-sizer": "1.0.1",
File renamed without changes.

site/src/@types/i18n.d.ts

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import "i18next"
2+
3+
// https://github.com/i18next/react-i18next/issues/1543#issuecomment-1528679591
4+
declare module "i18next" {
5+
interface TypeOptions {
6+
returnNull: false
7+
allowObjectInHTMLChildren: false
8+
}
9+
export function t<T>(s: string): T
10+
}
File renamed without changes.

site/src/api/errors.ts

+3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ export const isApiValidationError = (error: unknown): error is ApiError => {
3434
return isApiError(error) && hasApiFieldErrors(error)
3535
}
3636

37+
export const hasError = (error: unknown) =>
38+
error !== undefined && error !== null
39+
3740
export const mapApiErrorToFieldErrors = (
3841
apiErrorResponse: ApiErrorResponse,
3942
): FieldErrors => {

site/src/api/typesGenerated.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -1386,8 +1386,12 @@ export const Entitlements: Entitlement[] = [
13861386
]
13871387

13881388
// From codersdk/deployment.go
1389-
export type Experiment = "moons" | "workspace_actions"
1390-
export const Experiments: Experiment[] = ["moons", "workspace_actions"]
1389+
export type Experiment = "moons" | "workspace_actions" | "workspace_filter"
1390+
export const Experiments: Experiment[] = [
1391+
"moons",
1392+
"workspace_actions",
1393+
"workspace_filter",
1394+
]
13911395

13921396
// From codersdk/deployment.go
13931397
export type FeatureName =

site/src/components/DeploymentBanner/DeploymentBannerView.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { DeploymentStats, WorkspaceStatus } from "api/typesGenerated"
22
import { FC, useMemo, useEffect, useState } from "react"
33
import prettyBytes from "pretty-bytes"
4-
import { getStatus } from "components/WorkspaceStatusBadge/WorkspaceStatusBadge"
54
import BuildingIcon from "@mui/icons-material/Build"
65
import { makeStyles } from "@mui/styles"
76
import { RocketIcon } from "components/Icons/RocketIcon"
@@ -19,6 +18,7 @@ import dayjs from "dayjs"
1918
import CollectedIcon from "@mui/icons-material/Compare"
2019
import RefreshIcon from "@mui/icons-material/Refresh"
2120
import Button from "@mui/material/Button"
21+
import { getDisplayWorkspaceStatus } from "utils/workspace"
2222

2323
export const bannerHeight = 36
2424

@@ -218,7 +218,7 @@ const WorkspaceBuildValue: FC<{
218218
count?: number
219219
}> = ({ status, count }) => {
220220
const styles = useStyles()
221-
const displayStatus = getStatus(status)
221+
const displayStatus = getDisplayWorkspaceStatus(status)
222222
let statusText = displayStatus.text
223223
let icon = displayStatus.icon
224224
if (status === "starting") {

site/src/components/UserAvatar/UserAvatar.tsx

+6-8
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,19 @@
1-
import { Avatar } from "components/Avatar/Avatar"
1+
import { Avatar, AvatarProps } from "components/Avatar/Avatar"
22
import { FC } from "react"
33

4-
export interface UserAvatarProps {
4+
export type UserAvatarProps = {
55
username: string
66
avatarURL?: string
7-
// It is needed to work with the AvatarGroup so it can pass the
8-
// MuiAvatarGroup-avatar className
9-
className?: string
10-
}
7+
} & AvatarProps
118

129
export const UserAvatar: FC<UserAvatarProps> = ({
1310
username,
1411
avatarURL,
15-
className,
12+
13+
...avatarProps
1614
}) => {
1715
return (
18-
<Avatar title={username} src={avatarURL} className={className}>
16+
<Avatar title={username} src={avatarURL} {...avatarProps}>
1917
{username}
2018
</Avatar>
2119
)

site/src/components/WorkspaceStatusBadge/WorkspaceStatusBadge.tsx

+8-85
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
1-
import CircularProgress from "@mui/material/CircularProgress"
2-
import ErrorIcon from "@mui/icons-material/ErrorOutline"
3-
import StopIcon from "@mui/icons-material/StopOutlined"
4-
import PlayIcon from "@mui/icons-material/PlayArrowOutlined"
5-
import QueuedIcon from "@mui/icons-material/HourglassEmpty"
6-
import { Workspace, WorkspaceBuild } from "api/typesGenerated"
1+
import { Workspace } from "api/typesGenerated"
72
import { Pill } from "components/Pill/Pill"
8-
import i18next from "i18next"
93
import { FC, PropsWithChildren } from "react"
104
import { makeStyles } from "@mui/styles"
115
import { combineClasses } from "utils/combineClasses"
@@ -14,82 +8,7 @@ import {
148
ImpendingDeletionBadge,
159
ImpendingDeletionText,
1610
} from "components/WorkspaceDeletion"
17-
18-
const LoadingIcon: FC = () => {
19-
return <CircularProgress size={10} style={{ color: "#FFF" }} />
20-
}
21-
22-
export const getStatus = (buildStatus: WorkspaceBuild["status"]) => {
23-
const { t } = i18next
24-
25-
switch (buildStatus) {
26-
case undefined:
27-
return {
28-
text: t("workspaceStatus.loading", { ns: "common" }),
29-
icon: <LoadingIcon />,
30-
} as const
31-
case "running":
32-
return {
33-
type: "success",
34-
text: t("workspaceStatus.running", { ns: "common" }),
35-
icon: <PlayIcon />,
36-
} as const
37-
case "starting":
38-
return {
39-
type: "success",
40-
text: t("workspaceStatus.starting", { ns: "common" }),
41-
icon: <LoadingIcon />,
42-
} as const
43-
case "stopping":
44-
return {
45-
type: "warning",
46-
text: t("workspaceStatus.stopping", { ns: "common" }),
47-
icon: <LoadingIcon />,
48-
} as const
49-
case "stopped":
50-
return {
51-
type: "warning",
52-
text: t("workspaceStatus.stopped", { ns: "common" }),
53-
icon: <StopIcon />,
54-
} as const
55-
case "deleting":
56-
return {
57-
type: "warning",
58-
text: t("workspaceStatus.deleting", { ns: "common" }),
59-
icon: <LoadingIcon />,
60-
} as const
61-
case "deleted":
62-
return {
63-
type: "error",
64-
text: t("workspaceStatus.deleted", { ns: "common" }),
65-
icon: <ErrorIcon />,
66-
} as const
67-
case "canceling":
68-
return {
69-
type: "warning",
70-
text: t("workspaceStatus.canceling", { ns: "common" }),
71-
icon: <LoadingIcon />,
72-
} as const
73-
case "canceled":
74-
return {
75-
type: "warning",
76-
text: t("workspaceStatus.canceled", { ns: "common" }),
77-
icon: <ErrorIcon />,
78-
} as const
79-
case "failed":
80-
return {
81-
type: "error",
82-
text: t("workspaceStatus.failed", { ns: "common" }),
83-
icon: <ErrorIcon />,
84-
} as const
85-
case "pending":
86-
return {
87-
type: "info",
88-
text: t("workspaceStatus.pending", { ns: "common" }),
89-
icon: <QueuedIcon />,
90-
} as const
91-
}
92-
}
11+
import { getDisplayWorkspaceStatus } from "utils/workspace"
9312

9413
export type WorkspaceStatusBadgeProps = {
9514
workspace: Workspace
@@ -99,7 +18,9 @@ export type WorkspaceStatusBadgeProps = {
9918
export const WorkspaceStatusBadge: FC<
10019
PropsWithChildren<WorkspaceStatusBadgeProps>
10120
> = ({ workspace, className }) => {
102-
const { text, icon, type } = getStatus(workspace.latest_build.status)
21+
const { text, icon, type } = getDisplayWorkspaceStatus(
22+
workspace.latest_build.status,
23+
)
10324
return (
10425
<ChooseOne>
10526
{/* <ImpendingDeletionBadge/> determines its own visibility */}
@@ -117,7 +38,9 @@ export const WorkspaceStatusText: FC<
11738
PropsWithChildren<WorkspaceStatusBadgeProps>
11839
> = ({ workspace, className }) => {
11940
const styles = useStyles()
120-
const { text, type } = getStatus(workspace.latest_build.status)
41+
const { text, type } = getDisplayWorkspaceStatus(
42+
workspace.latest_build.status,
43+
)
12144

12245
return (
12346
<ChooseOne>

site/src/hooks/index.ts

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ export * from "./useClickable"
22
export * from "./useClickableTableRow"
33
export * from "./useClipboard"
44
export * from "./useFeatureVisibility"
5-
export * from "./useFilter"
65
export * from "./useLocalStorage"
76
export * from "./useMe"
87
export * from "./useOrganizationId"

site/src/hooks/useFilter.ts

-21
This file was deleted.

site/src/hooks/usePagination.ts

+7-9
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
import { DEFAULT_RECORDS_PER_PAGE } from "components/PaginationWidget/utils"
22
import { useSearchParams } from "react-router-dom"
33

4-
type UsePaginationResult = {
5-
page: number
6-
limit: number
7-
goToPage: (page: number) => void
8-
}
9-
10-
export const usePagination = (): UsePaginationResult => {
11-
const [searchParams, setSearchParams] = useSearchParams()
12-
const page = searchParams.get("page") ? Number(searchParams.get("page")) : 0
4+
export const usePagination = ({
5+
searchParamsResult,
6+
}: {
7+
searchParamsResult: ReturnType<typeof useSearchParams>
8+
}) => {
9+
const [searchParams, setSearchParams] = searchParamsResult
10+
const page = searchParams.get("page") ? Number(searchParams.get("page")) : 1
1311
const limit = DEFAULT_RECORDS_PER_PAGE
1412

1513
const goToPage = (page: number) => {

site/src/pages/UserSettingsPage/TokensPage/TokensPage.tsx

+8-8
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { FC, PropsWithChildren, useState } from "react"
22
import { Section } from "components/SettingsLayout/Section"
33
import { TokensPageView } from "./TokensPageView"
44
import makeStyles from "@mui/styles/makeStyles"
5-
import { useTranslation, Trans } from "react-i18next"
5+
import { useTranslation } from "react-i18next"
66
import { useTokensData } from "./hooks"
77
import { ConfirmDeleteDialog } from "./components"
88
import { Stack } from "components/Stack/Stack"
@@ -16,12 +16,6 @@ export const TokensPage: FC<PropsWithChildren<unknown>> = () => {
1616
const { t } = useTranslation("tokensPage")
1717

1818
const cliCreateCommand = "coder tokens create"
19-
const description = (
20-
<Trans t={t} i18nKey="description" values={{ cliCreateCommand }}>
21-
Tokens are used to authenticate with the Coder API. You can create a token
22-
with the Coder CLI using the <code>{{ cliCreateCommand }}</code> command.
23-
</Trans>
24-
)
2519

2620
const TokenActions = () => (
2721
<Stack direction="row" justifyContent="end" className={styles.tokenActions}>
@@ -52,7 +46,13 @@ export const TokensPage: FC<PropsWithChildren<unknown>> = () => {
5246
<Section
5347
title={t("title")}
5448
className={styles.section}
55-
description={description}
49+
description={
50+
<>
51+
Tokens are used to authenticate with the Coder API. You can create a
52+
token with the Coder CLI using the <code>{cliCreateCommand}</code>{" "}
53+
command.
54+
</>
55+
}
5656
layout="fluid"
5757
>
5858
<TokenActions />

0 commit comments

Comments
 (0)