@@ -11,6 +11,7 @@ import MenuItem from '@mui/joy/MenuItem';
1111import Dropdown from '@mui/joy/Dropdown' ;
1212import Checkbox from '@mui/joy/Checkbox' ;
1313import Tooltip from '@mui/joy/Tooltip' ;
14+ import Chip from '@mui/joy/Chip' ;
1415import {
1516 Trash2Icon ,
1617 LineChartIcon ,
@@ -122,6 +123,61 @@ const JobsList: React.FC<JobsListProps> = ({
122123 return type . charAt ( 0 ) . toUpperCase ( ) + type . slice ( 1 ) ;
123124 } ;
124125
126+ const formatScoreValue = ( value : number ) : string => {
127+ if ( ! Number . isFinite ( value ) ) return String ( value ) ;
128+ if ( Math . abs ( value ) >= 1000 ) return value . toFixed ( 1 ) ;
129+ if ( Math . abs ( value ) >= 100 ) return value . toFixed ( 2 ) ;
130+ if ( Math . abs ( value ) >= 1 ) return value . toFixed ( 3 ) ;
131+ return value . toFixed ( 4 ) ;
132+ } ;
133+
134+ const getScoreDisplay = (
135+ score : unknown ,
136+ ) : { label : string ; tooltip ?: string } | null => {
137+ if ( typeof score === 'number' ) {
138+ return { label : `Score: ${ formatScoreValue ( score ) } ` } ;
139+ }
140+
141+ if ( typeof score === 'string' ) {
142+ const parsed = Number . parseFloat ( score ) ;
143+ if ( Number . isFinite ( parsed ) ) {
144+ return { label : `Score: ${ formatScoreValue ( parsed ) } ` } ;
145+ }
146+ if ( score . trim ( ) ) {
147+ return { label : `Score: ${ score . trim ( ) } ` } ;
148+ }
149+ return null ;
150+ }
151+
152+ if ( score && typeof score === 'object' ) {
153+ const numericEntries = Object . entries ( score as Record < string , unknown > )
154+ . filter ( ( [ key ] ) => key . toLowerCase ( ) !== 'discard' )
155+ . map ( ( [ key , val ] ) => [ key , Number ( val ) ] as const )
156+ . filter ( ( [ , val ] ) => Number . isFinite ( val ) ) ;
157+
158+ if ( numericEntries . length === 0 ) return null ;
159+
160+ const preferredMetric =
161+ numericEntries . find ( ( [ key ] ) => key . toLowerCase ( ) === 'score' ) ??
162+ numericEntries [ 0 ] ;
163+ const [ firstMetric , firstValue ] = preferredMetric ;
164+
165+ const tooltip =
166+ numericEntries . length > 1
167+ ? numericEntries
168+ . map ( ( [ metric , val ] ) => `${ metric } : ${ formatScoreValue ( val ) } ` )
169+ . join ( ' | ' )
170+ : undefined ;
171+
172+ return {
173+ label : `${ firstMetric } : ${ formatScoreValue ( firstValue ) } ` ,
174+ tooltip,
175+ } ;
176+ }
177+
178+ return null ;
179+ } ;
180+
125181 const formatJobConfig = ( job : any ) => {
126182 const jobData = job ?. job_data || { } ;
127183 const interactiveType =
@@ -176,6 +232,7 @@ const JobsList: React.FC<JobsListProps> = ({
176232 const userInfo = jobData . user_info || { } ;
177233 const userDisplay = userInfo . name || userInfo . email || '' ;
178234 const providerDisplay = jobData . provider_name || job ?. provider_name || '' ;
235+ const scoreDisplay = getScoreDisplay ( jobData ?. score ) ;
179236
180237 if ( job ?. placeholder ) {
181238 return (
@@ -215,6 +272,21 @@ const JobsList: React.FC<JobsListProps> = ({
215272 < b > Title:</ b > { taskName }
216273 </ Typography >
217274 ) }
275+ { scoreDisplay && (
276+ < Tooltip
277+ title = { scoreDisplay . tooltip || '' }
278+ disableHoverListener = { ! scoreDisplay . tooltip }
279+ >
280+ < Chip
281+ size = "sm"
282+ color = "success"
283+ variant = "soft"
284+ sx = { { mt : 0.5 , width : 'fit-content' } }
285+ >
286+ { scoreDisplay . label }
287+ </ Chip >
288+ </ Tooltip >
289+ ) }
218290 </ >
219291 ) ;
220292 }
@@ -242,6 +314,21 @@ const JobsList: React.FC<JobsListProps> = ({
242314 < b > Provider:</ b > { providerDisplay }
243315 </ Typography >
244316 ) }
317+ { scoreDisplay && (
318+ < Tooltip
319+ title = { scoreDisplay . tooltip || '' }
320+ disableHoverListener = { ! scoreDisplay . tooltip }
321+ >
322+ < Chip
323+ size = "sm"
324+ color = "success"
325+ variant = "soft"
326+ sx = { { mt : 0.5 , width : 'fit-content' } }
327+ >
328+ { scoreDisplay . label }
329+ </ Chip >
330+ </ Tooltip >
331+ ) }
245332 </ >
246333 ) ;
247334 }
0 commit comments