Spaces:
Running
Running
| /** | |
| * | |
| * Copyright 2023-2025 InspectorRAGet Team | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| * | |
| **/ | |
| 'use client'; | |
| import { useMemo } from 'react'; | |
| import { | |
| DataTable, | |
| TableContainer, | |
| Table, | |
| TableHead, | |
| TableRow, | |
| TableHeader, | |
| TableBody, | |
| TableCell, | |
| } from '@carbon/react'; | |
| import { Metric, Annotation } from '@/src/types'; | |
| import { | |
| extractMetricDisplayValue, | |
| extractMetricDisplayName, | |
| } from '@/src/utilities/metrics'; | |
| import classes from './AnnotationsTable.module.scss'; | |
| // =================================================================================== | |
| // COMPUTE FUNCTIONS | |
| // =================================================================================== | |
| /** | |
| * Helper function to compute annotations table headers and rows | |
| * @param annotations full set of annotations | |
| * @returns | |
| */ | |
| function populateTable( | |
| annotations: { | |
| [key: string]: { [key: string]: Annotation }; | |
| }, | |
| metrics: Metric[], | |
| ) { | |
| // Step 0: Metric names | |
| const metricNames = metrics.map((metric) => metric.name); | |
| // Step 1: Identify headers | |
| const headers: { key: string; header: string }[] = [ | |
| { | |
| key: 'annotator', | |
| header: 'Annotator', | |
| }, | |
| ]; | |
| metrics.forEach((metric) => { | |
| headers.push({ | |
| key: metric.name, | |
| header: extractMetricDisplayName(metric), | |
| }); | |
| }); | |
| // Step 2: Build rows | |
| // Step 2.a: Collect metrics per annotator | |
| const MetricsPerAnnotator: { | |
| [key: string]: { [key: string]: string | number }; | |
| } = {}; | |
| for (const [metricName, annotators] of Object.entries(annotations)) { | |
| if (metricNames.includes(metricName)) { | |
| for (const [annotator, entry] of Object.entries(annotators)) { | |
| if (MetricsPerAnnotator.hasOwnProperty(annotator)) { | |
| MetricsPerAnnotator[annotator][metricName] = entry.value; | |
| } else { | |
| MetricsPerAnnotator[annotator] = { [metricName]: entry.value }; | |
| } | |
| } | |
| } | |
| } | |
| // Step 2.a: Formulate rows | |
| const rows: { [key: string]: any }[] = []; | |
| for (const [annotator, metricNames] of Object.entries(MetricsPerAnnotator)) { | |
| const row = { id: annotator, annotator: annotator }; | |
| for (const [metricName, value] of Object.entries(metricNames)) { | |
| row[metricName] = extractMetricDisplayValue( | |
| value, | |
| metrics.find((metric) => metric.name === metricName)?.values, | |
| ); | |
| } | |
| rows.push(row); | |
| } | |
| return [headers, rows]; | |
| } | |
| // =================================================================================== | |
| // MAIN FUNCTION | |
| // =================================================================================== | |
| export default function AnnotationsTable({ | |
| annotations, | |
| metrics, | |
| }: { | |
| annotations: { | |
| [key: string]: { [key: string]: Annotation }; | |
| }; | |
| metrics: Metric[]; | |
| }) { | |
| // Step 1: Run effects | |
| // Step 1.a: Populate table header and rows | |
| const [headers, rows] = useMemo( | |
| () => populateTable(annotations, metrics), | |
| [annotations, metrics], | |
| ); | |
| return ( | |
| <> | |
| {headers && rows && ( | |
| <div> | |
| <DataTable rows={rows} headers={headers}> | |
| {({ | |
| rows, | |
| headers, | |
| getTableProps, | |
| getHeaderProps, | |
| getRowProps, | |
| }) => ( | |
| <TableContainer className={classes.table}> | |
| <Table {...getTableProps()}> | |
| <TableHead> | |
| <TableRow> | |
| {headers.map((header, index) => ( | |
| <TableHeader | |
| key={'header--' + index} | |
| {...getHeaderProps({ header })} | |
| > | |
| {header.header} | |
| </TableHeader> | |
| ))} | |
| </TableRow> | |
| </TableHead> | |
| <TableBody> | |
| {rows.map((row, index) => ( | |
| <TableRow key={'row--' + index} {...getRowProps({ row })}> | |
| {row.cells.map((cell) => ( | |
| <TableCell key={cell.id}>{cell.value}</TableCell> | |
| ))} | |
| </TableRow> | |
| ))} | |
| </TableBody> | |
| </Table> | |
| </TableContainer> | |
| )} | |
| </DataTable> | |
| </div> | |
| )} | |
| </> | |
| ); | |
| } | |