Skip to content

Commit d3e3d67

Browse files
committed
feat: add isAdmin prop to menuItems for conditional rendering of settings and update related components
1 parent 0a96e7c commit d3e3d67

File tree

7 files changed

+56
-16
lines changed

7 files changed

+56
-16
lines changed

src/lib/menuItems.test.ts

+29-8
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ describe('menuItems', () => {
1515
menuItems({
1616
path: '/team/devteam',
1717
features,
18-
member: true
18+
member: true,
19+
isAdmin: false
1920
})
2021
).toEqual([
2122
[{ label: 'Team overview', href: '/team/devteam', active: true }],
@@ -53,7 +54,8 @@ describe('menuItems', () => {
5354
expect(
5455
menuItems({
5556
path: '/team/nais/prod-gcp/secret/github-backup-config',
56-
member: true
57+
member: true,
58+
isAdmin: false
5759
})
5860
.flatMap((g) => g)
5961
.find((i) => i.label === 'Secrets')?.active
@@ -64,7 +66,8 @@ describe('menuItems', () => {
6466
expect(
6567
menuItems({
6668
path: '/team/nais/prod-gcp/postgres/gemini',
67-
member: true
69+
member: true,
70+
isAdmin: false
6871
})
6972
.flatMap((g) => g)
7073
.find((i) => i.label === 'Postgres')?.active
@@ -76,7 +79,8 @@ describe('menuItems', () => {
7679
menuItems({
7780
path: '/team/nais/prod-gcp/valkey/gemini',
7881
features,
79-
member: true
82+
member: true,
83+
isAdmin: false
8084
})
8185
.flatMap((g) => g)
8286
.find((i) => i.label === 'Valkey')?.active
@@ -87,7 +91,8 @@ describe('menuItems', () => {
8791
expect(
8892
menuItems({
8993
path: '/team/devteam/jobs',
90-
member: true
94+
member: true,
95+
isAdmin: false
9196
})
9297
.flatMap((g) => g)
9398
.find((i) =>
@@ -101,7 +106,8 @@ describe('menuItems', () => {
101106
menuItems({
102107
path: '/team/tbd/jobs',
103108
features,
104-
member: false
109+
member: false,
110+
isAdmin: false
105111
})
106112
.flatMap((g) => g)
107113
.find((i) => ['Secrets', 'Activity log', 'Settings'].includes(i.label))
@@ -113,6 +119,7 @@ describe('menuItems', () => {
113119
path: '/team/tbd/jobs',
114120
features,
115121
member: true,
122+
isAdmin: false,
116123
inventory: {
117124
applications: { total: 42, notNais: 10 },
118125
jobs: { total: 1, notNais: 1 },
@@ -145,14 +152,27 @@ describe('menuItems', () => {
145152
{ label: 'BigQuery', count: 49 }
146153
]);
147154
});
155+
test('show settings when admin', () => {
156+
expect(
157+
menuItems({
158+
path: '/team/nais',
159+
features,
160+
member: false,
161+
isAdmin: true
162+
})
163+
.flatMap((g) => g)
164+
.find((i) => ['Settings'].includes(i.label))
165+
).toBeDefined();
166+
});
148167
});
149168

150169
describe('workload menu', () => {
151170
test('full', () => {
152171
expect(
153172
menuItems({
154173
path: '/team/devteam/dev/app/app-w-all-storage/utilization',
155-
member: true
174+
member: true,
175+
isAdmin: false
156176
})
157177
).toEqual([
158178
[{ label: 'App overview', href: '/team/devteam/dev/app/app-w-all-storage' }],
@@ -187,7 +207,8 @@ describe('menuItems', () => {
187207
expect(
188208
menuItems({
189209
path: '/team/devteam/dev/job/dataproduct-apps-topics/vulnerability-report',
190-
member: false
210+
member: false,
211+
isAdmin: false
191212
})
192213
.flatMap((g) => g)
193214
.find((i) => ['Delete'].includes(i.label))

src/lib/menuItems.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ export const menuItems = ({
22
path,
33
features,
44
member,
5-
inventory
5+
inventory,
6+
isAdmin
67
}: {
78
path: string;
89
features?: {
@@ -24,6 +25,7 @@ export const menuItems = ({
2425
kafkaTopics: { total: number };
2526
bigQueryDatasets: { total: number };
2627
};
28+
isAdmin: boolean;
2729
}): { label: string; href: string; active?: boolean; count?: number; badge?: boolean }[][] => {
2830
const split = path.split('/');
2931

@@ -111,7 +113,7 @@ export const menuItems = ({
111113
[
112114
menuItem('Members', 'members'),
113115
menuItem('Repositories', 'repositories'),
114-
member && menuItem('Settings', 'settings'),
116+
(member || isAdmin) && menuItem('Settings', 'settings'),
115117
member && menuItem('Activity log', 'activity-log')
116118
].filter(Boolean) as { label: string; href: string; active?: boolean }[]
117119
];

src/routes/team/[team]/+layout.svelte

+5-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
} = $derived(data);
2020
const gitHubOrganization = page.data.githubOrganization;
2121
const gitHubTeam = $derived(externalResources.gitHubTeam?.slug);
22+
23+
const isAdmin = $derived(
24+
UserInfo.data?.me.__typename === 'User' ? UserInfo.data?.me.isAdmin : false
25+
);
2226
</script>
2327

2428
<svelte:head><title>{teamSlug} - Console</title></svelte:head>
@@ -37,7 +41,7 @@
3741
{/if}
3842

3943
<div class="main">
40-
<Menu features={UserInfo.data?.features} member={viewerIsMember} {teamSlug} />
44+
<Menu features={UserInfo.data?.features} member={viewerIsMember} {teamSlug} {isAdmin} />
4145
<div class="container">
4246
<PageHeader {gitHubOrganization} {gitHubTeam} {purpose} {slackChannel} />
4347

src/routes/team/[team]/Menu.svelte

+4-1
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77
88
const {
99
member,
10+
isAdmin,
1011
features,
1112
teamSlug
1213
}: {
1314
member: boolean;
15+
isAdmin: boolean;
1416
features?: {
1517
unleash: { enabled: boolean };
1618
redis: { enabled: boolean };
@@ -71,6 +73,7 @@
7173
path: page.url.pathname,
7274
member,
7375
inventory: $Inventory.fetching ? undefined : $Inventory.data?.team.inventoryCounts,
74-
features
76+
features,
77+
isAdmin
7578
})}
7679
/>

src/routes/team/[team]/settings/+page.svelte

+7-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import EditText from './EditText.svelte';
2222
2323
let { data }: PageProps = $props();
24-
let { teamSlug } = $derived(data);
24+
let { teamSlug, viewerIsMember } = $derived(data);
2525
2626
const rotateKey = graphql(`
2727
mutation RotateDeployKey($team: Slug!) {
@@ -143,6 +143,7 @@
143143
descriptionErrors = data.errors;
144144
}
145145
}}
146+
isMember={viewerIsMember}
146147
/>
147148
</i>
148149

@@ -168,6 +169,7 @@
168169
defaultSlackChannelErrors = data.errors;
169170
}
170171
}}
172+
isMember={viewerIsMember}
171173
/>
172174
</p>
173175
<GraphErrors errors={defaultSlackChannelErrors} size="small" />
@@ -199,6 +201,7 @@
199201
slackChannelsErrors = data.errors;
200202
}
201203
}}
204+
isMember={viewerIsMember}
202205
/>
203206
</div>
204207
{/each}
@@ -301,6 +304,7 @@
301304
showKey = !showKey;
302305
}}
303306
icon={EyeIcon}
307+
disabled={!viewerIsMember}
304308
/>
305309
{/if}
306310
</div>
@@ -314,6 +318,7 @@
314318
variant="action"
315319
copyText={deployKey.key}
316320
size="small"
321+
disabled={!viewerIsMember}
317322
/>
318323
</div>
319324
<div class="button">
@@ -324,6 +329,7 @@
324329
showRotateKey = !showRotateKey;
325330
}}
326331
icon={ArrowsCirclepathIcon}
332+
disabled={!viewerIsMember}
327333
>
328334
Rotate key
329335
</Button>

src/routes/team/[team]/settings/+page.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import type { BeforeLoadEvent } from './$houdini';
44
export async function _houdini_beforeLoad({ parent }: BeforeLoadEvent) {
55
const pd = await parent();
66

7-
if (!pd.viewerIsMember) {
7+
if (
8+
!pd.viewerIsMember &&
9+
!(pd.UserInfo.data?.me.__typename === 'User' && pd.UserInfo.data?.me.isAdmin)
10+
) {
811
error(403, 'You are not allowed to view this page');
912
}
1013
}

src/routes/team/[team]/settings/EditText.svelte

+3-2
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
66
interface Props {
77
text: string;
8+
isMember: boolean;
89
variant?: 'textfield' | 'textarea';
910
}
1011
11-
let { text, variant = 'textarea' }: Props = $props();
12+
let { text, variant = 'textarea', isMember }: Props = $props();
1213
1314
const distpatch = createEventDispatcher<{ save: string }>();
1415
@@ -37,7 +38,7 @@
3738
bind:value={newText}
3839
></textarea>
3940
{/if}
40-
<Button onclick={save} size="xsmall">Save</Button>
41+
<Button onclick={save} size="xsmall" disabled={!isMember}>Save</Button>
4142
<Button onclick={reset} size="xsmall" variant="secondary-neutral">Cancel</Button>
4243
</div>
4344
{:else if height !== undefined}

0 commit comments

Comments
 (0)