Skip to content

Commit d007b86

Browse files
committed
chore: integrate mode into CreateWorkspacePageView
1 parent 15fdfbf commit d007b86

File tree

2 files changed

+162
-118
lines changed

2 files changed

+162
-118
lines changed

site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ const CreateWorkspacePage: FC = () => {
123123
<Loader />
124124
) : (
125125
<CreateWorkspacePageView
126+
mode={mode}
126127
defaultName={defaultName}
127128
defaultOwner={me}
128129
defaultBuildParameters={defaultBuildParameters}

site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx

Lines changed: 161 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import TextField from "@mui/material/TextField";
22
import * as TypesGen from "api/typesGenerated";
33
import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete";
44
import { FormikContextType, useFormik } from "formik";
5-
import { FC, useEffect, useState } from "react";
5+
import { FC, useEffect, useReducer, useState } from "react";
66
import {
77
getFormHelpers,
88
nameValidator,
@@ -29,11 +29,18 @@ import {
2929
import { ExternalAuth } from "./ExternalAuth";
3030
import { ErrorAlert } from "components/Alert/ErrorAlert";
3131
import { Stack } from "components/Stack/Stack";
32-
import { type ExternalAuthPollingState } from "./CreateWorkspacePage";
32+
import {
33+
CreateWorkspaceMode,
34+
type ExternalAuthPollingState,
35+
} from "./CreateWorkspacePage";
3336
import { useSearchParams } from "react-router-dom";
3437
import { CreateWSPermissions } from "./permissions";
38+
import { useTheme } from "@emotion/react";
39+
import { Margins } from "components/Margins/Margins";
40+
import { Alert } from "components/Alert/Alert";
3541

3642
export interface CreateWorkspacePageViewProps {
43+
mode: CreateWorkspaceMode;
3744
error: unknown;
3845
defaultName: string;
3946
defaultOwner: TypesGen.User;
@@ -54,6 +61,7 @@ export interface CreateWorkspacePageViewProps {
5461
}
5562

5663
export const CreateWorkspacePageView: FC<CreateWorkspacePageViewProps> = ({
64+
mode,
5765
error,
5866
defaultName,
5967
defaultOwner,
@@ -112,133 +120,143 @@ export const CreateWorkspacePageView: FC<CreateWorkspacePageViewProps> = ({
112120
);
113121

114122
return (
115-
<FullPageHorizontalForm title="New workspace" onCancel={onCancel}>
116-
<HorizontalForm onSubmit={form.handleSubmit}>
117-
{Boolean(error) && <ErrorAlert error={error} />}
118-
{/* General info */}
119-
<FormSection
120-
title="General"
121-
description="The template and name of your new workspace."
122-
>
123-
<FormFields>
124-
<SelectedTemplate template={template} />
125-
{versionId && versionId !== template.active_version_id && (
126-
<Stack spacing={1} className={styles.hasDescription}>
127-
<TextField
128-
disabled
129-
fullWidth
130-
value={versionId}
131-
label="Version ID"
132-
/>
133-
<span className={styles.description}>
134-
This parameter has been preset, and cannot be modified.
135-
</span>
136-
</Stack>
137-
)}
138-
<TextField
139-
{...getFieldHelpers("name")}
140-
disabled={creatingWorkspace}
141-
onChange={onChangeTrimmed(form)}
142-
autoFocus
143-
fullWidth
144-
label="Workspace Name"
145-
/>
146-
</FormFields>
147-
</FormSection>
123+
<>
124+
{mode === "duplicate" && <DuplicateWarningMessage />}
148125

149-
{permissions.createWorkspaceForUser && (
126+
<FullPageHorizontalForm title="New workspace" onCancel={onCancel}>
127+
<HorizontalForm onSubmit={form.handleSubmit}>
128+
{Boolean(error) && <ErrorAlert error={error} />}
129+
{/* General info */}
150130
<FormSection
151-
title="Workspace Owner"
152-
description="Only admins can create workspace for other users."
131+
title="General"
132+
description="The template and name of your new workspace."
153133
>
154134
<FormFields>
155-
<UserAutocomplete
156-
value={owner}
157-
onChange={(user) => {
158-
setOwner(user ?? defaultOwner);
159-
}}
160-
label="Owner"
161-
size="medium"
135+
<SelectedTemplate template={template} />
136+
{versionId && versionId !== template.active_version_id && (
137+
<Stack spacing={1} className={styles.hasDescription}>
138+
<TextField
139+
disabled
140+
fullWidth
141+
value={versionId}
142+
label="Version ID"
143+
/>
144+
<span className={styles.description}>
145+
This parameter has been preset, and cannot be modified.
146+
</span>
147+
</Stack>
148+
)}
149+
<TextField
150+
{...getFieldHelpers("name")}
151+
disabled={creatingWorkspace}
152+
onChange={onChangeTrimmed(form)}
153+
autoFocus
154+
fullWidth
155+
label="Workspace Name"
162156
/>
163157
</FormFields>
164158
</FormSection>
165-
)}
166159

167-
{externalAuth && externalAuth.length > 0 && (
168-
<FormSection
169-
title="External Authentication"
170-
description="This template requires authentication to external services."
171-
>
172-
<FormFields>
173-
{externalAuth.map((auth) => (
174-
<ExternalAuth
175-
key={auth.id}
176-
authenticateURL={auth.authenticate_url}
177-
authenticated={auth.authenticated}
178-
externalAuthPollingState={externalAuthPollingState}
179-
startPollingExternalAuth={startPollingExternalAuth}
180-
displayName={auth.display_name}
181-
displayIcon={auth.display_icon}
182-
error={externalAuthErrors[auth.id]}
160+
{permissions.createWorkspaceForUser && (
161+
<FormSection
162+
title="Workspace Owner"
163+
description="Only admins can create workspace for other users."
164+
>
165+
<FormFields>
166+
<UserAutocomplete
167+
value={owner}
168+
onChange={(user) => {
169+
setOwner(user ?? defaultOwner);
170+
}}
171+
label="Owner"
172+
size="medium"
183173
/>
184-
))}
185-
</FormFields>
186-
</FormSection>
187-
)}
174+
</FormFields>
175+
</FormSection>
176+
)}
188177

189-
{parameters && (
190-
<>
191-
<MutableTemplateParametersSection
192-
templateParameters={parameters}
193-
getInputProps={(parameter, index) => {
194-
return {
195-
...getFieldHelpers(
196-
"rich_parameter_values[" + index + "].value",
197-
),
198-
onChange: async (value) => {
199-
await form.setFieldValue("rich_parameter_values." + index, {
200-
name: parameter.name,
201-
value: value,
202-
});
203-
},
204-
disabled:
205-
disabledParamsList?.includes(
206-
parameter.name.toLowerCase().replace(/ /g, "_"),
207-
) || creatingWorkspace,
208-
};
209-
}}
210-
/>
211-
<ImmutableTemplateParametersSection
212-
templateParameters={parameters}
213-
classes={{ root: styles.warningSection }}
214-
getInputProps={(parameter, index) => {
215-
return {
216-
...getFieldHelpers(
217-
"rich_parameter_values[" + index + "].value",
218-
),
219-
onChange: async (value) => {
220-
await form.setFieldValue("rich_parameter_values." + index, {
221-
name: parameter.name,
222-
value: value,
223-
});
224-
},
225-
disabled:
226-
disabledParamsList?.includes(
227-
parameter.name.toLowerCase().replace(/ /g, "_"),
228-
) || creatingWorkspace,
229-
};
230-
}}
231-
/>
232-
</>
233-
)}
178+
{externalAuth && externalAuth.length > 0 && (
179+
<FormSection
180+
title="External Authentication"
181+
description="This template requires authentication to external services."
182+
>
183+
<FormFields>
184+
{externalAuth.map((auth) => (
185+
<ExternalAuth
186+
key={auth.id}
187+
authenticateURL={auth.authenticate_url}
188+
authenticated={auth.authenticated}
189+
externalAuthPollingState={externalAuthPollingState}
190+
startPollingExternalAuth={startPollingExternalAuth}
191+
displayName={auth.display_name}
192+
displayIcon={auth.display_icon}
193+
error={externalAuthErrors[auth.id]}
194+
/>
195+
))}
196+
</FormFields>
197+
</FormSection>
198+
)}
234199

235-
<FormFooter
236-
onCancel={onCancel}
237-
isLoading={creatingWorkspace}
238-
submitLabel="Create Workspace"
239-
/>
240-
</HorizontalForm>
241-
</FullPageHorizontalForm>
200+
{parameters && (
201+
<>
202+
<MutableTemplateParametersSection
203+
templateParameters={parameters}
204+
getInputProps={(parameter, index) => {
205+
return {
206+
...getFieldHelpers(
207+
"rich_parameter_values[" + index + "].value",
208+
),
209+
onChange: async (value) => {
210+
await form.setFieldValue(
211+
"rich_parameter_values." + index,
212+
{
213+
name: parameter.name,
214+
value: value,
215+
},
216+
);
217+
},
218+
disabled:
219+
disabledParamsList?.includes(
220+
parameter.name.toLowerCase().replace(/ /g, "_"),
221+
) || creatingWorkspace,
222+
};
223+
}}
224+
/>
225+
<ImmutableTemplateParametersSection
226+
templateParameters={parameters}
227+
classes={{ root: styles.warningSection }}
228+
getInputProps={(parameter, index) => {
229+
return {
230+
...getFieldHelpers(
231+
"rich_parameter_values[" + index + "].value",
232+
),
233+
onChange: async (value) => {
234+
await form.setFieldValue(
235+
"rich_parameter_values." + index,
236+
{
237+
name: parameter.name,
238+
value: value,
239+
},
240+
);
241+
},
242+
disabled:
243+
disabledParamsList?.includes(
244+
parameter.name.toLowerCase().replace(/ /g, "_"),
245+
) || creatingWorkspace,
246+
};
247+
}}
248+
/>
249+
</>
250+
)}
251+
252+
<FormFooter
253+
onCancel={onCancel}
254+
isLoading={creatingWorkspace}
255+
submitLabel="Create Workspace"
256+
/>
257+
</HorizontalForm>
258+
</FullPageHorizontalForm>
259+
</>
242260
);
243261
};
244262

@@ -279,6 +297,31 @@ const useExternalAuthVerification = (
279297
};
280298
};
281299

300+
function DuplicateWarningMessage() {
301+
const [isDismissed, dismiss] = useReducer(() => true, false);
302+
const theme = useTheme();
303+
304+
if (isDismissed) {
305+
return null;
306+
}
307+
308+
// Setup looks a little hokey (having an Alert already fully configured to
309+
// listen to dismissals, on top of more dismissal state), but relying solely
310+
// on the Alert API wouldn't get rid of the div and horizontal margin helper
311+
// after the dismiss happens. Not using CSS margins because those can be a
312+
// style maintenance nightmare over time
313+
return (
314+
<div css={{ paddingTop: theme.spacing(6) }}>
315+
<Margins size="medium">
316+
<Alert severity="warning" dismissible onDismiss={dismiss}>
317+
Duplicating a workspace only copies its parameters. No state from the
318+
old workspace is copied over.
319+
</Alert>
320+
</Margins>
321+
</div>
322+
);
323+
}
324+
282325
const useStyles = makeStyles((theme) => ({
283326
hasDescription: {
284327
paddingBottom: theme.spacing(2),

0 commit comments

Comments
 (0)