refactor(site): handle edge cases for non-admin users with no workspaces and templates (#10517)

This commit is contained in:
Bruno Quaresma 2023-11-06 09:34:45 -03:00 committed by GitHub
parent 55fb6b663a
commit 5b9e26a13f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 100 additions and 8 deletions

View File

@ -8,19 +8,76 @@ import { Link } from "react-router-dom";
export const WorkspacesEmpty = (props: {
isUsingFilter: boolean;
templates?: Template[];
canCreateTemplate: boolean;
}) => {
const { isUsingFilter, templates } = props;
const { isUsingFilter, templates, canCreateTemplate } = props;
const totalFeaturedTemplates = 6;
const featuredTemplates = templates?.slice(0, totalFeaturedTemplates);
const defaultTitle = "Create a workspace";
const defaultMessage =
"A workspace is your personal, customizable development environment.";
const defaultImage = (
<div
css={{
maxWidth: "50%",
height: 272,
overflow: "hidden",
marginTop: 48,
opacity: 0.85,
"& img": {
maxWidth: "100%",
},
}}
>
<img src="/featured/workspaces.webp" alt="" />
</div>
);
if (isUsingFilter) {
return <TableEmpty message="No results matched your search" />;
}
if (templates && templates.length === 0 && canCreateTemplate) {
return (
<TableEmpty
message={defaultTitle}
description={`${defaultMessage} To create a workspace, you first need to create a template.`}
cta={
<Button
component={Link}
to="/templates"
variant="contained"
startIcon={<ArrowForwardOutlined />}
>
Go to templates
</Button>
}
css={{
paddingBottom: 0,
}}
image={defaultImage}
/>
);
}
if (templates && templates.length === 0 && !canCreateTemplate) {
return (
<TableEmpty
message={defaultTitle}
description={`${defaultMessage} There are no templates available, but you will see them here once your admin adds them.`}
css={{
paddingBottom: 0,
}}
image={defaultImage}
/>
);
}
return (
<TableEmpty
message="Create a workspace"
description="A workspace is your personal, customizable development environment in the cloud. Select one template below to start."
message={defaultTitle}
description={`${defaultMessage} Select one template below to start.`}
cta={
<div>
<div
@ -80,6 +137,7 @@ export const WorkspacesEmpty = (props: {
</Link>
))}
</div>
{templates && templates.length > totalFeaturedTemplates && (
<Button
component={Link}

View File

@ -97,6 +97,7 @@ const WorkspacesPage: FC = () => {
const { entitlements } = useDashboard();
const canCheckWorkspaces =
entitlements.features["workspace_batch_actions"].enabled;
const permissions = usePermissions();
// We want to uncheck the selected workspaces always when the url changes
// because of filtering or pagination
@ -111,6 +112,7 @@ const WorkspacesPage: FC = () => {
</Helmet>
<WorkspacesPageView
canCreateTemplate={permissions.createTemplates}
checkedWorkspaces={checkedWorkspaces}
onCheckChange={setCheckedWorkspaces}
canCheckWorkspaces={canCheckWorkspaces}

View File

@ -147,6 +147,33 @@ export const OwnerHasNoWorkspaces: Story = {
args: {
workspaces: [],
count: 0,
canCreateTemplate: true,
},
};
export const OwnerHasNoWorkspacesAndNoTemplates: Story = {
args: {
workspaces: [],
templates: [],
count: 0,
canCreateTemplate: true,
},
};
export const UserHasNoWorkspaces: Story = {
args: {
workspaces: [],
count: 0,
canCreateTemplate: false,
},
};
export const UserHasNoWorkspacesAndNoTemplates: Story = {
args: {
workspaces: [],
templates: [],
count: 0,
canCreateTemplate: false,
},
};

View File

@ -1,6 +1,6 @@
import { Template, Workspace } from "api/typesGenerated";
import { PaginationWidgetBase } from "components/PaginationWidget/PaginationWidgetBase";
import { ComponentProps, FC } from "react";
import { ComponentProps } from "react";
import { Margins } from "components/Margins/Margins";
import { PageHeader, PageHeaderTitle } from "components/PageHeader/PageHeader";
import { Stack } from "components/Stack/Stack";
@ -49,11 +49,10 @@ export interface WorkspacesPageViewProps {
canCheckWorkspaces: boolean;
templatesFetchStatus: TemplateQuery["status"];
templates: TemplateQuery["data"];
canCreateTemplate: boolean;
}
export const WorkspacesPageView: FC<
React.PropsWithChildren<WorkspacesPageViewProps>
> = ({
export const WorkspacesPageView = ({
workspaces,
dormantWorkspaces,
error,
@ -69,7 +68,8 @@ export const WorkspacesPageView: FC<
canCheckWorkspaces,
templates,
templatesFetchStatus,
}) => {
canCreateTemplate,
}: WorkspacesPageViewProps) => {
const { saveLocal } = useLocalStorage();
const workspacesDeletionScheduled = dormantWorkspaces
@ -149,6 +149,7 @@ export const WorkspacesPageView: FC<
</TableToolbar>
<WorkspacesTable
canCreateTemplate={canCreateTemplate}
workspaces={workspaces}
isUsingFilter={filterProps.filter.used}
onUpdateWorkspace={onUpdateWorkspace}
@ -157,6 +158,7 @@ export const WorkspacesPageView: FC<
canCheckWorkspaces={canCheckWorkspaces}
templates={templates}
/>
{count !== undefined && (
<PaginationWidgetBase
count={count}

View File

@ -36,6 +36,7 @@ export interface WorkspacesTableProps {
onCheckChange: (checkedWorkspaces: Workspace[]) => void;
canCheckWorkspaces: boolean;
templates?: Template[];
canCreateTemplate: boolean;
}
export const WorkspacesTable: FC<WorkspacesTableProps> = ({
@ -46,6 +47,7 @@ export const WorkspacesTable: FC<WorkspacesTableProps> = ({
onCheckChange,
canCheckWorkspaces,
templates,
canCreateTemplate,
}) => {
return (
<TableContainer>
@ -92,6 +94,7 @@ export const WorkspacesTable: FC<WorkspacesTableProps> = ({
<WorkspacesEmpty
templates={templates}
isUsingFilter={isUsingFilter}
canCreateTemplate={canCreateTemplate}
/>
)}
{workspaces &&