11import {
2+ Box ,
23 Button ,
34 Flex ,
45 HStack ,
@@ -10,64 +11,71 @@ import {
1011} from "@chakra-ui/react"
1112import { t } from "i18next"
1213import React , { SetStateAction , useCallback , useMemo , useState } from "react"
13- import {
14- Bar ,
15- BarChart ,
16- CartesianGrid ,
17- Cell ,
18- LabelList ,
19- LabelProps ,
20- ResponsiveContainer ,
21- XAxis ,
22- YAxis ,
23- } from "recharts"
24-
25- const BAR_HEIGHT = 40
2614
27- const CustomNameLabel = ( props : LabelProps ) => {
28- const { x, y, value } = props
15+ const CustomBar : React . FC < {
16+ name : string
17+ value : number
18+ testCaseSelection : Record < string , boolean > | null
19+ handleOnBarClick : ( name : string ) => void
20+ } > = ( { name, value, testCaseSelection, handleOnBarClick } ) => {
21+ const [ selectedColor ] = useToken ( "colors" , [ "purple.500" ] )
22+ const [ unselectedColor ] = useToken ( "colors" , [ "purple.200" ] )
2923
30- if ( typeof x !== "number" || typeof y !== "number" ) return null
24+ if ( ! testCaseSelection ) {
25+ return null
26+ }
3127
3228 return (
33- // must use html <text>, as recharts LabelList does not support custom rendering
34- < text
35- x = { x + 8 }
36- y = { y + BAR_HEIGHT / 2 }
37- dominantBaseline = "middle"
38- fill = "#000"
39- fontWeight = "500"
40- style = { { pointerEvents : "none" , whiteSpace : "nowrap" } }
29+ < HStack
30+ justify = { "start" }
31+ width = { "100%" }
32+ onClick = { ( ) => handleOnBarClick ( name ) }
33+ position = { "relative" }
34+ background = { "gray.100" }
35+ borderRadius = { "lg" }
4136 >
42- { value }
43- </ text >
37+ < Text justifyContent = { "center" } pl = { 2 } position = { "absolute" } zIndex = { 1 } >
38+ { name }
39+ </ Text >
40+ < Text position = { "absolute" } right = { 2 } zIndex = { 1 } >
41+ { value . toFixed ( ) } %
42+ </ Text >
43+ < Flex
44+ flex = { Math . max ( value , 1 ) }
45+ height = { 7 }
46+ borderRadius = { "lg" }
47+ align = { "center" }
48+ background = { testCaseSelection [ name ] ? selectedColor : unselectedColor }
49+ position = { "relative" }
50+ > </ Flex >
51+
52+ < Flex flex = { 100 - Math . max ( value , 1 ) } />
53+ </ HStack >
4454 )
4555}
4656
47- const CustomValueLabel = ( { x, y, width, value } : LabelProps ) => {
48- const estimateTextWidth = ( text : string ) => text . length * 20
49-
50- const label = `${ Math . round ( Number ( value ) ) } %`
51- const padding = 16
52- const estimatedTextWidth = estimateTextWidth ( label )
53- const shouldRender =
54- typeof width === "number" && width > estimatedTextWidth + padding
55-
56- if ( ! shouldRender || typeof x !== "number" || typeof y !== "number" )
57- return null
57+ type BarChartData = {
58+ name : string
59+ value : number
60+ }
5861
62+ const CustomBarChart : React . FC < {
63+ data : BarChartData [ ]
64+ testCaseSelection : Record < string , boolean > | null
65+ handleOnBarClick : ( name : string ) => void
66+ } > = ( { data, testCaseSelection, handleOnBarClick } ) => {
5967 return (
60- < text
61- x = { x + width - 8 }
62- y = { y + BAR_HEIGHT / 2 }
63- dominantBaseline = "middle"
64- textAnchor = "end"
65- fill = "white"
66- fontWeight = "bold"
67- style = { { pointerEvents : "none" , whiteSpace : "nowrap" } }
68- >
69- { label }
70- </ text >
68+ < VStack width = { "full" } overflow = { "auto" } >
69+ { data . map ( ( entry , i ) => (
70+ < CustomBar
71+ name = { entry . name }
72+ value = { entry . value }
73+ testCaseSelection = { testCaseSelection }
74+ handleOnBarClick = { handleOnBarClick }
75+ key = { i }
76+ / >
77+ ) ) }
78+ </ VStack >
7179 )
7280}
7381
@@ -93,7 +101,7 @@ export const TestCaseBarChart: React.FC<{
93101 const data = useMemo ( ( ) => {
94102 return Object . entries ( passRatePerTestCase ) . map ( ( [ name , value ] ) => ( {
95103 name,
96- value : Math . max ( value * 100 , 1 ) ,
104+ value : value * 100 ,
97105 } ) )
98106 } , [ passRatePerTestCase ] )
99107
@@ -149,28 +157,8 @@ export const TestCaseBarChart: React.FC<{
149157 return data
150158 } , [ data , sorting ] )
151159
152- const [ selectedColor ] = useToken ( "colors" , [ "purple.500" ] )
153- const [ unselectedColor ] = useToken ( "colors" , [ "purple.200" ] )
154-
155- const barCells = useMemo ( ( ) => {
156- if ( ! testCaseSelection ) return
157- return sortedData . map ( ( entry ) => (
158- < Cell
159- key = { `cell-${ entry . name } ` }
160- fill = { testCaseSelection [ entry . name ] ? selectedColor : unselectedColor }
161- onClick = { ( ) => handleOnBarClick ( entry . name ) }
162- />
163- ) )
164- } , [
165- testCaseSelection ,
166- sortedData ,
167- selectedColor ,
168- unselectedColor ,
169- handleOnBarClick ,
170- ] )
171-
172160 return (
173- < VStack display = { "flex" } width = { "full" } p = { 0 } >
161+ < VStack display = { "flex" } width = { "full" } p = { 0 } flex = { 1 } >
174162 < Flex
175163 width = { "100%" }
176164 justifyContent = { "space-between" }
@@ -194,36 +182,20 @@ export const TestCaseBarChart: React.FC<{
194182 </ HStack >
195183 </ Flex >
196184
197- < Flex flex = { 1 } width = { "100%" } >
198- < ResponsiveContainer >
199- < BarChart
200- style = { {
201- width : "100%" ,
202- height : "100%" ,
203- } }
204- data = { sortedData }
205- layout = "vertical"
206- barSize = { BAR_HEIGHT }
207- margin = { { top : 4 , right : 14 , left : 14 , bottom : 0 } }
208- >
209- < XAxis type = "number" domain = { [ 0 , 100 ] } interval = { 0 } />
210- < YAxis type = "category" dataKey = "name" hide = { true } />
211- < CartesianGrid strokeDasharray = "3 3" horizontal = { false } />
212- < Bar dataKey = "value" radius = { [ 6 , 6 , 6 , 6 ] } animationDuration = { 0 } >
213- { barCells }
214- < LabelList dataKey = "name" content = { CustomNameLabel } />
215- < LabelList dataKey = "value" content = { CustomValueLabel } />
216- </ Bar >
217- </ BarChart >
218- </ ResponsiveContainer >
219- </ Flex >
185+ < Box flex = { 1 } minH = { 0 } overflowY = "auto" width = { "full" } >
186+ < CustomBarChart
187+ data = { sortedData }
188+ testCaseSelection = { testCaseSelection }
189+ handleOnBarClick = { handleOnBarClick }
190+ > </ CustomBarChart >
191+ </ Box >
220192
221193 < HStack justify = { "space-between" } w = { "full" } display = { "flex" } >
222194 < Button borderRadius = { "lg" } onClick = { handleWorstSolutionClick } >
223- Failing All Tests
195+ Select Fail All
224196 </ Button >
225197 < Button borderRadius = { "lg" } onClick = { handlePerfectSolutionClick } >
226- Passing All Tests
198+ Select Pass All
227199 </ Button >
228200 </ HStack >
229201 </ VStack >
0 commit comments