1
1
import capitalize from "lodash/capitalize" ;
2
2
import type { FC } from "react" ;
3
+ import { API } from "api/api" ;
3
4
import { AuditActions , ResourceTypes } from "api/typesGenerated" ;
4
5
import {
5
6
Filter ,
@@ -13,9 +14,11 @@ import {
13
14
} from "components/Filter/menu" ;
14
15
import {
15
16
SelectFilter ,
17
+ SelectFilterSearch ,
16
18
type SelectFilterOption ,
17
19
} from "components/Filter/SelectFilter" ;
18
20
import { type UserFilterMenu , UserMenu } from "components/Filter/UserFilter" ;
21
+ import { UserAvatar } from "components/UserAvatar/UserAvatar" ;
19
22
import { docs } from "utils/docs" ;
20
23
21
24
const PRESET_FILTERS = [
@@ -42,6 +45,7 @@ interface AuditFilterProps {
42
45
user : UserFilterMenu ;
43
46
action : ActionFilterMenu ;
44
47
resourceType : ResourceTypeFilterMenu ;
48
+ organization : OrganizationsFilterMenu ;
45
49
} ;
46
50
}
47
51
@@ -58,6 +62,7 @@ export const AuditFilter: FC<AuditFilterProps> = ({ filter, error, menus }) => {
58
62
< ResourceTypeMenu { ...menus . resourceType } />
59
63
< ActionMenu { ...menus . action } />
60
64
< UserMenu menu = { menus . user } />
65
+ < OrganizationsMenu menu = { menus . organization } />
61
66
</ >
62
67
}
63
68
skeleton = {
@@ -157,3 +162,79 @@ const ResourceTypeMenu = (menu: ResourceTypeFilterMenu) => {
157
162
/>
158
163
) ;
159
164
} ;
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
+ } ;
0 commit comments