InspectorRAGet / src /views /on-board /DataVerification.tsx
kpfadnis's picture
chore (maintainance): Update depdencies, copyright and minimal support for chat template.
e23b66d
raw
history blame
7.64 kB
/**
*
* 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 { isEmpty } from 'lodash';
import { memo, useState, useMemo, useEffect } from 'react';
import {
Button,
DataTable,
TableContainer,
Table,
TableHead,
TableRow,
TableHeader,
TableBody,
TableCell,
Pagination,
} from '@carbon/react';
import { ArrowLeft, ArrowRight, WarningAlt } from '@carbon/icons-react';
import { RawData } from '@/src/types';
import { DataErrorKinds, processData } from '@/src/processor';
import { useNotification } from '@/src/components/notification/Notification';
import ExampleTile from '@/src/components/example-tile/ExampleTile';
import classes from './DataVerification.module.scss';
interface Props {
data: RawData;
onNext: Function;
onPrev: Function;
}
interface disqualifiedTaskRow {
id: string;
taskId: string;
models: Set<string>;
metrics: Set<string>;
reasons: string[];
}
export default memo(function DataVerificationView({
data,
onNext,
onPrev,
}: Props) {
const [page, setPage] = useState(1);
const [pageSize, setPageSize] = useState(10);
const [visibleRows, setVisibleRows] = useState<disqualifiedTaskRow[]>([]);
const { createNotification } = useNotification();
// Process and validate data
const [exampleData, disqualifiedTasks, notifications] = useMemo(
() => processData(data),
[data],
);
useEffect(() => {
if (notifications) {
notifications.forEach((notification) => {
createNotification(notification);
});
}
}, [notifications]);
// Create headers, rows and visible rows
const headers = [
{
key: 'taskId',
header: 'Task ID',
},
{
key: 'models',
header: 'Missing Models',
},
{
key: 'metrics',
header: 'Missing Metrics',
},
{
key: 'reasons',
header: 'Reasons',
},
];
const rows = useMemo(() => {
return Object.keys(disqualifiedTasks).map((taskId) => {
const missingModels = new Set<string>();
const missingMetrics = new Set<string>();
const reasons = new Set<string>();
disqualifiedTasks[taskId].reasons.forEach((reason) => {
reasons.add(reason.kind);
if (reason.kind === DataErrorKinds.MISSING_METRIC) {
missingMetrics.add(reason.data);
} else if (reason.kind === DataErrorKinds.MISSING_MODEL) {
missingModels.add(reason.data);
}
});
return {
id: taskId,
taskId: taskId,
models: missingModels,
metrics: missingMetrics,
reasons: [...reasons],
};
});
}, [disqualifiedTasks]);
useEffect(
() =>
setVisibleRows(
rows.slice((page - 1) * pageSize, (page - 1) * pageSize + pageSize),
),
[rows, page, pageSize],
);
return (
<div className={classes.root}>
{exampleData ? (
<>
<ExampleTile
data={exampleData}
disableNavigation={true}
></ExampleTile>
{isEmpty(rows) ? (
<div className={classes.successMessageContainer}>
<h3>Everything looks good. Enjoy analyzing!</h3>
</div>
) : (
<>
<h4>Disqualified Tasks</h4>
{headers && rows && (
<div className={classes.disqualifiedTasksContainer}>
<DataTable rows={visibleRows} 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.info.header != 'taskId'
? !isEmpty(cell.value)
? [...cell.value].join(', ')
: '-'
: cell.value}
</TableCell>
))}
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
)}
</DataTable>
<Pagination
pageSizes={[10]}
totalItems={rows.length}
onChange={(event: any) => {
// Step 1: Update page size
setPageSize(event.pageSize);
// Step 2: Update page
setPage(event.page);
}}
></Pagination>
</div>
)}
</>
)}
<div className={classes.navigationContainer}>
{exampleData.tasks.length > 500 ? (
<div className={classes.warningContainer}>
<WarningAlt
className={classes.warningContainerIcon}
size={18}
/>
<span className={classes.warningContainerText}>
{`Due to high number of data points, it might take us a moment to get everything ready once you click the "visualize" button.`}
</span>
</div>
) : null}
<div className={classes.navigationButtons}>
<Button
kind="secondary"
renderIcon={ArrowLeft}
iconDescription="Return to uploading data"
onClick={onPrev}
>
Return to uploading data
</Button>
<Button
disabled={!exampleData}
renderIcon={ArrowRight}
iconDescription="Proceed"
onClick={() => {
onNext(exampleData);
}}
>
Visualize
</Button>
</div>
</div>
</>
) : null}
</div>
);
});