1
+ import groupBy from 'lodash/groupBy' ;
2
+
1
3
import IdBadge from 'sentry/components/idBadge' ;
2
4
import { t } from 'sentry/locale' ;
3
5
import type { Project } from 'sentry/types' ;
@@ -6,9 +8,24 @@ import type {Project} from 'sentry/types';
6
8
import type { InputFieldProps } from './inputField' ;
7
9
import SelectField from './selectField' ;
8
10
11
+ /**
12
+ * Function used to group projects by returning the key of the group
13
+ */
14
+ type GroupProjects = ( project : Project ) => string ;
15
+
9
16
// projects can be passed as a direct prop as well
10
17
export interface RenderFieldProps extends InputFieldProps {
11
18
avatarSize ?: number ;
19
+ /**
20
+ * When using groupProjects you can specify the labels of the groups as a
21
+ * mapping of the key returned for the groupProjects to the label
22
+ */
23
+ groupLabels ?: Record < string , React . ReactNode > ;
24
+ /**
25
+ * Controls grouping of projects within the field. Useful to prioritize some
26
+ * projects above others
27
+ */
28
+ groupProjects ?: GroupProjects ;
12
29
projects ?: Project [ ] ;
13
30
/**
14
31
* Use the slug as the select field value. Without setting this the numeric id
@@ -19,23 +36,37 @@ export interface RenderFieldProps extends InputFieldProps {
19
36
20
37
function SentryProjectSelectorField ( {
21
38
projects,
39
+ groupProjects,
40
+ groupLabels,
22
41
avatarSize = 20 ,
23
42
placeholder = t ( 'Choose Sentry project' ) ,
24
43
valueIsSlug,
25
44
...props
26
45
} : RenderFieldProps ) {
27
- const projectOptions = projects ?. map ( project => ( {
28
- value : project [ valueIsSlug ? 'slug' : 'id' ] ,
29
- label : project . slug ,
30
- leadingItems : (
31
- < IdBadge
32
- project = { project }
33
- avatarSize = { avatarSize }
34
- avatarProps = { { consistentWidth : true } }
35
- hideName
36
- />
37
- ) ,
38
- } ) ) ;
46
+ function projectToOption ( project : Project ) {
47
+ return {
48
+ value : project [ valueIsSlug ? 'slug' : 'id' ] ,
49
+ label : project . slug ,
50
+ leadingItems : (
51
+ < IdBadge
52
+ project = { project }
53
+ avatarSize = { avatarSize }
54
+ avatarProps = { { consistentWidth : true } }
55
+ hideName
56
+ />
57
+ ) ,
58
+ } ;
59
+ }
60
+
61
+ const projectOptions =
62
+ projects && groupProjects
63
+ ? // Create project groups when groupProjects is in use
64
+ Object . entries ( groupBy ( projects , groupProjects ) ) . map ( ( [ key , projectsGroup ] ) => ( {
65
+ label : groupLabels ?. [ key ] ?? key ,
66
+ options : projectsGroup . map ( projectToOption ) ,
67
+ } ) )
68
+ : // Otherwise just map projects to the options
69
+ projects ?. map ( projectToOption ) ;
39
70
40
71
return < SelectField placeholder = { placeholder } options = { projectOptions } { ...props } /> ;
41
72
}
0 commit comments