-
Paul Pestov authoredPaul Pestov authored
WorkflowsTable.vue 5.31 KiB
<template>
<div>
<div class="_display:flex _margin-bottom:4" v-if="evals.length > 0">
<div class="_display:flex _align-items:center _margin-left:auto">
<p class="_margin-right:2">{{ $t('group_by') }}:</p>
<i-select
v-model="sortBy"
:options="sortOptions"
modelValue="value"
idField="label"
placeholder="Choose something.."
@update:modelValue="onChange($event.value)"
/>
</div>
</div>
<i-table v-if="evals.length > 0" class="_width:100%" condensed border="true">
<thead>
<tr>
<th class="_padding-left:2">{{ sortBy.value === 'documents' ? $t('documents') : $t('workflows') }}</th>
<th class="_padding-left:2">{{ sortBy.value === 'documents' ? $t('workflows') : $t('documents') }}</th>
<th v-for="(evalKey, i) in evals" :key="i">
<span class="def-label _display:flex _align-items:center _justify-content:center _cursor:pointer">
{{ defs[evalKey] ? defs[evalKey].label : evalKey }}
<i-icon name="ink-info"/>
<div class="def-tooltip">
<i-card>
{{ defs[evalKey] ? defs[evalKey].short_descr : $t('no_description') }}.
<a v-if="defs[evalKey]" :href="defs[evalKey].url">{{ $t('details') }}</a>
</i-card>
</div>
</span>
</th>
</tr>
</thead>
<tbody>
<template v-for="(key, i) in Object.keys(groupedData)" :key="i">
<tr v-for="(subject, j) in groupedData[key].subjects" :key="j">
<td v-if="j === 0" :rowspan="groupedData[key].subjects.length" class="_vertical-align:top _padding-left:2">
<span class="_font-weight:bold">{{ groupedData[key].label }}</span>
</td>
<td class="_vertical-align:top _padding-left:2">{{ subject.label }}</td>
<td
v-for="({ name, value }, k) in subject.evaluations"
:key="k"
class="_text-align:center"
:class="(j === groupedData[key].subjects.length - 1) ? '_padding-bottom:5' : ''"
>
<i-badge
size="lg"
class="metric _cursor:pointer _padding-x:1"
:class="getEvalColor(name, value)">
{{ createReadableMetricValue(name, value) }}
</i-badge>
</td>
</tr>
</template>
</tbody>
</i-table>
<div>{{ $t('no_table_data') }}</div>
</div>
</template>
<script setup>
import { watch, ref } from "vue";
import { useI18n } from "vue-i18n";
import { createReadableMetricValue, getEvalColor } from "@/helpers/utils";
const { t } = useI18n();
const props = defineProps(['data', 'defs']);
const groupedData = ref({});
const evals = ref([]);
const sortOptions = ref([{
value: 'documents',
label: t('documents')
}, {
value: 'workflows',
label: t('workflows')
}]);
const sortBy = ref(sortOptions.value[0]);
const onChange = (value) => {
if (value === 'workflows') groupByWorkflows();
else if (value === 'documents') groupByDocuments();
};
const groupByWorkflows = () => {
groupedData.value = props.data.filter(item => !!(item.metadata.ocr_workflow)).reduce((acc, cur) => {
const ocrWorkflowId = cur.metadata.ocr_workflow['@id'];
const label = cur.metadata.ocr_workflow.label;
evals.value = Object.keys(cur.evaluation_results.document_wide);
const subject = {
label: cur.metadata.gt_workspace.label,
evaluations: Object.keys(cur.evaluation_results.document_wide).map(key => ({
name: key,
value: cur.evaluation_results.document_wide[key]
}))
};
if (!acc[ocrWorkflowId]) {
acc[ocrWorkflowId] = {
label,
subjects: [subject]
};
} else {
acc[ocrWorkflowId].subjects.push(subject);
acc[ocrWorkflowId].subjects.sort((a, b) => {
if (a.label > b.label) return 1;
else return -1;
});
}
return acc;
}, {});
};
const groupByDocuments = () => {
groupedData.value = props.data.filter(item => !!(item.metadata.gt_workspace)).reduce((acc, cur) => {
const gtWorkspaceId = cur.metadata.gt_workspace['@id'];
const label = cur.metadata.gt_workspace.label;
evals.value = Object.keys(cur.evaluation_results.document_wide);
const subject = {
label: cur.metadata.ocr_workflow.label,
evaluations: Object.keys(cur.evaluation_results.document_wide).map(key => ({
name: key,
value: cur.evaluation_results.document_wide[key]
}))
};
if (!acc[gtWorkspaceId]) {
acc[gtWorkspaceId] = {
label,
subjects: [subject]
};
} else {
acc[gtWorkspaceId].subjects.push(subject);
acc[gtWorkspaceId].subjects.sort((a, b) => {
if (a.label > b.label) return 1;
else return -1;
});
}
return acc;
}, {});
};
watch(() => props.data, groupByDocuments, { immediate: true });
</script>
<style scoped lang="scss">
.def-label {
position: relative;
&:hover {
.def-tooltip {
visibility: visible;
}
}
}
.def-tooltip {
visibility: hidden;
position: absolute;
top: 0;
transform: translateY(-100%);
width: 300px;
z-index: 100;
padding-bottom: 10px;
.card {
box-shadow: rgba(0, 0, 0, 0.1) 0px 20px 25px -5px, rgba(0, 0, 0, 0.04) 0px 10px 10px -5px;
}
}
th, th span {
font-weight: bold;
}
</style>