Skip to content

Commit 0cafeb2

Browse files
committed
Add organizations filter to audit table
1 parent 590d18b commit 0cafeb2

File tree

2 files changed

+96
-1
lines changed

2 files changed

+96
-1
lines changed

site/src/pages/AuditPage/AuditFilter.tsx

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import capitalize from "lodash/capitalize";
22
import type { FC } from "react";
3+
import { API } from "api/api";
34
import { AuditActions, ResourceTypes } from "api/typesGenerated";
45
import {
56
Filter,
@@ -13,9 +14,11 @@ import {
1314
} from "components/Filter/menu";
1415
import {
1516
SelectFilter,
17+
SelectFilterSearch,
1618
type SelectFilterOption,
1719
} from "components/Filter/SelectFilter";
1820
import { type UserFilterMenu, UserMenu } from "components/Filter/UserFilter";
21+
import { UserAvatar } from "components/UserAvatar/UserAvatar";
1922
import { docs } from "utils/docs";
2023

2124
const PRESET_FILTERS = [
@@ -42,6 +45,7 @@ interface AuditFilterProps {
4245
user: UserFilterMenu;
4346
action: ActionFilterMenu;
4447
resourceType: ResourceTypeFilterMenu;
48+
organization: OrganizationsFilterMenu;
4549
};
4650
}
4751

@@ -58,6 +62,7 @@ export const AuditFilter: FC<AuditFilterProps> = ({ filter, error, menus }) => {
5862
<ResourceTypeMenu {...menus.resourceType} />
5963
<ActionMenu {...menus.action} />
6064
<UserMenu menu={menus.user} />
65+
<OrganizationsMenu menu={menus.organization} />
6166
</>
6267
}
6368
skeleton={
@@ -157,3 +162,79 @@ const ResourceTypeMenu = (menu: ResourceTypeFilterMenu) => {
157162
/>
158163
);
159164
};
165+
166+
export const useOrganizationsFilterMenu = ({
167+
value,
168+
onChange,
169+
}: Pick<UseFilterMenuOptions<SelectFilterOption>, "value" | "onChange">) => {
170+
return useFilterMenu({
171+
onChange,
172+
value,
173+
id: "organizations",
174+
getSelectedOption: async () => {
175+
if (value) {
176+
const organizations = await API.getOrganizations();
177+
const organization = organizations.find((o) => o.name === value);
178+
if (organization) {
179+
return {
180+
label: organization.display_name || organization.name,
181+
value: organization.name,
182+
startIcon: (
183+
<UserAvatar
184+
key={organization.id}
185+
size="xs"
186+
username={organization.display_name || organization.name}
187+
avatarURL={organization.icon}
188+
/>
189+
),
190+
};
191+
}
192+
}
193+
return null;
194+
},
195+
getOptions: async () => {
196+
const organizationsRes = await API.getOrganizations();
197+
return organizationsRes.map<SelectFilterOption>((organization) => ({
198+
label: organization.display_name || organization.name,
199+
value: organization.name,
200+
startIcon: (
201+
<UserAvatar
202+
key={organization.id}
203+
size="xs"
204+
username={organization.display_name || organization.name}
205+
avatarURL={organization.icon}
206+
/>
207+
),
208+
}));
209+
},
210+
});
211+
};
212+
213+
export type OrganizationsFilterMenu = ReturnType<
214+
typeof useOrganizationsFilterMenu
215+
>;
216+
217+
interface OrganizationsMenuProps {
218+
menu: OrganizationsFilterMenu;
219+
}
220+
221+
export const OrganizationsMenu: FC<OrganizationsMenuProps> = ({ menu }) => {
222+
return (
223+
<SelectFilter
224+
label="Select an organization"
225+
placeholder="All organizations"
226+
emptyText="No organizations found"
227+
options={menu.searchOptions}
228+
onSelect={menu.selectOption}
229+
selectedOption={menu.selectedOption ?? undefined}
230+
selectFilterSearch={
231+
<SelectFilterSearch
232+
inputProps={{ "aria-label": "Search organization" }}
233+
placeholder="Search organization..."
234+
value={menu.query}
235+
onChange={menu.setQuery}
236+
/>
237+
}
238+
/>
239+
);
240+
};

site/src/pages/AuditPage/AuditPage.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ import { isNonInitialPage } from "components/PaginationWidget/utils";
88
import { usePaginatedQuery } from "hooks/usePaginatedQuery";
99
import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility";
1010
import { pageTitle } from "utils/page";
11-
import { useActionFilterMenu, useResourceTypeFilterMenu } from "./AuditFilter";
11+
import {
12+
useActionFilterMenu,
13+
useOrganizationsFilterMenu,
14+
useResourceTypeFilterMenu,
15+
} from "./AuditFilter";
1216
import { AuditPageView } from "./AuditPageView";
1317

1418
const AuditPage: FC = () => {
@@ -55,6 +59,15 @@ const AuditPage: FC = () => {
5559
}),
5660
});
5761

62+
const organizationsMenu = useOrganizationsFilterMenu({
63+
value: filter.values.organization,
64+
onChange: (option) =>
65+
filter.update({
66+
...filter.values,
67+
organization: option?.value,
68+
}),
69+
});
70+
5871
return (
5972
<>
6073
<Helmet>
@@ -74,6 +87,7 @@ const AuditPage: FC = () => {
7487
user: userMenu,
7588
action: actionMenu,
7689
resourceType: resourceTypeMenu,
90+
organization: organizationsMenu,
7791
},
7892
}}
7993
/>

0 commit comments

Comments
 (0)