import Button from "@mui/material/Button" import { makeStyles } from "@mui/styles" import RefreshOutlined from "@mui/icons-material/RefreshOutlined" import { Avatar } from "components/Avatar/Avatar" import { AgentRow } from "components/Resources/AgentRow" import { WorkspaceBuildLogs } from "components/WorkspaceBuildLogs/WorkspaceBuildLogs" import { ActiveTransition, WorkspaceBuildProgress, } from "components/WorkspaceBuildProgress/WorkspaceBuildProgress" import { FC } from "react" import { useTranslation } from "react-i18next" import { useNavigate } from "react-router-dom" import * as TypesGen from "../../api/typesGenerated" import { Alert } from "../Alert/Alert" import { BuildsTable } from "../BuildsTable/BuildsTable" import { Margins } from "../Margins/Margins" import { Resources } from "../Resources/Resources" import { Stack } from "../Stack/Stack" import { WorkspaceActions } from "../WorkspaceActions/WorkspaceActions" import { WorkspaceDeletedBanner } from "../WorkspaceDeletedBanner/WorkspaceDeletedBanner" import { WorkspaceStats } from "../WorkspaceStats/WorkspaceStats" import { FullWidthPageHeader, PageHeaderActions, PageHeaderTitle, PageHeaderSubtitle, } from "components/PageHeader/FullWidthPageHeader" import { TemplateVersionWarnings } from "components/TemplateVersionWarnings/TemplateVersionWarnings" import { ErrorAlert } from "components/Alert/ErrorAlert" import { ImpendingDeletionBanner } from "components/WorkspaceDeletion" import { useLocalStorage } from "hooks" import { ChooseOne, Cond } from "components/Conditionals/ChooseOne" export enum WorkspaceErrors { GET_BUILDS_ERROR = "getBuildsError", BUILD_ERROR = "buildError", CANCELLATION_ERROR = "cancellationError", } export interface WorkspaceProps { scheduleProps: { onDeadlinePlus: (hours: number) => void onDeadlineMinus: (hours: number) => void maxDeadlineIncrease: number maxDeadlineDecrease: number } handleStart: () => void handleStop: () => void handleRestart: () => void handleDelete: () => void handleUpdate: () => void handleCancel: () => void handleSettings: () => void handleChangeVersion: () => void isUpdating: boolean isRestarting: boolean workspace: TypesGen.Workspace resources?: TypesGen.WorkspaceResource[] builds?: TypesGen.WorkspaceBuild[] templateWarnings?: TypesGen.TemplateVersionWarning[] canUpdateWorkspace: boolean canUpdateTemplate: boolean canChangeVersions: boolean hideSSHButton?: boolean hideVSCodeDesktopButton?: boolean workspaceErrors: Partial> buildInfo?: TypesGen.BuildInfoResponse sshPrefix?: string template?: TypesGen.Template quota_budget?: number failedBuildLogs: TypesGen.ProvisionerJobLog[] | undefined handleBuildRetry: () => void } /** * Workspace is the top-level component for viewing an individual workspace */ export const Workspace: FC> = ({ scheduleProps, handleStart, handleStop, handleRestart, handleDelete, handleUpdate, handleCancel, handleSettings, handleChangeVersion, workspace, isUpdating, isRestarting, resources, builds, canUpdateWorkspace, canUpdateTemplate, canChangeVersions, workspaceErrors, hideSSHButton, hideVSCodeDesktopButton, buildInfo, sshPrefix, template, quota_budget, failedBuildLogs, handleBuildRetry, templateWarnings, }) => { const styles = useStyles() const navigate = useNavigate() const serverVersion = buildInfo?.version || "" const { t } = useTranslation("workspacePage") const { saveLocal, getLocal } = useLocalStorage() const buildError = Boolean(workspaceErrors[WorkspaceErrors.BUILD_ERROR]) && ( ) const cancellationError = Boolean( workspaceErrors[WorkspaceErrors.CANCELLATION_ERROR], ) && ( ) let transitionStats: TypesGen.TransitionStats | undefined = undefined if (template !== undefined) { transitionStats = ActiveTransition(template, workspace) } return ( <> {workspace.name}
{workspace.name} {workspace.owner_name}
{buildError} {cancellationError} navigate(`/templates`)} /> {/* determines its own visibility */} saveLocal("dismissedWorkspace", workspace.id)} /> {failedBuildLogs && ( Workspace build failed {workspace.latest_build.job.error} {canUpdateTemplate && (
)}
)} {transitionStats !== undefined && ( )} {typeof resources !== "undefined" && resources.length > 0 && ( ( )} /> )} {workspaceErrors[WorkspaceErrors.GET_BUILDS_ERROR] ? ( ) : ( )}
) } const spacerWidth = 300 export const useStyles = makeStyles((theme) => { return { content: { marginTop: theme.spacing(4), }, statusBadge: { marginLeft: theme.spacing(2), }, actions: { [theme.breakpoints.down("md")]: { flexDirection: "column", }, }, firstColumnSpacer: { flex: 2, }, secondColumnSpacer: { flex: `0 0 ${spacerWidth}px`, }, layout: { alignItems: "flex-start", }, main: { width: "100%", }, timelineContents: { margin: 0, }, logs: { border: `1px solid ${theme.palette.divider}`, }, errorDetails: { color: theme.palette.text.secondary, fontSize: 12, }, fullWidth: { width: "100%", }, } })