Skip to content

Commit 28789d7

Browse files
feat: add View Source button for template administrators in workspace creation (#18951)
1 parent bb83071 commit 28789d7

7 files changed

+100
-9
lines changed

site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,10 @@ const CreateWorkspacePage: FC = () => {
6565
});
6666
const permissionsQuery = useQuery({
6767
...checkAuthorization({
68-
checks: createWorkspaceChecks(templateQuery.data?.organization_id ?? ""),
68+
checks: createWorkspaceChecks(
69+
templateQuery.data?.organization_id ?? "",
70+
templateQuery.data?.id,
71+
),
6972
}),
7073
enabled: !!templateQuery.data,
7174
});
@@ -208,6 +211,7 @@ const CreateWorkspacePage: FC = () => {
208211
startPollingExternalAuth={startPollingExternalAuth}
209212
hasAllRequiredExternalAuth={hasAllRequiredExternalAuth}
210213
permissions={permissionsQuery.data as CreateWorkspacePermissions}
214+
canUpdateTemplate={permissionsQuery.data?.canUpdateTemplate}
211215
parameters={realizedParameters as TemplateVersionParameter[]}
212216
presets={templateVersionPresetsQuery.data ?? []}
213217
creatingWorkspace={createWorkspaceMutation.isPending}

site/src/pages/CreateWorkspacePage/CreateWorkspacePageExperimental.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,10 @@ const CreateWorkspacePageExperimental: FC = () => {
7979
});
8080
const permissionsQuery = useQuery({
8181
...checkAuthorization({
82-
checks: createWorkspaceChecks(templateQuery.data?.organization_id ?? ""),
82+
checks: createWorkspaceChecks(
83+
templateQuery.data?.organization_id ?? "",
84+
templateQuery.data?.id,
85+
),
8386
}),
8487
enabled: !!templateQuery.data,
8588
});
@@ -292,6 +295,7 @@ const CreateWorkspacePageExperimental: FC = () => {
292295
owner={owner}
293296
setOwner={setOwner}
294297
autofillParameters={autofillParameters}
298+
canUpdateTemplate={permissionsQuery.data?.canUpdateTemplate}
295299
error={
296300
wsError ||
297301
createWorkspaceMutation.error ||

site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const meta: Meta<typeof CreateWorkspacePageView> = {
2828
mode: "form",
2929
permissions: {
3030
createWorkspaceForAny: true,
31+
canUpdateTemplate: false,
3132
},
3233
onCancel: action("onCancel"),
3334
},
@@ -382,3 +383,23 @@ export const ExternalAuthAllConnected: Story = {
382383
],
383384
},
384385
};
386+
387+
export const WithViewSourceButton: Story = {
388+
args: {
389+
canUpdateTemplate: true,
390+
versionId: "template-version-123",
391+
template: {
392+
...MockTemplate,
393+
organization_name: "default",
394+
name: "docker-template",
395+
},
396+
},
397+
parameters: {
398+
docs: {
399+
description: {
400+
story:
401+
"This story shows the View Source button that appears for template administrators. The button allows quick navigation to the template editor from the workspace creation page.",
402+
},
403+
},
404+
},
405+
};

site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@ import { Switch } from "components/Switch/Switch";
2727
import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete";
2828
import { type FormikContextType, useFormik } from "formik";
2929
import type { ExternalAuthPollingState } from "hooks/useExternalAuth";
30+
import { ExternalLinkIcon } from "lucide-react";
3031
import { generateWorkspaceName } from "modules/workspaces/generateWorkspaceName";
3132
import { type FC, useCallback, useEffect, useMemo, useState } from "react";
33+
import { Link } from "react-router-dom";
3234
import {
3335
getFormHelpers,
3436
nameValidator,
@@ -67,6 +69,7 @@ interface CreateWorkspacePageViewProps {
6769
presets: TypesGen.Preset[];
6870
permissions: CreateWorkspacePermissions;
6971
creatingWorkspace: boolean;
72+
canUpdateTemplate?: boolean;
7073
onCancel: () => void;
7174
onSubmit: (
7275
req: TypesGen.CreateWorkspaceRequest,
@@ -92,6 +95,7 @@ export const CreateWorkspacePageView: FC<CreateWorkspacePageViewProps> = ({
9295
presets = [],
9396
permissions,
9497
creatingWorkspace,
98+
canUpdateTemplate,
9599
onSubmit,
96100
onCancel,
97101
}) => {
@@ -218,9 +222,21 @@ export const CreateWorkspacePageView: FC<CreateWorkspacePageViewProps> = ({
218222
<Margins size="medium">
219223
<PageHeader
220224
actions={
221-
<Button size="sm" variant="outline" onClick={onCancel}>
222-
Cancel
223-
</Button>
225+
<Stack direction="row" spacing={2}>
226+
{canUpdateTemplate && (
227+
<Button asChild size="sm" variant="outline">
228+
<Link
229+
to={`/templates/${template.organization_name}/${template.name}/versions/${versionId}/edit`}
230+
>
231+
<ExternalLinkIcon />
232+
View source
233+
</Link>
234+
</Button>
235+
)}
236+
<Button size="sm" variant="outline" onClick={onCancel}>
237+
Cancel
238+
</Button>
239+
</Stack>
224240
}
225241
>
226242
<Stack direction="row">

site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.stories.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const meta: Meta<typeof CreateWorkspacePageViewExperimental> = {
2020
parameters: [],
2121
permissions: {
2222
createWorkspaceForAny: true,
23+
canUpdateTemplate: false,
2324
},
2425
presets: [],
2526
sendMessage: () => {},
@@ -38,3 +39,23 @@ export const WebsocketError: Story = {
3839
),
3940
},
4041
};
42+
43+
export const WithViewSourceButton: Story = {
44+
args: {
45+
canUpdateTemplate: true,
46+
versionId: "template-version-123",
47+
template: {
48+
...MockTemplate,
49+
organization_name: "default",
50+
name: "docker-template",
51+
},
52+
},
53+
parameters: {
54+
docs: {
55+
description: {
56+
story:
57+
"This story shows the View Source button that appears for template administrators in the experimental workspace creation page. The button allows quick navigation to the template editor.",
58+
},
59+
},
60+
},
61+
};

site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {
2626
import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete";
2727
import { type FormikContextType, useFormik } from "formik";
2828
import type { ExternalAuthPollingState } from "hooks/useExternalAuth";
29-
import { ArrowLeft, CircleHelp } from "lucide-react";
29+
import { ArrowLeft, CircleHelp, ExternalLinkIcon } from "lucide-react";
3030
import { useSyncFormParameters } from "modules/hooks/useSyncFormParameters";
3131
import {
3232
Diagnostics,
@@ -43,6 +43,7 @@ import {
4343
useRef,
4444
useState,
4545
} from "react";
46+
import { Link as RouterLink } from "react-router-dom";
4647
import { docs } from "utils/docs";
4748
import { nameValidator } from "utils/formUtils";
4849
import type { AutofillBuildParameter } from "utils/richParameters";
@@ -53,6 +54,7 @@ import type { CreateWorkspacePermissions } from "./permissions";
5354

5455
interface CreateWorkspacePageViewExperimentalProps {
5556
autofillParameters: AutofillBuildParameter[];
57+
canUpdateTemplate?: boolean;
5658
creatingWorkspace: boolean;
5759
defaultName?: string | null;
5860
defaultOwner: TypesGen.User;
@@ -84,6 +86,7 @@ export const CreateWorkspacePageViewExperimental: FC<
8486
CreateWorkspacePageViewExperimentalProps
8587
> = ({
8688
autofillParameters,
89+
canUpdateTemplate,
8790
creatingWorkspace,
8891
defaultName,
8992
defaultOwner,
@@ -378,6 +381,16 @@ export const CreateWorkspacePageViewExperimental: FC<
378381
</Badge>
379382
)}
380383
</span>
384+
{canUpdateTemplate && (
385+
<Button asChild size="sm" variant="outline">
386+
<RouterLink
387+
to={`/templates/${template.organization_name}/${template.name}/versions/${versionId}/edit`}
388+
>
389+
<ExternalLinkIcon />
390+
View source
391+
</RouterLink>
392+
</Button>
393+
)}
381394
</div>
382395
<span className="flex flex-row items-center gap-2">
383396
<h1 className="text-3xl font-semibold m-0">New workspace</h1>

site/src/pages/CreateWorkspacePage/permissions.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,25 @@
1-
export const createWorkspaceChecks = (organizationId: string) =>
1+
export const createWorkspaceChecks = (
2+
organizationId: string,
3+
templateId?: string,
4+
) =>
25
({
36
createWorkspaceForAny: {
47
object: {
5-
resource_type: "workspace",
8+
resource_type: "workspace" as const,
69
organization_id: organizationId,
710
owner_id: "*",
811
},
9-
action: "create",
12+
action: "create" as const,
1013
},
14+
...(templateId && {
15+
canUpdateTemplate: {
16+
object: {
17+
resource_type: "template" as const,
18+
resource_id: templateId,
19+
},
20+
action: "update" as const,
21+
},
22+
}),
1123
}) as const;
1224

1325
export type CreateWorkspacePermissions = Record<

0 commit comments

Comments
 (0)