mirror of https://github.com/coder/coder.git
refactor(site): handle edge cases for non-admin users with no workspaces and templates (#10517)
This commit is contained in:
parent
55fb6b663a
commit
5b9e26a13f
|
@ -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}
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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 &&
|
||||
|
|
Loading…
Reference in New Issue