From ca353cb81cbb681ce99818812c24c23ca4950db8 Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Fri, 3 Nov 2023 11:03:21 -0300 Subject: [PATCH] refactor(site): improve first workspace creation time (#10510) One tiny improvement to make the onboarding faster. When a user has no workspace, show the existent templates with direct links to the workspace creation instead of asking them to see all templates, select one, and after, click on "Create workspace". Before: Screenshot 2023-11-03 at 10 11 32 After: Screenshot 2023-11-03 at 10 11 43 --- .../pages/WorkspacesPage/WorkspacesEmpty.tsx | 97 +++++++++++++++++++ .../WorkspacesPage/WorkspacesPageView.tsx | 2 +- .../pages/WorkspacesPage/WorkspacesTable.tsx | 59 ++--------- 3 files changed, 107 insertions(+), 51 deletions(-) create mode 100644 site/src/pages/WorkspacesPage/WorkspacesEmpty.tsx diff --git a/site/src/pages/WorkspacesPage/WorkspacesEmpty.tsx b/site/src/pages/WorkspacesPage/WorkspacesEmpty.tsx new file mode 100644 index 0000000000..9c1603d1c6 --- /dev/null +++ b/site/src/pages/WorkspacesPage/WorkspacesEmpty.tsx @@ -0,0 +1,97 @@ +import ArrowForwardOutlined from "@mui/icons-material/ArrowForwardOutlined"; +import Button from "@mui/material/Button"; +import { Template } from "api/typesGenerated"; +import { Avatar } from "components/Avatar/Avatar"; +import { TableEmpty } from "components/TableEmpty/TableEmpty"; +import { Link } from "react-router-dom"; + +export const WorkspacesEmpty = (props: { + isUsingFilter: boolean; + templates?: Template[]; +}) => { + const { isUsingFilter, templates } = props; + const totalFeaturedTemplates = 6; + const featuredTemplates = templates?.slice(0, totalFeaturedTemplates); + + if (isUsingFilter) { + return ; + } + + return ( + +
({ + display: "flex", + flexWrap: "wrap", + gap: theme.spacing(2), + marginBottom: theme.spacing(3), + justifyContent: "center", + maxWidth: "800px", + })} + > + {featuredTemplates?.map((t) => ( + ({ + width: "320px", + padding: theme.spacing(2), + borderRadius: 6, + border: `1px solid ${theme.palette.divider}`, + textAlign: "left", + display: "flex", + gap: theme.spacing(2), + textDecoration: "none", + color: "inherit", + + "&:hover": { + backgroundColor: theme.palette.background.paperLight, + }, + })} + > +
+ + {t.name} + +
+
+

+ {t.display_name} +

+ ({ + fontSize: 13, + color: theme.palette.text.secondary, + lineHeight: "0.5", + })} + > + {t.description} + +
+ + ))} +
+ {templates && templates.length > totalFeaturedTemplates && ( + + )} + + } + /> + ); +}; diff --git a/site/src/pages/WorkspacesPage/WorkspacesPageView.tsx b/site/src/pages/WorkspacesPage/WorkspacesPageView.tsx index 44d16701d5..45f90bf0e1 100644 --- a/site/src/pages/WorkspacesPage/WorkspacesPageView.tsx +++ b/site/src/pages/WorkspacesPage/WorkspacesPageView.tsx @@ -47,7 +47,6 @@ export interface WorkspacesPageViewProps { onCheckChange: (checkedWorkspaces: Workspace[]) => void; onDeleteAll: () => void; canCheckWorkspaces: boolean; - templatesFetchStatus: TemplateQuery["status"]; templates: TemplateQuery["data"]; } @@ -156,6 +155,7 @@ export const WorkspacesPageView: FC< checkedWorkspaces={checkedWorkspaces} onCheckChange={onCheckChange} canCheckWorkspaces={canCheckWorkspaces} + templates={templates} /> {count !== undefined && ( void; onCheckChange: (checkedWorkspaces: Workspace[]) => void; canCheckWorkspaces: boolean; + templates?: Template[]; } export const WorkspacesTable: FC = ({ @@ -48,9 +45,8 @@ export const WorkspacesTable: FC = ({ onUpdateWorkspace, onCheckChange, canCheckWorkspaces, + templates, }) => { - const theme = useTheme(); - return ( @@ -93,47 +89,10 @@ export const WorkspacesTable: FC = ({ )} {workspaces && workspaces.length === 0 && ( - <> - {isUsingFilter ? ( - - ) : ( - } - variant="contained" - data-testid="button-select-template" - > - Select a Template - - } - image={ -
- -
- } - /> - )} - + )} {workspaces && workspaces.map((workspace) => {