import type { Interpolation, Theme } from "@emotion/react"; import FormHelperText from "@mui/material/FormHelperText"; import TextField from "@mui/material/TextField"; import type * as TypesGen from "api/typesGenerated"; import { Alert } from "components/Alert/Alert"; import { ErrorAlert } from "components/Alert/ErrorAlert"; import { Avatar } from "components/Avatar/Avatar"; import { Button } from "components/Button/Button"; import { FormFields, FormFooter, FormSection, HorizontalForm, } from "components/Form/Form"; import { Margins } from "components/Margins/Margins"; import { PageHeader, PageHeaderSubtitle, PageHeaderTitle, } from "components/PageHeader/PageHeader"; import { Pill } from "components/Pill/Pill"; import { RichParameterInput } from "components/RichParameterInput/RichParameterInput"; import { Spinner } from "components/Spinner/Spinner"; import { Stack } from "components/Stack/Stack"; import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete"; import { type FormikContextType, useFormik } from "formik"; import { generateWorkspaceName } from "modules/workspaces/generateWorkspaceName"; import { type FC, useCallback, useEffect, useMemo, useState } from "react"; import { getFormHelpers, nameValidator, onChangeTrimmed, } from "utils/formUtils"; import { type AutofillBuildParameter, getInitialRichParameterValues, useValidationSchemaForRichParameters, } from "utils/richParameters"; import * as Yup from "yup"; import type { CreateWorkspaceMode, ExternalAuthPollingState, } from "./CreateWorkspacePage"; import { ExternalAuthButton } from "./ExternalAuthButton"; import type { CreateWSPermissions } from "./permissions"; export const Language = { duplicationWarning: "Duplicating a workspace only copies its parameters. No state from the old workspace is copied over.", } as const; export interface CreateWorkspacePageViewProps { mode: CreateWorkspaceMode; defaultName?: string | null; disabledParams?: string[]; error: unknown; resetMutation: () => void; defaultOwner: TypesGen.User; template: TypesGen.Template; versionId?: string; externalAuth: TypesGen.TemplateVersionExternalAuth[]; externalAuthPollingState: ExternalAuthPollingState; startPollingExternalAuth: () => void; hasAllRequiredExternalAuth: boolean; parameters: TypesGen.TemplateVersionParameter[]; autofillParameters: AutofillBuildParameter[]; permissions: CreateWSPermissions; creatingWorkspace: boolean; onCancel: () => void; onSubmit: ( req: TypesGen.CreateWorkspaceRequest, owner: TypesGen.User, ) => void; } export const CreateWorkspacePageView: FC = ({ mode, defaultName, disabledParams, error, resetMutation, defaultOwner, template, versionId, externalAuth, externalAuthPollingState, startPollingExternalAuth, hasAllRequiredExternalAuth, parameters, autofillParameters, permissions, creatingWorkspace, onSubmit, onCancel, }) => { const [owner, setOwner] = useState(defaultOwner); const [suggestedName, setSuggestedName] = useState(() => generateWorkspaceName(), ); const rerollSuggestedName = useCallback(() => { setSuggestedName(() => generateWorkspaceName()); }, []); const form: FormikContextType = useFormik({ initialValues: { name: defaultName ?? "", template_id: template.id, rich_parameter_values: getInitialRichParameterValues( parameters, autofillParameters, ), }, validationSchema: Yup.object({ name: nameValidator("Workspace Name"), rich_parameter_values: useValidationSchemaForRichParameters(parameters), }), enableReinitialize: true, onSubmit: (request) => { if (!hasAllRequiredExternalAuth) { return; } onSubmit(request, owner); }, }); useEffect(() => { if (error) { window.scrollTo(0, 0); } }, [error]); const getFieldHelpers = getFormHelpers( form, error, ); const autofillByName = useMemo( () => Object.fromEntries( autofillParameters.map((param) => [param.name, param]), ), [autofillParameters], ); return ( Cancel } >
{template.display_name.length > 0 ? template.display_name : template.name} New workspace
{template.deprecated && Deprecated}
{Boolean(error) && } {mode === "duplicate" && ( {Language.duplicationWarning} )} {/* General info */} {versionId && versionId !== template.active_version_id && ( This parameter has been preset, and cannot be modified. )}
Need a suggestion?{" "}
{permissions.createWorkspaceForUser && ( { setOwner(user ?? defaultOwner); }} label="Owner" size="medium" /> )}
{externalAuth && externalAuth.length > 0 && ( {Boolean(error) && !hasAllRequiredExternalAuth && ( To create a workspace using this template, please connect to all required external authentication providers listed below. )} {externalAuth.map((auth) => ( ))} )} {parameters.length > 0 && ( {/* The parameter fields are densely packed and carry significant information, hence they require additional vertical spacing for better readability and user experience. */} {parameters.map((parameter, index) => { const parameterField = `rich_parameter_values.${index}`; const parameterInputName = `${parameterField}.value`; const isDisabled = disabledParams?.includes( parameter.name.toLowerCase().replace(/ /g, "_"), ) || creatingWorkspace; return ( { await form.setFieldValue(parameterField, { name: parameter.name, value, }); }} key={parameter.name} parameter={parameter} parameterAutofill={autofillByName[parameter.name]} disabled={isDisabled} /> ); })} )}
); }; const styles = { nameSuggestion: (theme) => ({ color: theme.roles.notice.fill.solid, padding: "4px 8px", lineHeight: "inherit", fontSize: "inherit", height: "unset", minWidth: "unset", }), hasDescription: { paddingBottom: 16, }, description: (theme) => ({ fontSize: 13, color: theme.palette.text.secondary, }), } satisfies Record>;