From 15fc3db68600ff5d152f2d926b6ea14fbdc65c96 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Thu, 24 Aug 2023 17:25:20 +0000 Subject: [PATCH 1/8] Remove experiment from BE --- coderd/apidoc/docs.go | 6 ++---- coderd/apidoc/swagger.json | 6 ++---- codersdk/deployment.go | 4 ---- docs/api/schemas.md | 1 - site/src/api/typesGenerated.ts | 2 -- 5 files changed, 4 insertions(+), 15 deletions(-) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 0af41e03271ea..033ded970c5d4 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -8125,8 +8125,7 @@ const docTemplate = `{ "tailnet_pg_coordinator", "single_tailnet", "template_restart_requirement", - "deployment_health_page", - "workspaces_batch_actions" + "deployment_health_page" ], "x-enum-varnames": [ "ExperimentMoons", @@ -8134,8 +8133,7 @@ const docTemplate = `{ "ExperimentTailnetPGCoordinator", "ExperimentSingleTailnet", "ExperimentTemplateRestartRequirement", - "ExperimentDeploymentHealthPage", - "ExperimentWorkspacesBatchActions" + "ExperimentDeploymentHealthPage" ] }, "codersdk.Feature": { diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index 008534328fd70..e373cbe46874b 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -7276,8 +7276,7 @@ "tailnet_pg_coordinator", "single_tailnet", "template_restart_requirement", - "deployment_health_page", - "workspaces_batch_actions" + "deployment_health_page" ], "x-enum-varnames": [ "ExperimentMoons", @@ -7285,8 +7284,7 @@ "ExperimentTailnetPGCoordinator", "ExperimentSingleTailnet", "ExperimentTemplateRestartRequirement", - "ExperimentDeploymentHealthPage", - "ExperimentWorkspacesBatchActions" + "ExperimentDeploymentHealthPage" ] }, "codersdk.Feature": { diff --git a/codersdk/deployment.go b/codersdk/deployment.go index a8356b6816554..ef0f34711c3ce 100644 --- a/codersdk/deployment.go +++ b/codersdk/deployment.go @@ -1939,9 +1939,6 @@ const ( // Deployment health page ExperimentDeploymentHealthPage Experiment = "deployment_health_page" - // Workspaces batch actions - ExperimentWorkspacesBatchActions Experiment = "workspaces_batch_actions" - // Add new experiments here! // ExperimentExample Experiment = "example" ) @@ -1952,7 +1949,6 @@ const ( // not be included here and will be essentially hidden. var ExperimentsAll = Experiments{ ExperimentDeploymentHealthPage, - ExperimentWorkspacesBatchActions, } // Experiments is a list of experiments that are enabled for the deployment. diff --git a/docs/api/schemas.md b/docs/api/schemas.md index 3cb49b84bf833..3ee7d2814bd1a 100644 --- a/docs/api/schemas.md +++ b/docs/api/schemas.md @@ -2719,7 +2719,6 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in | `single_tailnet` | | `template_restart_requirement` | | `deployment_health_page` | -| `workspaces_batch_actions` | ## codersdk.Feature diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 39f5401d5ff29..d27f19aa8afd3 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -1604,7 +1604,6 @@ export type Experiment = | "tailnet_pg_coordinator" | "template_restart_requirement" | "workspace_actions" - | "workspaces_batch_actions" export const Experiments: Experiment[] = [ "deployment_health_page", "moons", @@ -1612,7 +1611,6 @@ export const Experiments: Experiment[] = [ "tailnet_pg_coordinator", "template_restart_requirement", "workspace_actions", - "workspaces_batch_actions", ] // From codersdk/deployment.go From b95a64335fe92f3221758e45a51a5ff9b2c1f4e9 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Thu, 24 Aug 2023 17:53:07 +0000 Subject: [PATCH 2/8] Remove feature checks and improve loading stat --- .../components/TableLoader/TableLoader.tsx | 50 +++--- .../components/UsersTable/UsersTableBody.tsx | 35 ++++- site/src/pages/GroupsPage/GroupsPageView.tsx | 30 +++- .../pages/TemplatesPage/TemplatesPageView.tsx | 36 ++++- .../pages/WorkspacesPage/WorkspacesPage.tsx | 10 +- .../WorkspacesPage/WorkspacesPageView.tsx | 3 - .../pages/WorkspacesPage/WorkspacesTable.tsx | 144 +++++++++++------- site/src/testHelpers/entities.ts | 1 - 8 files changed, 201 insertions(+), 108 deletions(-) diff --git a/site/src/components/TableLoader/TableLoader.tsx b/site/src/components/TableLoader/TableLoader.tsx index 9c569f08b208f..70851ce61af03 100644 --- a/site/src/components/TableLoader/TableLoader.tsx +++ b/site/src/components/TableLoader/TableLoader.tsx @@ -1,9 +1,7 @@ import { makeStyles } from "@mui/styles" import TableCell from "@mui/material/TableCell" -import TableRow from "@mui/material/TableRow" -import Skeleton from "@mui/material/Skeleton" -import { AvatarDataSkeleton } from "components/AvatarData/AvatarDataSkeleton" -import { FC } from "react" +import TableRow, { TableRowProps } from "@mui/material/TableRow" +import { FC, ReactNode, cloneElement, isValidElement } from "react" import { Loader } from "../Loader/Loader" export const TableLoader: FC = () => { @@ -25,35 +23,27 @@ const useStyles = makeStyles((theme) => ({ }, })) -export const TableLoaderSkeleton: FC<{ - columns: number +export const TableLoaderSkeleton = ({ + rows = 4, + children, +}: { rows?: number - useAvatarData?: boolean -}> = ({ columns, rows = 4, useAvatarData = false }) => { - const placeholderColumns = Array(columns).fill(undefined) - const placeholderRows = Array(rows).fill(undefined) - + children: ReactNode +}) => { + if (!isValidElement(children)) { + throw new Error( + "TableLoaderSkeleton children must be a valid React element", + ) + } return ( <> - {placeholderRows.map((_, rowIndex) => ( - - {placeholderColumns.map((_, columnIndex) => { - if (useAvatarData && columnIndex === 0) { - return ( - - - - ) - } - - return ( - - - - ) - })} - - ))} + {Array.from({ length: rows }, (_, i) => + cloneElement(children, { key: i }), + )} ) } + +export const TableRowSkeleton = (props: TableRowProps) => { + return +} diff --git a/site/src/components/UsersTable/UsersTableBody.tsx b/site/src/components/UsersTable/UsersTableBody.tsx index 82e154a3d0d0b..5c5fbd6beb42a 100644 --- a/site/src/components/UsersTable/UsersTableBody.tsx +++ b/site/src/components/UsersTable/UsersTableBody.tsx @@ -11,11 +11,16 @@ import * as TypesGen from "../../api/typesGenerated" import { combineClasses } from "../../utils/combineClasses" import { AvatarData } from "../AvatarData/AvatarData" import { EmptyState } from "../EmptyState/EmptyState" -import { TableLoaderSkeleton } from "../TableLoader/TableLoader" +import { + TableLoaderSkeleton, + TableRowSkeleton, +} from "../TableLoader/TableLoader" import { TableRowMenu } from "../TableRowMenu/TableRowMenu" import { EditRolesButton } from "components/EditRolesButton/EditRolesButton" import { Stack } from "components/Stack/Stack" import { EnterpriseBadge } from "components/DeploySettingsLayout/Badges" +import Skeleton from "@mui/material/Skeleton" +import { AvatarDataSkeleton } from "components/AvatarData/AvatarDataSkeleton" const isOwnerRole = (role: TypesGen.Role): boolean => { return role.name === "owner" @@ -80,7 +85,7 @@ export const UsersTableBody: FC< return ( - + @@ -252,3 +257,29 @@ const useStyles = makeStyles((theme) => ({ borderColor: theme.palette.info.light, }, })) + +const TableLoader = () => { + return ( + + + + + + + + + + + + + + + + + + + + + + ) +} diff --git a/site/src/pages/GroupsPage/GroupsPageView.tsx b/site/src/pages/GroupsPage/GroupsPageView.tsx index 1acb5e79cf769..5cac6e3bce238 100644 --- a/site/src/pages/GroupsPage/GroupsPageView.tsx +++ b/site/src/pages/GroupsPage/GroupsPageView.tsx @@ -15,7 +15,10 @@ import { AvatarData } from "components/AvatarData/AvatarData" import { ChooseOne, Cond } from "components/Conditionals/ChooseOne" import { EmptyState } from "components/EmptyState/EmptyState" import { Stack } from "components/Stack/Stack" -import { TableLoaderSkeleton } from "components/TableLoader/TableLoader" +import { + TableLoaderSkeleton, + TableRowSkeleton, +} from "components/TableLoader/TableLoader" import { UserAvatar } from "components/UserAvatar/UserAvatar" import { FC } from "react" import { Link as RouterLink, useNavigate } from "react-router-dom" @@ -23,6 +26,9 @@ import { Paywall } from "components/Paywall/Paywall" import { Group } from "api/typesGenerated" import { GroupAvatar } from "components/GroupAvatar/GroupAvatar" import { docs } from "utils/docs" +import Skeleton from "@mui/material/Skeleton" +import { Box } from "@mui/system" +import { AvatarDataSkeleton } from "components/AvatarData/AvatarDataSkeleton" export type GroupsPageViewProps = { groups: Group[] | undefined @@ -83,7 +89,7 @@ export const GroupsPageView: FC = ({ - + @@ -184,6 +190,26 @@ export const GroupsPageView: FC = ({ ) } +const TableLoader = () => { + return ( + + + + + + + + + + + + + + + + ) +} + const useStyles = makeStyles((theme) => ({ clickableTableRow: { cursor: "pointer", diff --git a/site/src/pages/TemplatesPage/TemplatesPageView.tsx b/site/src/pages/TemplatesPage/TemplatesPageView.tsx index 77a8edad916a1..4aad4c16b6603 100644 --- a/site/src/pages/TemplatesPage/TemplatesPageView.tsx +++ b/site/src/pages/TemplatesPage/TemplatesPageView.tsx @@ -24,7 +24,10 @@ import { PageHeaderTitle, } from "../../components/PageHeader/PageHeader" import { Stack } from "../../components/Stack/Stack" -import { TableLoaderSkeleton } from "../../components/TableLoader/TableLoader" +import { + TableLoaderSkeleton, + TableRowSkeleton, +} from "../../components/TableLoader/TableLoader" import { HelpTooltip, HelpTooltipLink, @@ -42,6 +45,9 @@ import ArrowForwardOutlined from "@mui/icons-material/ArrowForwardOutlined" import { Avatar } from "components/Avatar/Avatar" import { ErrorAlert } from "components/Alert/ErrorAlert" import { docs } from "utils/docs" +import Skeleton from "@mui/material/Skeleton" +import { Box } from "@mui/system" +import { AvatarDataSkeleton } from "components/AvatarData/AvatarDataSkeleton" export const Language = { developerCount: (activeCount: number): string => { @@ -196,7 +202,7 @@ export const TemplatesPageView: FC< - + @@ -222,6 +228,32 @@ export const TemplatesPageView: FC< ) } +const TableLoader = () => { + return ( + + + + + + + + + + + + + + + + + + + + + + ) +} + const useStyles = makeStyles((theme) => ({ templateIconWrapper: { // Same size then the avatar component diff --git a/site/src/pages/WorkspacesPage/WorkspacesPage.tsx b/site/src/pages/WorkspacesPage/WorkspacesPage.tsx index ed810e36769b3..e7e85e7fd1fed 100644 --- a/site/src/pages/WorkspacesPage/WorkspacesPage.tsx +++ b/site/src/pages/WorkspacesPage/WorkspacesPage.tsx @@ -1,9 +1,6 @@ import { usePagination } from "hooks/usePagination" import { Workspace } from "api/typesGenerated" -import { - useDashboard, - useIsWorkspaceActionsEnabled, -} from "components/Dashboard/DashboardProvider" +import { useIsWorkspaceActionsEnabled } from "components/Dashboard/DashboardProvider" import { FC, useEffect, useState } from "react" import { Helmet } from "react-helmet-async" import { pageTitle } from "utils/page" @@ -68,10 +65,6 @@ const WorkspacesPage: FC = () => { const [checkedWorkspaces, setCheckedWorkspaces] = useState([]) const [isDeletingAll, setIsDeletingAll] = useState(false) const [urlSearchParams] = searchParamsResult - const dashboard = useDashboard() - const isWorkspaceBatchActionsEnabled = - dashboard.experiments.includes("workspaces_batch_actions") || - process.env.NODE_ENV === "development" // We want to uncheck the selected workspaces always when the url changes // because of filtering or pagination @@ -86,7 +79,6 @@ const WorkspacesPage: FC = () => { page: number limit: number - isWorkspaceBatchActionsEnabled?: boolean onPageChange: (page: number) => void onUpdateWorkspace: (workspace: Workspace) => void onCheckChange: (checkedWorkspaces: Workspace[]) => void @@ -64,7 +63,6 @@ export const WorkspacesPageView: FC< onUpdateWorkspace, page, checkedWorkspaces, - isWorkspaceBatchActionsEnabled, onCheckChange, onDeleteAll, }) => { @@ -151,7 +149,6 @@ export const WorkspacesPageView: FC< onUpdateWorkspace={onUpdateWorkspace} checkedWorkspaces={checkedWorkspaces} onCheckChange={onCheckChange} - isWorkspaceBatchActionsEnabled={isWorkspaceBatchActionsEnabled} /> {count !== undefined && ( void onCheckChange: (checkedWorkspaces: Workspace[]) => void } @@ -47,7 +51,6 @@ export const WorkspacesTable: FC = ({ workspaces, checkedWorkspaces, isUsingFilter, - isWorkspaceBatchActionsEnabled, onUpdateWorkspace, onCheckChange, }) => { @@ -59,37 +62,32 @@ export const WorkspacesTable: FC = ({ - {isWorkspaceBatchActionsEnabled ? ( - `${theme.spacing(1.5)} !important`, - }} - > - - { - if (!workspaces) { - return - } - - if (!checked) { - onCheckChange([]) - } else { - onCheckChange(workspaces) - } - }} - /> - Name - - - ) : ( - Name - )} + `${theme.spacing(1.5)} !important`, + }} + > + + { + if (!workspaces) { + return + } + if (!checked) { + onCheckChange([]) + } else { + onCheckChange(workspaces) + } + }} + /> + Name + + Template Last used Status @@ -97,7 +95,7 @@ export const WorkspacesTable: FC = ({ - {!workspaces && } + {!workspaces && } {workspaces && workspaces.length === 0 && ( @@ -142,34 +140,30 @@ export const WorkspacesTable: FC = ({ - isWorkspaceBatchActionsEnabled - ? `${theme.spacing(1.5)} !important` - : undefined, + `${theme.spacing(1.5)} !important`, }} > - {isWorkspaceBatchActionsEnabled && ( - { - e.stopPropagation() - }} - onChange={(e) => { - if (e.currentTarget.checked) { - onCheckChange([...checkedWorkspaces, workspace]) - } else { - onCheckChange( - checkedWorkspaces.filter( - (w) => w.id !== workspace.id, - ), - ) - } - }} - /> - )} + { + e.stopPropagation() + }} + onChange={(e) => { + if (e.currentTarget.checked) { + onCheckChange([...checkedWorkspaces, workspace]) + } else { + onCheckChange( + checkedWorkspaces.filter( + (w) => w.id !== workspace.id, + ), + ) + } + }} + /> { ) } +const TableLoader = () => { + return ( + + + `${theme.spacing(1.5)} !important`, + }} + > + + + + + + + + + + + + + + + + + + + + ) +} + const cantBeChecked = (workspace: Workspace) => { return ["deleting", "pending"].includes(workspace.latest_build.status) } diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index 2a77a174e8831..e4e7f2f96f8b0 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -1511,7 +1511,6 @@ export const MockEntitlementsWithScheduling: TypesGen.Entitlements = { export const MockExperiments: TypesGen.Experiment[] = [ "workspace_actions", "moons", - "workspaces_batch_actions", ] export const MockAuditLog: TypesGen.AuditLog = { From c8f436917256d0f11bf91854559dd287487cf03d Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Thu, 24 Aug 2023 17:53:27 +0000 Subject: [PATCH 3/8] Improve verbiage --- site/src/pages/WorkspacesPage/WorkspacesPageView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/pages/WorkspacesPage/WorkspacesPageView.tsx b/site/src/pages/WorkspacesPage/WorkspacesPageView.tsx index f382c17ae15b8..3909ccdb98dd8 100644 --- a/site/src/pages/WorkspacesPage/WorkspacesPageView.tsx +++ b/site/src/pages/WorkspacesPage/WorkspacesPageView.tsx @@ -129,7 +129,7 @@ export const WorkspacesPageView: FC< startIcon={} onClick={onDeleteAll} > - Delete all + Delete selected From 614bc144fb78972ee9aa546e09a65f3ae4b11c85 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Thu, 24 Aug 2023 17:54:57 +0000 Subject: [PATCH 4/8] Make comparison upper case --- site/src/pages/WorkspacesPage/WorkspacesPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/pages/WorkspacesPage/WorkspacesPage.tsx b/site/src/pages/WorkspacesPage/WorkspacesPage.tsx index e7e85e7fd1fed..ef8354932ab0a 100644 --- a/site/src/pages/WorkspacesPage/WorkspacesPage.tsx +++ b/site/src/pages/WorkspacesPage/WorkspacesPage.tsx @@ -190,7 +190,7 @@ const BatchDeleteConfirmation = ({ const confirmDeletion = async () => { setConfirmError(false) - if (confirmValue.toLowerCase() !== "delete") { + if (confirmValue !== "DELETE") { setConfirmError(true) return } From c36d363d30d0458b790779874644ed9202ab239a Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Tue, 29 Aug 2023 13:53:56 +0000 Subject: [PATCH 5/8] Add feature to enterprise --- codersdk/deployment.go | 2 ++ site/src/api/typesGenerated.ts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/codersdk/deployment.go b/codersdk/deployment.go index ef0f34711c3ce..9071fad1584a8 100644 --- a/codersdk/deployment.go +++ b/codersdk/deployment.go @@ -48,6 +48,7 @@ const ( FeatureAdvancedTemplateScheduling FeatureName = "advanced_template_scheduling" FeatureTemplateRestartRequirement FeatureName = "template_restart_requirement" FeatureWorkspaceProxy FeatureName = "workspace_proxy" + FeatureWorkspaceBatchActions FeatureName = "workspace_batch_actions" ) // FeatureNames must be kept in-sync with the Feature enum above. @@ -64,6 +65,7 @@ var FeatureNames = []FeatureName{ FeatureAdvancedTemplateScheduling, FeatureWorkspaceProxy, FeatureUserRoleManagement, + FeatureWorkspaceBatchActions, } // Humanize returns the feature name in a human-readable format. diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 2b5f8633a9a93..fe271ba3fc33e 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -1628,6 +1628,7 @@ export type FeatureName = | "template_restart_requirement" | "user_limit" | "user_role_management" + | "workspace_batch_actions" | "workspace_proxy" export const FeatureNames: FeatureName[] = [ "advanced_template_scheduling", @@ -1642,6 +1643,7 @@ export const FeatureNames: FeatureName[] = [ "template_restart_requirement", "user_limit", "user_role_management", + "workspace_batch_actions", "workspace_proxy", ] From e653b8cf927ab9ab6257114b8f53bec6e070fe5a Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Tue, 29 Aug 2023 14:12:52 +0000 Subject: [PATCH 6/8] Put feature behind enterprise --- .../pages/WorkspacesPage/WorkspacesPage.tsx | 9 +- .../WorkspacesPageView.stories.tsx | 1 + .../WorkspacesPage/WorkspacesPageView.tsx | 3 + .../pages/WorkspacesPage/WorkspacesTable.tsx | 96 ++++++++++--------- 4 files changed, 61 insertions(+), 48 deletions(-) diff --git a/site/src/pages/WorkspacesPage/WorkspacesPage.tsx b/site/src/pages/WorkspacesPage/WorkspacesPage.tsx index 7c95efff1cfc3..ad3bf1d00aa6b 100644 --- a/site/src/pages/WorkspacesPage/WorkspacesPage.tsx +++ b/site/src/pages/WorkspacesPage/WorkspacesPage.tsx @@ -1,6 +1,9 @@ import { usePagination } from "hooks/usePagination" import { Workspace } from "api/typesGenerated" -import { useIsWorkspaceActionsEnabled } from "components/Dashboard/DashboardProvider" +import { + useDashboard, + useIsWorkspaceActionsEnabled, +} from "components/Dashboard/DashboardProvider" import { FC, useEffect, useState } from "react" import { Helmet } from "react-helmet-async" import { pageTitle } from "utils/page" @@ -65,6 +68,9 @@ const WorkspacesPage: FC = () => { const [checkedWorkspaces, setCheckedWorkspaces] = useState([]) const [isDeletingAll, setIsDeletingAll] = useState(false) const [urlSearchParams] = searchParamsResult + const { entitlements } = useDashboard() + const canCheckWorkspaces = + entitlements.features["workspace_batch_actions"].enabled // We want to uncheck the selected workspaces always when the url changes // because of filtering or pagination @@ -81,6 +87,7 @@ const WorkspacesPage: FC = () => { = { limit: DEFAULT_RECORDS_PER_PAGE, filterProps: defaultFilterProps, checkedWorkspaces: [], + canCheckWorkspaces: true, }, decorators: [ (Story) => ( diff --git a/site/src/pages/WorkspacesPage/WorkspacesPageView.tsx b/site/src/pages/WorkspacesPage/WorkspacesPageView.tsx index ce0fd14ba8756..16563d1a0235c 100644 --- a/site/src/pages/WorkspacesPage/WorkspacesPageView.tsx +++ b/site/src/pages/WorkspacesPage/WorkspacesPageView.tsx @@ -48,6 +48,7 @@ export interface WorkspacesPageViewProps { onUpdateWorkspace: (workspace: Workspace) => void onCheckChange: (checkedWorkspaces: Workspace[]) => void onDeleteAll: () => void + canCheckWorkspaces: boolean } export const WorkspacesPageView: FC< @@ -65,6 +66,7 @@ export const WorkspacesPageView: FC< checkedWorkspaces, onCheckChange, onDeleteAll, + canCheckWorkspaces, }) => { const { saveLocal } = useLocalStorage() @@ -149,6 +151,7 @@ export const WorkspacesPageView: FC< onUpdateWorkspace={onUpdateWorkspace} checkedWorkspaces={checkedWorkspaces} onCheckChange={onCheckChange} + canCheckWorkspaces={canCheckWorkspaces} /> {count !== undefined && ( void onCheckChange: (checkedWorkspaces: Workspace[]) => void + canCheckWorkspaces: boolean } export const WorkspacesTable: FC = ({ @@ -53,6 +54,7 @@ export const WorkspacesTable: FC = ({ isUsingFilter, onUpdateWorkspace, onCheckChange, + canCheckWorkspaces, }) => { const { t } = useTranslation("workspacesPage") const styles = useStyles() @@ -62,29 +64,29 @@ export const WorkspacesTable: FC = ({
- `${theme.spacing(1.5)} !important`, - }} - > + - { - if (!workspaces) { - return - } + {canCheckWorkspaces && ( + { + if (!workspaces) { + return + } - if (!checked) { - onCheckChange([]) - } else { - onCheckChange(workspaces) - } - }} - /> + if (!checked) { + onCheckChange([]) + } else { + onCheckChange(workspaces) + } + }} + /> + )} Name @@ -137,33 +139,33 @@ export const WorkspacesTable: FC = ({ key={workspace.id} checked={checked} > - - `${theme.spacing(1.5)} !important`, - }} - > + - { - e.stopPropagation() - }} - onChange={(e) => { - if (e.currentTarget.checked) { - onCheckChange([...checkedWorkspaces, workspace]) - } else { - onCheckChange( - checkedWorkspaces.filter( - (w) => w.id !== workspace.id, - ), - ) - } - }} - /> + {canCheckWorkspaces && ( + { + e.stopPropagation() + }} + onChange={(e) => { + if (e.currentTarget.checked) { + onCheckChange([...checkedWorkspaces, workspace]) + } else { + onCheckChange( + checkedWorkspaces.filter( + (w) => w.id !== workspace.id, + ), + ) + } + }} + /> + )} Date: Tue, 29 Aug 2023 14:22:51 +0000 Subject: [PATCH 7/8] fix js test --- site/src/pages/WorkspacesPage/WorkspacesPage.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/pages/WorkspacesPage/WorkspacesPage.test.tsx b/site/src/pages/WorkspacesPage/WorkspacesPage.test.tsx index 6abb3d06e2310..9b03d98d80d0f 100644 --- a/site/src/pages/WorkspacesPage/WorkspacesPage.test.tsx +++ b/site/src/pages/WorkspacesPage/WorkspacesPage.test.tsx @@ -63,7 +63,7 @@ describe("WorkspacesPage", () => { await user.click(getWorkspaceCheckbox(workspaces[0])) await user.click(getWorkspaceCheckbox(workspaces[1])) - await user.click(screen.getByRole("button", { name: /delete all/i })) + await user.click(screen.getByRole("button", { name: /delete selected/i })) await user.type(screen.getByLabelText(/type delete to confirm/i), "DELETE") await user.click(screen.getByTestId("confirm-button")) From 90de8dd5aa089819cab22e19ae5de07665e9f5d3 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Tue, 29 Aug 2023 14:37:45 +0000 Subject: [PATCH 8/8] Fix tests --- site/src/testHelpers/entities.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index 4346901bd7445..caa71f57e6a1f 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -1757,7 +1757,12 @@ export const MockEntitlements: TypesGen.Entitlements = { errors: [], warnings: [], has_license: false, - features: withDefaultFeatures({}), + features: withDefaultFeatures({ + workspace_batch_actions: { + enabled: true, + entitlement: "entitled", + }, + }), require_telemetry: false, trial: false, refreshed_at: "2022-05-20T16:45:57.122Z",