1
1
import React , { useEffect , useMemo , useState } from "react" ;
2
2
// import { Field } from '@grafana/data';
3
- import { CollapsableSection } from '@grafana/ui' ;
3
+ import { useTheme2 , CollapsableSection , Icon } from '@grafana/ui' ;
4
4
import { LogContextProps } from "./LogContextUI" ;
5
- import { css } from "@emotion/css" ;
5
+ import { css , cx } from "@emotion/css" ;
6
6
import { QuickwitQuery } from 'LogContext/QueryBuilder' ;
7
7
8
8
@@ -21,24 +21,25 @@ const excludedFields = [
21
21
type FieldContingency = { [ value : string ] : {
22
22
count : number , pinned : boolean , active ?: boolean
23
23
} } ;
24
+ type Field = {
25
+ name : string ,
26
+ contingency : FieldContingency
27
+ }
24
28
25
29
26
- const lcAttributeItemStyle = css `
27
- display : flex;
28
- justify-content : space-between;
29
- font-size : 0.8rem ;
30
- padding-left : 10px ;
31
- & [data-active = true ] {
32
- background-color : rgba (127 , 127 , 255 , 0.1 );
33
- }
34
- & : hover {
35
- background-color : rgba (255 , 255 , 255 , 0.1 );
36
- background-opacity : 0.2 ;
37
- }
38
- ` ;
39
30
31
+ function LogContextFieldSection ( field : Field ) {
32
+ const theme = useTheme2 ( )
33
+ const hasActiveFilters = Object . entries ( field . contingency ) . map ( ( [ _ , entry ] ) => ! ! entry . active ) . reduce ( ( a , b ) => a || b , false ) ;
34
+ return (
35
+ < span className = { css ( { fontSize :theme . typography . body . fontSize , display :"flex" , alignItems : "baseline" , gap :"0.5rem" , width :"100%" } ) } >
36
+ { hasActiveFilters && < Icon name = { "filter" } className = { css ( { color :theme . colors . primary . text } ) } /> }
37
+ < span > { field . name } </ span >
38
+ </ span >
39
+ )
40
+ }
40
41
41
- type AttrbuteItemsProps = {
42
+ type FieldItemProps = {
42
43
label : string ,
43
44
contingency : {
44
45
count : number ,
@@ -47,11 +48,25 @@ type AttrbuteItemsProps = {
47
48
active ?: boolean ,
48
49
onClick : ( ) => void
49
50
}
50
- function LogContextAttributeItem ( props : AttrbuteItemsProps ) {
51
+ function LogContextFieldItem ( props : FieldItemProps ) {
52
+ const theme = useTheme2 ( )
53
+ const lcAttributeItemStyle = css ( {
54
+ display : "flex" ,
55
+ justifyContent : "space-between" ,
56
+ paddingLeft : "10px" ,
57
+ fontSize : theme . typography . bodySmall . fontSize ,
58
+ "&[data-active=true]" : {
59
+ backgroundColor : theme . colors . primary . transparent ,
60
+ } ,
61
+ "&:hover" : {
62
+ backgroundColor : theme . colors . secondary . shade ,
63
+ }
64
+ } ) ;
65
+
51
66
return (
52
67
< a className = { lcAttributeItemStyle } onClick = { props . onClick } data-active = { props . active } >
53
68
< span className = { css `text-overflow : ellipsis; min-width : 0 ; flex : 0 1 ` } > { props . label } </ span >
54
- < span className = { css `flex-grow:0` } > { props . contingency . pinned && "* " } { props . contingency . count } </ span >
69
+ < span className = { css `flex-grow:0` } > { props . contingency . pinned && < Icon name = { "crosshair" } /> } { props . contingency . count } </ span >
55
70
</ a >
56
71
)
57
72
}
@@ -72,7 +87,7 @@ type QueryBuilderProps = {
72
87
export function LogContextQueryBuilderSidebar ( props : LogContextProps & QueryBuilderProps ) {
73
88
74
89
const { row, parsedQuery, updateQuery} = props ;
75
- const [ fields , setFields ] = useState < Array < { name : string ; contingency : FieldContingency ; } > > ( [ ] ) ;
90
+ const [ fields , setFields ] = useState < Field [ ] > ( [ ] ) ;
76
91
77
92
78
93
const filteredFields = useMemo ( ( ) => (
@@ -88,7 +103,7 @@ export function LogContextQueryBuilderSidebar(props: LogContextProps & QueryBuil
88
103
const fields = filteredFields
89
104
. map ( ( f ) => {
90
105
const contingency : FieldContingency = { } ;
91
- f . values . toArray ( ) . forEach ( ( attrName , i ) => {
106
+ f . values . forEach ( ( attrName , i ) => {
92
107
if ( ! contingency [ attrName ] ) {
93
108
contingency [ attrName ] = {
94
109
count : 0 ,
@@ -115,23 +130,34 @@ export function LogContextQueryBuilderSidebar(props: LogContextProps & QueryBuil
115
130
}
116
131
}
117
132
133
+ const renderFieldSection = ( field : Field ) => {
134
+ return (
135
+ < CollapsableSection
136
+ label = { LogContextFieldSection ( field ) }
137
+ className = { css `& > div { flex-grow : 1 ; }` }
138
+ isOpen = { false } key = "log-attribute-field-{field.name}"
139
+ contentClassName = { cx ( css `margin : 0 ; padding : 0 ` ) } >
140
+ < div className = { css `display:flex; flex-direction : column; gap : 5px ` } >
141
+
142
+ { field . contingency && Object . entries ( field . contingency ) . map ( ( [ fieldValue , contingency ] , i ) => (
143
+
144
+ < LogContextFieldItem
145
+ label = { fieldValue } contingency = { contingency } key = { `field-opt${ i } ` }
146
+ onClick = { ( ) => { selectQueryFilter ( field . name , fieldValue ) } }
147
+ active = { contingency . active }
148
+ />
149
+ ) ) }
150
+ </ div >
151
+ </ CollapsableSection >
152
+ )
153
+ }
154
+
155
+
118
156
return (
119
157
< div className = { lcSidebarStyle } >
120
- { fields && fields . map ( ( field ) => (
121
- < CollapsableSection label = { ( < h6 > { field . name } </ h6 > ) } isOpen = { false } key = "log-attribute-field-{field.name}" contentClassName = { css `margin : 0 ; padding : 0 ` } >
122
- < div className = { css `display:flex; flex-direction : column; gap : 5px ` } >
123
-
124
- { field . contingency && Object . entries ( field . contingency ) . map ( ( [ fieldValue , contingency ] , i ) => (
125
-
126
- < LogContextAttributeItem
127
- label = { fieldValue } contingency = { contingency } key = { `field-opt${ i } ` }
128
- onClick = { ( ) => { selectQueryFilter ( field . name , fieldValue ) } }
129
- active = { contingency . active }
130
- />
131
- ) ) }
132
- </ div >
133
- </ CollapsableSection >
134
- ) ) }
135
- </ div >
158
+ { fields && fields . map ( ( field ) => {
159
+
160
+ return ( renderFieldSection ( field ) ) ;
161
+ } ) } </ div >
136
162
) ;
137
163
}
0 commit comments