mirror of https://github.com/coder/coder.git
173 lines
5.1 KiB
TypeScript
173 lines
5.1 KiB
TypeScript
import { Template, Workspace } from "api/typesGenerated";
|
|
import { PaginationWidgetBase } from "components/PaginationWidget/PaginationWidgetBase";
|
|
import { ComponentProps } from "react";
|
|
import { Margins } from "components/Margins/Margins";
|
|
import { PageHeader, PageHeaderTitle } from "components/PageHeader/PageHeader";
|
|
import { Stack } from "components/Stack/Stack";
|
|
import { WorkspaceHelpTooltip } from "./WorkspaceHelpTooltip";
|
|
import { WorkspacesTable } from "pages/WorkspacesPage/WorkspacesTable";
|
|
import { useLocalStorage } from "hooks";
|
|
import { DormantWorkspaceBanner, Count } from "components/WorkspaceDeletion";
|
|
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
|
import { WorkspacesFilter } from "./filter/filter";
|
|
import { hasError, isApiValidationError } from "api/errors";
|
|
import {
|
|
PaginationStatus,
|
|
TableToolbar,
|
|
} from "components/TableToolbar/TableToolbar";
|
|
import Box from "@mui/material/Box";
|
|
import Button from "@mui/material/Button";
|
|
import DeleteOutlined from "@mui/icons-material/DeleteOutlined";
|
|
import { WorkspacesButton } from "./WorkspacesButton";
|
|
import { UseQueryResult } from "react-query";
|
|
|
|
export const Language = {
|
|
pageTitle: "Workspaces",
|
|
yourWorkspacesButton: "Your workspaces",
|
|
allWorkspacesButton: "All workspaces",
|
|
runningWorkspacesButton: "Running workspaces",
|
|
createWorkspace: <>Create Workspace…</>,
|
|
seeAllTemplates: "See all templates",
|
|
template: "Template",
|
|
};
|
|
|
|
type TemplateQuery = UseQueryResult<Template[]>;
|
|
|
|
export interface WorkspacesPageViewProps {
|
|
error: unknown;
|
|
workspaces?: Workspace[];
|
|
dormantWorkspaces?: Workspace[];
|
|
checkedWorkspaces: Workspace[];
|
|
count?: number;
|
|
filterProps: ComponentProps<typeof WorkspacesFilter>;
|
|
page: number;
|
|
limit: number;
|
|
onPageChange: (page: number) => void;
|
|
onUpdateWorkspace: (workspace: Workspace) => void;
|
|
onCheckChange: (checkedWorkspaces: Workspace[]) => void;
|
|
onDeleteAll: () => void;
|
|
canCheckWorkspaces: boolean;
|
|
templatesFetchStatus: TemplateQuery["status"];
|
|
templates: TemplateQuery["data"];
|
|
canCreateTemplate: boolean;
|
|
}
|
|
|
|
export const WorkspacesPageView = ({
|
|
workspaces,
|
|
dormantWorkspaces,
|
|
error,
|
|
limit,
|
|
count,
|
|
filterProps,
|
|
onPageChange,
|
|
onUpdateWorkspace,
|
|
page,
|
|
checkedWorkspaces,
|
|
onCheckChange,
|
|
onDeleteAll,
|
|
canCheckWorkspaces,
|
|
templates,
|
|
templatesFetchStatus,
|
|
canCreateTemplate,
|
|
}: WorkspacesPageViewProps) => {
|
|
const { saveLocal } = useLocalStorage();
|
|
|
|
const workspacesDeletionScheduled = dormantWorkspaces
|
|
?.filter((workspace) => workspace.deleting_at)
|
|
.map((workspace) => workspace.id);
|
|
|
|
const hasDormantWorkspace =
|
|
dormantWorkspaces !== undefined && dormantWorkspaces.length > 0;
|
|
|
|
return (
|
|
<Margins>
|
|
<PageHeader
|
|
actions={
|
|
<WorkspacesButton
|
|
templates={templates}
|
|
templatesFetchStatus={templatesFetchStatus}
|
|
>
|
|
{Language.createWorkspace}
|
|
</WorkspacesButton>
|
|
}
|
|
>
|
|
<PageHeaderTitle>
|
|
<Stack direction="row" spacing={1} alignItems="center">
|
|
<span>{Language.pageTitle}</span>
|
|
<WorkspaceHelpTooltip />
|
|
</Stack>
|
|
</PageHeaderTitle>
|
|
</PageHeader>
|
|
|
|
<Stack>
|
|
{hasError(error) && !isApiValidationError(error) && (
|
|
<ErrorAlert error={error} />
|
|
)}
|
|
{/* <DormantWorkspaceBanner/> determines its own visibility */}
|
|
<DormantWorkspaceBanner
|
|
workspaces={dormantWorkspaces}
|
|
shouldRedisplayBanner={hasDormantWorkspace}
|
|
onDismiss={() =>
|
|
saveLocal(
|
|
"dismissedWorkspaceList",
|
|
JSON.stringify(workspacesDeletionScheduled),
|
|
)
|
|
}
|
|
count={Count.Multiple}
|
|
/>
|
|
|
|
<WorkspacesFilter error={error} {...filterProps} />
|
|
</Stack>
|
|
|
|
<TableToolbar>
|
|
{checkedWorkspaces.length > 0 ? (
|
|
<>
|
|
<Box>
|
|
Selected <strong>{checkedWorkspaces.length}</strong> of{" "}
|
|
<strong>{workspaces?.length}</strong>{" "}
|
|
{workspaces?.length === 1 ? "workspace" : "workspaces"}
|
|
</Box>
|
|
|
|
<Box sx={{ marginLeft: "auto" }}>
|
|
<Button
|
|
size="small"
|
|
startIcon={<DeleteOutlined />}
|
|
onClick={onDeleteAll}
|
|
>
|
|
Delete selected
|
|
</Button>
|
|
</Box>
|
|
</>
|
|
) : (
|
|
<PaginationStatus
|
|
isLoading={!workspaces && !error}
|
|
showing={workspaces?.length ?? 0}
|
|
total={count ?? 0}
|
|
label="workspaces"
|
|
/>
|
|
)}
|
|
</TableToolbar>
|
|
|
|
<WorkspacesTable
|
|
canCreateTemplate={canCreateTemplate}
|
|
workspaces={workspaces}
|
|
isUsingFilter={filterProps.filter.used}
|
|
onUpdateWorkspace={onUpdateWorkspace}
|
|
checkedWorkspaces={checkedWorkspaces}
|
|
onCheckChange={onCheckChange}
|
|
canCheckWorkspaces={canCheckWorkspaces}
|
|
templates={templates}
|
|
/>
|
|
|
|
{count !== undefined && (
|
|
<PaginationWidgetBase
|
|
count={count}
|
|
limit={limit}
|
|
onChange={onPageChange}
|
|
page={page}
|
|
/>
|
|
)}
|
|
</Margins>
|
|
);
|
|
};
|