From aad7a9dc4f8459895b864b96fc3222a5e319be22 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Tue, 26 Sep 2023 21:09:01 +0000 Subject: [PATCH 1/4] chore: remove `Maybe` --- .../components/Conditionals/Maybe.stories.tsx | 25 ----- site/src/components/Conditionals/Maybe.tsx | 17 --- .../Dialogs/DeleteDialog/DeleteDialog.tsx | 5 +- site/src/components/PageHeader/PageHeader.tsx | 4 +- .../PaginationWidget/PaginationWidget.tsx | 103 +++++++++--------- .../components/Resources/AgentRowPreview.tsx | 7 +- .../TemplateVersionWarnings.tsx | 19 ++-- .../ImpendingDeletionStat.tsx | 58 +++++----- .../CreateTemplatePage/CreateTemplatePage.tsx | 9 +- site/src/pages/GroupsPage/GroupPage.tsx | 89 ++++++++------- site/src/pages/LoginPage/SignInForm.tsx | 62 ++++++----- .../StarterTemplatesPageView.tsx | 9 +- .../pages/TemplatePage/TemplatePageHeader.tsx | 5 +- .../TemplatePermissionsPageView.tsx | 13 +-- .../pages/TemplatesPage/TemplatesPageView.tsx | 37 +++---- .../WorkspaceProxyPage/WorkspaceProxyRow.tsx | 5 +- .../UsersPage/UsersTable/EditRolesButton.tsx | 8 +- site/src/pages/WorkspacePage/Workspace.tsx | 5 +- .../WorkspacesPage/WorkspacesPageView.tsx | 5 +- 19 files changed, 216 insertions(+), 269 deletions(-) delete mode 100644 site/src/components/Conditionals/Maybe.stories.tsx delete mode 100644 site/src/components/Conditionals/Maybe.tsx diff --git a/site/src/components/Conditionals/Maybe.stories.tsx b/site/src/components/Conditionals/Maybe.stories.tsx deleted file mode 100644 index cfe14ede5acbb..0000000000000 --- a/site/src/components/Conditionals/Maybe.stories.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { StoryObj, Meta } from "@storybook/react"; -import { Maybe } from "./Maybe"; - -const meta: Meta = { - title: "components/Conditionals/Maybe", - component: Maybe, - args: { - children: "Now you see me", - }, -}; - -export default meta; -type Story = StoryObj; - -export const ConditionIsTrue: Story = { - args: { - condition: true, - }, -}; - -export const ConditionIsFalse: Story = { - args: { - condition: false, - }, -}; diff --git a/site/src/components/Conditionals/Maybe.tsx b/site/src/components/Conditionals/Maybe.tsx deleted file mode 100644 index 7975101c17cab..0000000000000 --- a/site/src/components/Conditionals/Maybe.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { PropsWithChildren } from "react"; - -export interface MaybeProps { - condition: boolean; -} - -/** - * Wrapper component for conditionally rendering a child component without using "curly brace mode." - * @param condition boolean expression that determines whether the child will be rendered - * @returns the child or null - */ -export const Maybe = ({ - children, - condition, -}: PropsWithChildren): JSX.Element | null => { - return condition ? <>{children} : null; -}; diff --git a/site/src/components/Dialogs/DeleteDialog/DeleteDialog.tsx b/site/src/components/Dialogs/DeleteDialog/DeleteDialog.tsx index 0ac7938f5c4c3..9ae03c4d481da 100644 --- a/site/src/components/Dialogs/DeleteDialog/DeleteDialog.tsx +++ b/site/src/components/Dialogs/DeleteDialog/DeleteDialog.tsx @@ -1,6 +1,5 @@ import makeStyles from "@mui/styles/makeStyles"; import TextField from "@mui/material/TextField"; -import { Maybe } from "components/Conditionals/Maybe"; import { ChangeEvent, useState, PropsWithChildren, FC } from "react"; import { ConfirmDialog } from "../ConfirmDialog/ConfirmDialog"; @@ -34,9 +33,7 @@ export const DeleteDialog: FC> = ({ const content = ( <>

Deleting this {entity} is irreversible!

- -

{info}

-
+ {info !== undefined &&

{info}

}

Are you sure you want to proceed?

Type {name} below to confirm.

diff --git a/site/src/components/PageHeader/PageHeader.tsx b/site/src/components/PageHeader/PageHeader.tsx index b24ccb7b05619..f34e57fec6254 100644 --- a/site/src/components/PageHeader/PageHeader.tsx +++ b/site/src/components/PageHeader/PageHeader.tsx @@ -1,10 +1,10 @@ import { makeStyles } from "@mui/styles"; -import { PropsWithChildren, FC } from "react"; +import { type FC, type PropsWithChildren, type ReactNode } from "react"; import { combineClasses } from "../../utils/combineClasses"; import { Stack } from "../Stack/Stack"; export interface PageHeaderProps { - actions?: JSX.Element; + actions?: ReactNode; className?: string; } diff --git a/site/src/components/PaginationWidget/PaginationWidget.tsx b/site/src/components/PaginationWidget/PaginationWidget.tsx index 08a40412a2abe..fff86071a2617 100644 --- a/site/src/components/PaginationWidget/PaginationWidget.tsx +++ b/site/src/components/PaginationWidget/PaginationWidget.tsx @@ -5,7 +5,6 @@ import KeyboardArrowLeft from "@mui/icons-material/KeyboardArrowLeft"; import KeyboardArrowRight from "@mui/icons-material/KeyboardArrowRight"; import { useActor } from "@xstate/react"; import { ChooseOne, Cond } from "components/Conditionals/ChooseOne"; -import { Maybe } from "components/Conditionals/Maybe"; import { CSSProperties } from "react"; import { PaginationMachineRef } from "xServices/pagination/paginationXService"; import { PageButton } from "./PageButton"; @@ -40,57 +39,59 @@ export const PaginationWidget = ({ // if beyond page 1, show pagination widget even if there's only one true page, so user can navigate back const showWidget = numPages > 1 || currentPage > 1; + if (!showWidget) { + return null; + } + return ( - -
- - - - - - - {buildPagedList(numPages, currentPage).map((page) => - typeof page !== "number" ? ( - - ) : ( - send({ type: "GO_TO_PAGE", page })} - /> - ), - )} - - - -
-
+
+ + + + + + + {buildPagedList(numPages, currentPage).map((page) => + typeof page !== "number" ? ( + + ) : ( + send({ type: "GO_TO_PAGE", page })} + /> + ), + )} + + + +
); }; diff --git a/site/src/components/Resources/AgentRowPreview.tsx b/site/src/components/Resources/AgentRowPreview.tsx index 24246f149b7cf..755eebe73324c 100644 --- a/site/src/components/Resources/AgentRowPreview.tsx +++ b/site/src/components/Resources/AgentRowPreview.tsx @@ -1,9 +1,8 @@ import { makeStyles } from "@mui/styles"; import { AppPreviewLink } from "components/Resources/AppLink/AppPreviewLink"; -import { Maybe } from "components/Conditionals/Maybe"; import { FC } from "react"; import { combineClasses } from "utils/combineClasses"; -import { WorkspaceAgent } from "../../api/typesGenerated"; +import { WorkspaceAgent } from "api/typesGenerated"; import { Stack } from "../Stack/Stack"; interface AgentRowPreviewStyles { @@ -90,9 +89,9 @@ export const AgentRowPreview: FC = ({ {agent.apps.map((app) => ( ))} - + {agent.apps.length === 0 && ( None - + )} diff --git a/site/src/components/TemplateVersionWarnings/TemplateVersionWarnings.tsx b/site/src/components/TemplateVersionWarnings/TemplateVersionWarnings.tsx index dd7513e3a3d8f..9aedf14bb60ed 100644 --- a/site/src/components/TemplateVersionWarnings/TemplateVersionWarnings.tsx +++ b/site/src/components/TemplateVersionWarnings/TemplateVersionWarnings.tsx @@ -1,7 +1,6 @@ import { FC } from "react"; import * as TypesGen from "api/typesGenerated"; import { Alert } from "components/Alert/Alert"; -import { Maybe } from "components/Conditionals/Maybe"; export interface TemplateVersionWarningsProps { warnings?: TypesGen.TemplateVersionWarning[]; @@ -14,14 +13,16 @@ export const TemplateVersionWarnings: FC< return <>; } + if (!warnings.includes("UNSUPPORTED_WORKSPACES")) { + return null; + } + return ( - -
- - This template uses legacy parameters which are not supported anymore. - Contact your administrator for assistance. - -
-
+
+ + This template uses legacy parameters which are not supported anymore. + Contact your administrator for assistance. + +
); }; diff --git a/site/src/components/WorkspaceDeletion/ImpendingDeletionStat.tsx b/site/src/components/WorkspaceDeletion/ImpendingDeletionStat.tsx index 91db5dc680c8b..e36b19625a387 100644 --- a/site/src/components/WorkspaceDeletion/ImpendingDeletionStat.tsx +++ b/site/src/components/WorkspaceDeletion/ImpendingDeletionStat.tsx @@ -1,4 +1,3 @@ -import { Maybe } from "components/Conditionals/Maybe"; import { StatsItem } from "components/Stats/Stats"; import Link from "@mui/material/Link"; import { Link as RouterLink } from "react-router-dom"; @@ -6,12 +5,15 @@ import styled from "@emotion/styled"; import { Workspace } from "api/typesGenerated"; import { displayImpendingDeletion } from "./utils"; import { useDashboard } from "components/Dashboard/DashboardProvider"; +import { type FC } from "react"; -export const ImpendingDeletionStat = ({ - workspace, -}: { +interface ImpendingDeletionStatProps { workspace: Workspace; -}): JSX.Element => { +} + +export const ImpendingDeletionStat: FC = ({ + workspace, +}) => { const { entitlements, experiments } = useDashboard(); const allowAdvancedScheduling = entitlements.features["advanced_template_scheduling"].enabled; @@ -19,29 +21,31 @@ export const ImpendingDeletionStat = ({ // is merged up const allowWorkspaceActions = experiments.includes("workspace_actions"); + if ( + !displayImpendingDeletion( + workspace, + allowAdvancedScheduling, + allowWorkspaceActions, + ) + ) { + return null; + } + return ( - - - {/* We check for string existence in the conditional */} - {new Date(workspace.deleting_at as string).toLocaleString()} - - } - /> - + + {/* We check for string existence in the conditional */} + {new Date(workspace.deleting_at as string).toLocaleString()} + + } + /> ); }; diff --git a/site/src/pages/CreateTemplatePage/CreateTemplatePage.tsx b/site/src/pages/CreateTemplatePage/CreateTemplatePage.tsx index eb78bd2c94ea8..b0b9f056daded 100644 --- a/site/src/pages/CreateTemplatePage/CreateTemplatePage.tsx +++ b/site/src/pages/CreateTemplatePage/CreateTemplatePage.tsx @@ -1,6 +1,5 @@ import { useMachine } from "@xstate/react"; import { isApiValidationError } from "api/errors"; -import { Maybe } from "components/Conditionals/Maybe"; import { useDashboard } from "components/Dashboard/DashboardProvider"; import { FullPageHorizontalForm } from "components/FullPageForm/FullPageHorizontalForm"; import { Loader } from "components/Loader/Loader"; @@ -55,14 +54,12 @@ const CreateTemplatePage: FC = () => { - - - + {state.hasTag("loading") && } - + {Boolean(error) && !isApiValidationError(error) && ( - + )} {shouldDisplayForm && ( { +export const GroupPage: FC = () => { const { groupId } = useParams() as { groupId: string }; const queryClient = useQueryClient(); const navigate = useNavigate(); @@ -79,25 +78,27 @@ export const GroupPage: React.FC = () => { - - - + canUpdateGroup && ( + <> + + + + ) } > @@ -113,30 +114,26 @@ export const GroupPage: React.FC = () => { - - { - try { - await addMemberMutation.mutateAsync({ - groupId, - userId: user.id, - }); - reset(); - } catch (error) { - displayError( - getErrorMessage(error, "Failed to add member."), - ); - } - }} - /> - + {canUpdateGroup && + groupData !== undefined && + !isEveryoneGroup(groupData) && ( + { + try { + await addMemberMutation.mutateAsync({ + groupId, + userId: user.id, + }); + reset(); + } catch (error) { + displayError( + getErrorMessage(error, "Failed to add member."), + ); + } + }} + /> + )} > = ({

Sign in to Coder

- + + {Boolean(error) && (
-
- + )} + + {Boolean(info) && Boolean(error) && (
{info}
-
- + )} + + {passwordEnabled && showPasswordAuth && ( - - + )} + + {passwordEnabled && showPasswordAuth && oAuthEnabled && (
Or
- - + )} + + {oAuthEnabled && ( - + )} - + {!passwordEnabled && !oAuthEnabled && ( No authentication methods configured! - + )} - -
-
-
Or
-
-
+ {passwordEnabled && !showPasswordAuth && ( + <> +
+
+
Or
+
+
- - + + + )}
); }; diff --git a/site/src/pages/StarterTemplatesPage/StarterTemplatesPageView.tsx b/site/src/pages/StarterTemplatesPage/StarterTemplatesPageView.tsx index 0fd768acaa60e..5a7e5e1b830b3 100644 --- a/site/src/pages/StarterTemplatesPage/StarterTemplatesPageView.tsx +++ b/site/src/pages/StarterTemplatesPage/StarterTemplatesPageView.tsx @@ -1,6 +1,5 @@ import { makeStyles } from "@mui/styles"; import { ErrorAlert } from "components/Alert/ErrorAlert"; -import { Maybe } from "components/Conditionals/Maybe"; import { Loader } from "components/Loader/Loader"; import { Margins } from "components/Margins/Margins"; import { @@ -59,13 +58,9 @@ export const StarterTemplatesPageView: FC = ({ - - - + {Boolean(error) && } - - - + {Boolean(!starterTemplatesByTag) && } {starterTemplatesByTag && tags && ( diff --git a/site/src/pages/TemplatePage/TemplatePageHeader.tsx b/site/src/pages/TemplatePage/TemplatePageHeader.tsx index ace6fb9764df6..3985306a97548 100644 --- a/site/src/pages/TemplatePage/TemplatePageHeader.tsx +++ b/site/src/pages/TemplatePage/TemplatePageHeader.tsx @@ -6,7 +6,6 @@ import { TemplateVersion, } from "api/typesGenerated"; import { Avatar } from "components/Avatar/Avatar"; -import { Maybe } from "components/Conditionals/Maybe"; import { DeleteDialog } from "components/Dialogs/DeleteDialog/DeleteDialog"; import { PageHeader, @@ -132,13 +131,13 @@ export const TemplatePageHeader: FC = ({ actions={ <> - + {permissions.canUpdateTemplate && ( - + )} } > diff --git a/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPageView.tsx b/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPageView.tsx index 27216eec7fa43..192a4eea8aa33 100644 --- a/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPageView.tsx +++ b/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPageView.tsx @@ -27,7 +27,6 @@ import { UserOrGroupAutocompleteValue, } from "components/UserOrGroupAutocomplete/UserOrGroupAutocomplete"; import { FC, useState } from "react"; -import { Maybe } from "components/Conditionals/Maybe"; import { GroupAvatar } from "components/GroupAvatar/GroupAvatar"; import { getGroupSubtitle } from "utils/groups"; import { PageHeader, PageHeaderTitle } from "components/PageHeader/PageHeader"; @@ -213,7 +212,7 @@ export const TemplatePermissionsPageView: FC< - + {canUpdatePermissions && ( - + )} @@ -288,7 +287,7 @@ export const TemplatePermissionsPageView: FC< - + {canUpdatePermissions && ( - + )} ))} @@ -336,7 +335,7 @@ export const TemplatePermissionsPageView: FC< - + {canUpdatePermissions && ( - + )} ))} diff --git a/site/src/pages/TemplatesPage/TemplatesPageView.tsx b/site/src/pages/TemplatesPage/TemplatesPageView.tsx index 426d46902bdd0..88ce3540c304b 100644 --- a/site/src/pages/TemplatesPage/TemplatesPageView.tsx +++ b/site/src/pages/TemplatesPage/TemplatesPageView.tsx @@ -8,7 +8,6 @@ import TableHead from "@mui/material/TableHead"; import TableRow from "@mui/material/TableRow"; import AddIcon from "@mui/icons-material/AddOutlined"; import { ChooseOne, Cond } from "components/Conditionals/ChooseOne"; -import { Maybe } from "components/Conditionals/Maybe"; import { FC } from "react"; import { useNavigate, Link as RouterLink } from "react-router-dom"; import { createDayString } from "utils/createDayString"; @@ -158,19 +157,21 @@ export const TemplatesPageView: FC = ({ - - - + canCreateTemplates && ( + <> + + + + ) } > @@ -179,11 +180,11 @@ export const TemplatesPageView: FC = ({ - 0)}> + {templates && templates.length > 0 && ( Select a template to create a workspace. - + )} @@ -204,9 +205,7 @@ export const TemplatesPageView: FC = ({ - - - + {isLoading && } diff --git a/site/src/pages/UserSettingsPage/WorkspaceProxyPage/WorkspaceProxyRow.tsx b/site/src/pages/UserSettingsPage/WorkspaceProxyPage/WorkspaceProxyRow.tsx index 5747398cb12e4..16f37eeec1a3d 100644 --- a/site/src/pages/UserSettingsPage/WorkspaceProxyPage/WorkspaceProxyRow.tsx +++ b/site/src/pages/UserSettingsPage/WorkspaceProxyPage/WorkspaceProxyRow.tsx @@ -12,7 +12,6 @@ import { } from "components/DeploySettingsLayout/Badges"; import { ProxyLatencyReport } from "contexts/useProxyLatency"; import { getLatencyColor } from "utils/latency"; -import { Maybe } from "components/Conditionals/Maybe"; import Box from "@mui/material/Box"; export const ProxyRow: FC<{ @@ -72,7 +71,7 @@ export const ProxyRow: FC<{ {latency ? `${latency.latencyMS.toFixed(0)} ms` : "Not available"} - + {shouldShowMessages && ( - + )} ); }; diff --git a/site/src/pages/UsersPage/UsersTable/EditRolesButton.tsx b/site/src/pages/UsersPage/UsersTable/EditRolesButton.tsx index 3eb61f169f925..739f42eb6948a 100644 --- a/site/src/pages/UsersPage/UsersTable/EditRolesButton.tsx +++ b/site/src/pages/UsersPage/UsersTable/EditRolesButton.tsx @@ -12,7 +12,6 @@ import { HelpTooltipText, HelpTooltipTitle, } from "components/HelpTooltip/HelpTooltip"; -import { Maybe } from "components/Conditionals/Maybe"; const roleDescriptions: Record = { owner: @@ -94,7 +93,7 @@ export const EditRolesButton: FC = ({ return ( <> - + {canSetRoles ? ( = ({ > - - + ) : ( Externally controlled Roles for this user are controlled by the OIDC identity provider. - + )} > = ({ - + {showAlertPendingInQueue && ( Workspace build is pending @@ -294,7 +293,7 @@ export const Workspace: FC> = ({ - + )} {workspace.latest_build.job.error && ( - + {hasError(error) && !isApiValidationError(error) && ( - + )} {/* determines its own visibility */} Date: Tue, 26 Sep 2023 21:18:37 +0000 Subject: [PATCH 2/4] missed one --- site/src/pages/GroupsPage/GroupPage.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/src/pages/GroupsPage/GroupPage.tsx b/site/src/pages/GroupsPage/GroupPage.tsx index e579d908fc424..9f40529c60639 100644 --- a/site/src/pages/GroupsPage/GroupPage.tsx +++ b/site/src/pages/GroupsPage/GroupPage.tsx @@ -276,7 +276,7 @@ const GroupMemberRow = (props: { /> - + {canUpdate && ( - + )} ); From 28fc626bbef993c23bec7095bee94122f380a55f Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Wed, 27 Sep 2023 16:24:23 +0000 Subject: [PATCH 3/4] make this a bit nicer --- .../TemplateVersionWarnings/TemplateVersionWarnings.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/site/src/components/TemplateVersionWarnings/TemplateVersionWarnings.tsx b/site/src/components/TemplateVersionWarnings/TemplateVersionWarnings.tsx index 9aedf14bb60ed..473488bda92bb 100644 --- a/site/src/components/TemplateVersionWarnings/TemplateVersionWarnings.tsx +++ b/site/src/components/TemplateVersionWarnings/TemplateVersionWarnings.tsx @@ -8,10 +8,8 @@ export interface TemplateVersionWarningsProps { export const TemplateVersionWarnings: FC< React.PropsWithChildren -> = ({ warnings }) => { - if (!warnings) { - return <>; - } +> = (props) => { + const { warnings = [] } = props; if (!warnings.includes("UNSUPPORTED_WORKSPACES")) { return null; From 0de3cee490b77df706eec7f1c99acc5c51c69237 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Wed, 27 Sep 2023 16:29:02 +0000 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=A7=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Dialogs/DeleteDialog/DeleteDialog.tsx | 2 +- site/src/components/PageHeader/PageHeader.tsx | 2 +- site/src/pages/GroupsPage/GroupPage.tsx | 38 +++++++++---------- 3 files changed, 20 insertions(+), 22 deletions(-) diff --git a/site/src/components/Dialogs/DeleteDialog/DeleteDialog.tsx b/site/src/components/Dialogs/DeleteDialog/DeleteDialog.tsx index 9ae03c4d481da..e4246d689d7ee 100644 --- a/site/src/components/Dialogs/DeleteDialog/DeleteDialog.tsx +++ b/site/src/components/Dialogs/DeleteDialog/DeleteDialog.tsx @@ -33,7 +33,7 @@ export const DeleteDialog: FC> = ({ const content = ( <>

Deleting this {entity} is irreversible!

- {info !== undefined &&

{info}

} + {Boolean(info) &&

{info}

}

Are you sure you want to proceed?

Type {name} below to confirm.

diff --git a/site/src/components/PageHeader/PageHeader.tsx b/site/src/components/PageHeader/PageHeader.tsx index f34e57fec6254..3678e9b6fe89a 100644 --- a/site/src/components/PageHeader/PageHeader.tsx +++ b/site/src/components/PageHeader/PageHeader.tsx @@ -1,6 +1,6 @@ import { makeStyles } from "@mui/styles"; import { type FC, type PropsWithChildren, type ReactNode } from "react"; -import { combineClasses } from "../../utils/combineClasses"; +import { combineClasses } from "utils/combineClasses"; import { Stack } from "../Stack/Stack"; export interface PageHeaderProps { diff --git a/site/src/pages/GroupsPage/GroupPage.tsx b/site/src/pages/GroupsPage/GroupPage.tsx index 9f40529c60639..de46b19a831a0 100644 --- a/site/src/pages/GroupsPage/GroupPage.tsx +++ b/site/src/pages/GroupsPage/GroupPage.tsx @@ -114,26 +114,24 @@ export const GroupPage: FC = () => { - {canUpdateGroup && - groupData !== undefined && - !isEveryoneGroup(groupData) && ( - { - try { - await addMemberMutation.mutateAsync({ - groupId, - userId: user.id, - }); - reset(); - } catch (error) { - displayError( - getErrorMessage(error, "Failed to add member."), - ); - } - }} - /> - )} + {canUpdateGroup && groupData && !isEveryoneGroup(groupData) && ( + { + try { + await addMemberMutation.mutateAsync({ + groupId, + userId: user.id, + }); + reset(); + } catch (error) { + displayError( + getErrorMessage(error, "Failed to add member."), + ); + } + }} + /> + )}