Skip to content

Commit 8da0a3a

Browse files
committed
feat: show summary if unable to edit org
This can happen if you can edit the members, for example, but not the organization settings. In this case you will see a new summary page instead of the edit form.
1 parent c648c54 commit 8da0a3a

6 files changed

+105
-13
lines changed

site/src/pages/ManagementSettingsPage/OrganizationSettingsPage.test.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,4 +116,24 @@ describe("OrganizationSettingsPage", () => {
116116
await renderPage("the-endless-void");
117117
await screen.findByText("Organization not found");
118118
});
119+
120+
it("cannot edit organization", async () => {
121+
server.use(
122+
http.get("/api/v2/organizations", () => {
123+
return HttpResponse.json([MockDefaultOrganization]);
124+
}),
125+
http.post("/api/v2/authcheck", async () => {
126+
return HttpResponse.json({
127+
viewDeploymentValues: true,
128+
});
129+
}),
130+
);
131+
// No form since they cannot edit, instead sees the summary view.
132+
await renderPage(MockDefaultOrganization.name);
133+
expect(screen.queryByTestId("org-settings-form")).not.toBeInTheDocument();
134+
await screen.findByRole("heading", {
135+
level: 1,
136+
name: MockDefaultOrganization.display_name,
137+
});
138+
});
119139
});

site/src/pages/ManagementSettingsPage/OrganizationSettingsPage.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
useOrganizationSettings,
1616
} from "./ManagementSettingsLayout";
1717
import { OrganizationSettingsPageView } from "./OrganizationSettingsPageView";
18+
import { OrganizationSummaryPageView } from "./OrganizationSummaryPageView";
1819

1920
const OrganizationSettingsPage: FC = () => {
2021
const { organization: organizationName } = useParams() as {
@@ -65,12 +66,18 @@ const OrganizationSettingsPage: FC = () => {
6566
return <EmptyState message="Organization not found" />;
6667
}
6768

69+
// The user may not be able to edit this org but they can still see it because
70+
// they can edit members, etc. In this case they will be shown a read-only
71+
// summary page instead of the settings form.
72+
if (!permissions[organization.id]?.editOrganization) {
73+
return <OrganizationSummaryPageView organization={organization} />;
74+
}
75+
6876
const error =
6977
updateOrganizationMutation.error ?? deleteOrganizationMutation.error;
7078

7179
return (
7280
<OrganizationSettingsPageView
73-
canEdit={permissions[organization.id]?.editOrganization ?? false}
7481
organization={organization}
7582
error={error}
7683
onSubmit={async (values) => {

site/src/pages/ManagementSettingsPage/OrganizationSettingsPageView.stories.tsx

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ const meta: Meta<typeof OrganizationSettingsPageView> = {
1010
component: OrganizationSettingsPageView,
1111
args: {
1212
organization: MockOrganization,
13-
canEdit: true,
1413
},
1514
};
1615

@@ -24,9 +23,3 @@ export const DefaultOrg: Story = {
2423
organization: MockDefaultOrganization,
2524
},
2625
};
27-
28-
export const CannotEdit: Story = {
29-
args: {
30-
canEdit: false,
31-
},
32-
};

site/src/pages/ManagementSettingsPage/OrganizationSettingsPageView.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,11 @@ interface OrganizationSettingsPageViewProps {
4444
error: unknown;
4545
onSubmit: (values: UpdateOrganizationRequest) => Promise<void>;
4646
onDeleteOrganization: () => void;
47-
canEdit: boolean;
4847
}
4948

5049
export const OrganizationSettingsPageView: FC<
5150
OrganizationSettingsPageViewProps
52-
> = ({ organization, error, onSubmit, onDeleteOrganization, canEdit }) => {
51+
> = ({ organization, error, onSubmit, onDeleteOrganization }) => {
5352
const form = useFormik<UpdateOrganizationRequest>({
5453
initialValues: {
5554
name: organization.name,
@@ -85,7 +84,7 @@ export const OrganizationSettingsPageView: FC<
8584
description="The name and description of the organization."
8685
>
8786
<fieldset
88-
disabled={form.isSubmitting || !canEdit}
87+
disabled={form.isSubmitting}
8988
css={{ border: "unset", padding: 0, margin: 0, width: "100%" }}
9089
>
9190
<FormFields>
@@ -117,10 +116,10 @@ export const OrganizationSettingsPageView: FC<
117116
</FormFields>
118117
</fieldset>
119118
</FormSection>
120-
{canEdit && <FormFooter isLoading={form.isSubmitting} />}
119+
<FormFooter isLoading={form.isSubmitting} />
121120
</HorizontalForm>
122121

123-
{canEdit && !organization.is_default && (
122+
{!organization.is_default && (
124123
<HorizontalContainer css={{ marginTop: 48 }}>
125124
<HorizontalSection
126125
title="Settings"
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import type { Meta, StoryObj } from "@storybook/react";
2+
import {
3+
MockDefaultOrganization,
4+
MockOrganization,
5+
} from "testHelpers/entities";
6+
import { OrganizationSummaryPageView } from "./OrganizationSummaryPageView";
7+
8+
const meta: Meta<typeof OrganizationSummaryPageView> = {
9+
title: "pages/OrganizationSummaryPageView",
10+
component: OrganizationSummaryPageView,
11+
args: {
12+
organization: MockOrganization,
13+
},
14+
};
15+
16+
export default meta;
17+
type Story = StoryObj<typeof OrganizationSummaryPageView>;
18+
19+
export const DefaultOrg: Story = {
20+
args: {
21+
organization: MockDefaultOrganization,
22+
},
23+
};
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import type { FC } from "react";
2+
import type { Organization } from "api/typesGenerated";
3+
import {
4+
PageHeader,
5+
PageHeaderTitle,
6+
PageHeaderSubtitle,
7+
} from "components/PageHeader/PageHeader";
8+
import { Stack } from "components/Stack/Stack";
9+
import { UserAvatar } from "components/UserAvatar/UserAvatar";
10+
11+
interface OrganizationSummaryPageViewProps {
12+
organization: Organization;
13+
}
14+
15+
export const OrganizationSummaryPageView: FC<
16+
OrganizationSummaryPageViewProps
17+
> = (props) => {
18+
return (
19+
<div>
20+
<PageHeader
21+
css={{
22+
// The deployment settings layout already has padding.
23+
paddingTop: 0,
24+
}}
25+
>
26+
<Stack direction="row" spacing={3} alignItems="center">
27+
<UserAvatar
28+
key={props.organization.id}
29+
size="xl"
30+
username={
31+
props.organization.display_name || props.organization.name
32+
}
33+
avatarURL={props.organization.icon}
34+
/>
35+
<div>
36+
<PageHeaderTitle>
37+
{props.organization.display_name || props.organization.name}
38+
</PageHeaderTitle>
39+
{props.organization.description && (
40+
<PageHeaderSubtitle>
41+
{props.organization.description}
42+
</PageHeaderSubtitle>
43+
)}
44+
</div>
45+
</Stack>
46+
</PageHeader>
47+
You are a member of this organization.
48+
</div>
49+
);
50+
};

0 commit comments

Comments
 (0)