Skip to content

Commit 6255f4a

Browse files
committed
ui: use correct group in correct environment, and fix error notifications for partial errors
1 parent 2313d6e commit 6255f4a

File tree

4 files changed

+72
-23
lines changed

4 files changed

+72
-23
lines changed

src/common/config.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@ type ValueOrArray<T> = T | ArrayOfValueOrArray<T>;
99
type GroupRoleMapping = Record<string, readonly AppRoles[]>;
1010
type AzureRoleMapping = Record<string, readonly AppRoles[]>;
1111
type UserRoleMapping = Record<string, readonly AppRoles[]>;
12-
type KnownGroupMappings = {
13-
Exec: string;
14-
}
1512

1613
export type ConfigType = {
1714
GroupRoleMapping: GroupRoleMapping;

src/ui/config.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { execCouncilGroupId, execCouncilTestingGroupId } from '@common/config';
2+
13
export const runEnvironments = ['dev', 'prod', 'local-dev'] as const;
24
// local dev should be used when you want to test against a local instance of the API
35

@@ -9,6 +11,9 @@ export type ValidService = ValidServices;
911
export type ConfigType = {
1012
AadValidClientId: string;
1113
ServiceConfiguration: Record<ValidServices, ServiceConfiguration>;
14+
KnownGroupMappings: {
15+
Exec: string;
16+
};
1217
};
1318

1419
export type ServiceConfiguration = {
@@ -45,6 +50,9 @@ const environmentConfig: EnvironmentConfigType = {
4550
baseEndpoint: 'https://merchapi.acm.illinois.edu',
4651
},
4752
},
53+
KnownGroupMappings: {
54+
Exec: execCouncilTestingGroupId,
55+
},
4856
},
4957
dev: {
5058
AadValidClientId: 'd1978c23-6455-426a-be4d-528b2d2e4026',
@@ -65,6 +73,9 @@ const environmentConfig: EnvironmentConfigType = {
6573
baseEndpoint: 'https://merchapi.acm.illinois.edu',
6674
},
6775
},
76+
KnownGroupMappings: {
77+
Exec: execCouncilTestingGroupId,
78+
},
6879
},
6980
prod: {
7081
AadValidClientId: '43fee67e-e383-4071-9233-ef33110e9386',
@@ -85,6 +96,9 @@ const environmentConfig: EnvironmentConfigType = {
8596
baseEndpoint: 'https://merchapi.acm.illinois.edu',
8697
},
8798
},
99+
KnownGroupMappings: {
100+
Exec: execCouncilGroupId,
101+
},
88102
},
89103
} as const;
90104

src/ui/pages/iam/GroupMemberManagement.tsx

Lines changed: 54 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -70,25 +70,62 @@ export const GroupMemberManagement: React.FC<GroupMemberManagementProps> = ({
7070
setIsLoading(true);
7171
try {
7272
const response = await updateMembers(toAdd, toRemove);
73-
if (response.success) {
74-
setMembers((prev) =>
75-
prev
76-
.filter((member) => !toRemove.includes(member.email))
77-
.concat(toAdd.map((email) => ({ name: '', email })))
78-
);
79-
setToAdd([]);
80-
setToRemove([]);
73+
let { success, failure } = response;
74+
if (!success) {
75+
success = [];
76+
}
77+
if (!failure) {
78+
failure = [];
8179
}
8280

83-
notifications.show({
84-
title: 'Success',
85-
message: 'Changes saved successfully!',
86-
color: 'green',
87-
});
81+
const successfulAdds = success.filter((entry) => toAdd.includes(entry.email));
82+
const successfulRemoves = success.filter((entry) => toRemove.includes(entry.email));
83+
const failedAdds = failure.filter(({ email }) => toAdd.includes(email));
84+
const failedRemoves = failure.filter(({ email }) => toRemove.includes(email));
85+
86+
setMembers((prev) =>
87+
prev
88+
.filter((member) => !successfulRemoves.some((remove) => remove.email === member.email))
89+
.concat(successfulAdds.map(({ email }) => ({ name: email.split('@')[0], email })))
90+
);
91+
92+
setToAdd([]);
93+
setToRemove([]);
94+
95+
if (failure.length === 0) {
96+
notifications.show({
97+
title: 'Success',
98+
message: 'All changes processed successfully!',
99+
color: 'green',
100+
});
101+
} else {
102+
failedAdds.forEach(({ email, message }) => {
103+
notifications.show({
104+
title: `Error adding ${email}`,
105+
message,
106+
color: 'red',
107+
});
108+
});
109+
110+
failedRemoves.forEach(({ email, message }) => {
111+
notifications.show({
112+
title: `Error removing ${email}`,
113+
message,
114+
color: 'red',
115+
});
116+
});
117+
const allSuccess = successfulAdds.concat(successfulRemoves);
118+
allSuccess.forEach(({ email }) => {
119+
notifications.show({
120+
message: `Successfully modified ${email}`,
121+
color: 'green',
122+
});
123+
});
124+
}
88125
} catch (error) {
89126
notifications.show({
90127
title: 'Error',
91-
message: 'Failed to save changes.',
128+
message: 'Failed to save changes due to an unexpected error.',
92129
color: 'red',
93130
});
94131
} finally {
@@ -99,7 +136,7 @@ export const GroupMemberManagement: React.FC<GroupMemberManagementProps> = ({
99136
return (
100137
<Box p="md">
101138
<Text fw={500} mb={4}>
102-
Exec Group Management
139+
Exec Council Group Management
103140
</Text>
104141

105142
{/* Member List */}
@@ -117,7 +154,7 @@ export const GroupMemberManagement: React.FC<GroupMemberManagementProps> = ({
117154
{member.name} ({member.email})
118155
</Text>
119156
{toRemove.includes(member.email) && (
120-
<Badge color="green" size="sm">
157+
<Badge color="red" size="sm">
121158
Queued for removal
122159
</Badge>
123160
)}
@@ -137,7 +174,7 @@ export const GroupMemberManagement: React.FC<GroupMemberManagementProps> = ({
137174
<Group justify="space-between">
138175
<Box>
139176
<Text size="sm">{member}</Text>
140-
<Badge color="red" size="sm">
177+
<Badge color="green" size="sm">
141178
Queued for addition
142179
</Badge>
143180
</Box>

src/ui/pages/iam/ManageIam.page.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@ import { useApi } from '@ui/util/api';
55
import { AppRoles } from '@common/roles';
66
import UserInvitePanel from './UserInvitePanel';
77
import GroupMemberManagement from './GroupMemberManagement';
8-
import { execCouncilGroupId } from '@common/config';
98
import {
109
EntraActionResponse,
1110
GroupMemberGetResponse,
1211
GroupModificationPatchRequest,
1312
} from '@common/types/iam';
13+
import { getRunEnvironmentConfig } from '@ui/config';
1414

1515
export const ManageIamPage = () => {
1616
const api = useApi('core');
17+
const groupId = getRunEnvironmentConfig().KnownGroupMappings.Exec;
1718

1819
const handleInviteSubmit = async (emailList: string[]) => {
1920
try {
@@ -35,7 +36,7 @@ export const ManageIamPage = () => {
3536

3637
const getExecMembers = async () => {
3738
try {
38-
const response = await api.get(`/api/v1/iam/groups/${execCouncilGroupId}`);
39+
const response = await api.get(`/api/v1/iam/groups/${groupId}`);
3940
return response.data as GroupMemberGetResponse;
4041
} catch (error: any) {
4142
console.error('Failed to get users:', error);
@@ -46,7 +47,7 @@ export const ManageIamPage = () => {
4647
const updateExecMembers = async (toAdd: string[], toRemove: string[]) => {
4748
const allMembers = toAdd.concat(toRemove);
4849
try {
49-
const response = await api.patch(`/api/v1/iam/groups/${execCouncilGroupId}`, {
50+
const response = await api.patch(`/api/v1/iam/groups/${groupId}`, {
5051
remove: toRemove,
5152
add: toAdd,
5253
} as GroupModificationPatchRequest);

0 commit comments

Comments
 (0)