kpfadnis's picture
chore: Initial commit.
599f646
raw
history blame
10.3 kB
/**
*
* Copyright 2023-2024 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 Link from 'next/link';
import { useMemo, memo } from 'react';
import {
ExpandableTile,
TileAboveTheFoldContent,
TileBelowTheFoldContent,
Tag,
DefinitionTooltip,
Tooltip,
Toggletip,
ToggletipButton,
ToggletipContent,
ToggletipActions,
UnorderedList,
ListItem,
Button,
} from '@carbon/react';
import {
Task as TaskIcon,
Information,
Flag,
FlagFilled,
Chat,
Copy,
} from '@carbon/icons-react';
import { Task, TaskEvaluation } from '@/src/types';
import { MetricDefinitions } from '@/src/utilities/metrics';
import { castDurationToString } from '@/src/utilities/time';
import classes from './TaskTile.module.scss';
interface Props {
task: Task;
evaluations: TaskEvaluation[];
expanded?: boolean;
onClickFlagIcon: Function;
onClickCommentsIcon: Function;
onClickCopyToClipboardIcon?: Function;
}
export default memo(function TaskTile({
task,
evaluations,
expanded = true,
onClickFlagIcon,
onClickCommentsIcon,
onClickCopyToClipboardIcon,
}: Props) {
// Step 1: Extract neccessary information
const [annotators, metrics, models, duration] = useMemo(() => {
const annotatorsMap: { [key: string]: number } = {};
const metricsSet: Set<string> = new Set();
const modelsSet: Set<string> = new Set();
evaluations.forEach((evaluation) => {
// Add model information
modelsSet.add(evaluation.modelId);
for (const metric in evaluation.annotations) {
// Add metric information
metricsSet.add(metric);
for (const annotator in evaluation.annotations[metric]) {
// Add annotator information
annotatorsMap[annotator] =
evaluation.annotations[metric][annotator].duration || 0;
}
}
});
// Calcuate average time taken by annotators
const avgDuration: number = Math.floor(
Object.values(annotatorsMap).reduce((a, b) => a + b, 0) /
Object.keys(annotatorsMap).length,
);
return [annotatorsMap, metricsSet, modelsSet, avgDuration];
}, [evaluations]);
const [
durationInDays,
durationInHours,
durationInMinutes,
durationInSeconds,
] = useMemo(() => castDurationToString(duration), [duration]);
return (
<ExpandableTile expanded={expanded}>
<TileAboveTheFoldContent>
<div className={classes.heading}>
<TaskIcon className={classes.icon} />
<span className={classes.title}>{task.taskId}</span>
<div className={classes.actions}>
<Button
key={`${task.taskId}__flag-btn`}
className={classes.flagTaskBtn}
kind={'ghost'}
renderIcon={task.flagged ? FlagFilled : Flag}
hasIconOnly={true}
iconDescription={'Flag to review later'}
tooltipAlignment={'end'}
tooltipPosition={'right'}
onClick={onClickFlagIcon}
/>
<Tooltip align={'right'} label={'Click to show / hide comments'}>
<Button
id="comment"
className={classes.commentsIndicator}
kind={'ghost'}
onClick={onClickCommentsIcon}
disabled={
task.comments === undefined || task.comments.length === 0
}
>
<Chat />
{task.comments ? task.comments.length : 0}
</Button>
</Tooltip>
{onClickCopyToClipboardIcon && (
<Button
key={`${task.taskId}__copyToClipboard-btn`}
className={classes.copyToClipboardBtn}
kind={'ghost'}
renderIcon={Copy}
hasIconOnly={true}
iconDescription={'Copy task details to clipboard'}
tooltipAlignment={'end'}
tooltipPosition={'right'}
onClick={onClickCopyToClipboardIcon}
/>
)}
</div>
</div>
</TileAboveTheFoldContent>
<TileBelowTheFoldContent>
<div className={classes.block}>
<div className={classes.information}>
<div className={classes.artifactEvaluations}>
<div className={classes.artifactTitle}>
<span># of evaluations</span>
</div>
<div className={classes.artifactValue}>
<span>{evaluations.length}</span>
</div>
</div>
<div className={classes.artifactAnnotators}>
<div className={classes.artifactTitle}>
<span># of annotators</span>
</div>
<div className={classes.artifactValue}>
<span>{Object.keys(annotators).length}</span>
</div>
</div>
<div className={classes.artifactMetrics}>
<div className={classes.artifactHeader}>
<div className={classes.artifactTitle}>
<span>Metrics</span>
</div>
<Toggletip>
<ToggletipButton label="Additional information">
<Information />
</ToggletipButton>
<ToggletipContent>
<p>Analytics platform supports three kind of metrics</p>
<UnorderedList>
<ListItem className={classes.listItem}>
Go vs No-Go Rubric
</ListItem>
<ListItem className={classes.listItem}>
Intuitive Rubric
</ListItem>
<ListItem className={classes.listItem}>
Detailed Rubric
</ListItem>
</UnorderedList>
<ToggletipActions>
<Link target="_blank" rel="noopener noreferrer" href="">
Reference
</Link>
</ToggletipActions>
</ToggletipContent>
</Toggletip>
</div>
<div className={classes.artifactValue}>
{Array.from(metrics).map((metric, idx) => {
return (
<Tag type={'cool-gray'} key={'metric-' + idx}>
<DefinitionTooltip
key={'tooltip--metric-' + idx}
definition={MetricDefinitions[metric]}
align={'bottom'}
openOnHover={true}
>
{metric}
</DefinitionTooltip>
</Tag>
);
})}
</div>
</div>
<div className={classes.artifactModels}>
<div className={classes.artifactTitle}>
<span>Models</span>
</div>
<div className={classes.artifactValue}>
{Array.from(models).map((model, idx) => {
return (
<Tag type={'cool-gray'} key={'model-' + idx}>
{model}
</Tag>
);
})}
</div>
</div>
{durationInDays ||
durationInHours ||
durationInMinutes ||
durationInSeconds ? (
<div className={classes.artifactDuration}>
<div className={classes.artifactTitle}>
<span>Duration</span>
</div>
<div className={classes.artifactValue}>
<DefinitionTooltip
definition={Object.keys(annotators).map(
(annotator, idx) => {
// Step 1: Convert duration to string
const [
durationInDaysForAnnotator,
durationInHoursForAnnotator,
durationInMinutesForAnnotator,
durationInSecondsForAnnotator,
] = castDurationToString(annotators[annotator]);
return (
<>
<span key={'annotator-' + idx}>
{annotator}:&nbsp;
{durationInDaysForAnnotator
? durationInDaysForAnnotator + ' days '
: ''}
{durationInHoursForAnnotator
? durationInHoursForAnnotator + ' hours '
: ''}
{durationInMinutesForAnnotator
? durationInMinutesForAnnotator + ' mins '
: ''}
{durationInSecondsForAnnotator} sec
</span>
<br />
</>
);
},
)}
align={'bottom'}
openOnHover={true}
>
<span>
{durationInDays ? durationInDays + ' days ' : ''}
{durationInHours ? durationInHours + ' hours ' : ''}
{durationInMinutes ? durationInMinutes + ' mins ' : ''}
{durationInSeconds} sec
</span>
</DefinitionTooltip>
</div>
</div>
) : null}
</div>
</div>
</TileBelowTheFoldContent>
</ExpandableTile>
);
});