Skip to content

Commit

Permalink
feat: add sorting by label, metric (wip), year
Browse files Browse the repository at this point in the history
  • Loading branch information
jfrer committed Jul 2, 2024
1 parent 1fbbbac commit b6dd235
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 11 deletions.
18 changes: 13 additions & 5 deletions src/components/workflows/WorkflowsTimeline.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script setup lang="ts">
import TimelineItem from "@/components/workflows/timeline/TimelineItem.vue"
import Dropdown from 'primevue/dropdown'
import { computed, onMounted, ref, watch} from "vue"
import { computed, onBeforeMount, onMounted, ref, watch} from "vue"
import { EvaluationMetrics, getMaxValueByMetric} from '@/helpers/metrics'
import { useI18n } from "vue-i18n"
import type { DropdownOption, EvaluationResultsDocumentWide, Workflow, GroundTruth } from "@/types"
Expand All @@ -11,19 +11,26 @@ import filtersStore from '@/store/filters-store'
import timelineStore from "@/store/timeline-store"
import TrendLegend from "@/components/workflows/TrendLegend.vue";
import TimelineFilters from "./timeline/TimelineFilters.vue"
import TimelineSorting from "./timeline/TimelineSorting.vue"
const { t } = useI18n()
const gtList = computed<GroundTruth[]>(() => workflowsStore.gt.filter(({ id }) => filtersStore.gtTimeline.findIndex(({ value }) => value === id) > -1))
const workflows = ref<Workflow[]>([])
const selectedMetric = ref<DropdownOption | null>(null)
const metrics = computed<DropdownOption[]>(() => Object.keys(EvaluationMetrics).map(key => ({ value: EvaluationMetrics[key], label: t(EvaluationMetrics[key]) })))
const selectedMetricValue = computed<keyof EvaluationResultsDocumentWide>(() => <keyof EvaluationResultsDocumentWide>selectedMetric.value?.value || EvaluationMetrics.CER_MEAN)
const sortedGtList = ref<GroundTruth[]>([])
onMounted(async () => {
selectedMetric.value = metrics.value[0]
workflows.value = workflowsStore.workflows
})
watch(gtList, () => {
sortedGtList.value = gtList.value
})
watch(selectedMetric,
() => timelineStore.setMaxValue(
selectedMetricValue.value,
Expand All @@ -35,22 +42,23 @@ watch(selectedMetric,

<template>
<div class="flex flex-col">
<div class="flex w-full mb-4">
<div class="flex mb-4 space-x-4 items-end justify-between">
<TimelineSorting v-model="sortedGtList" :selectedMetric="selectedMetricValue"/>
<Dropdown
v-model="selectedMetric"
:options="metrics"
:pt="DropdownPassThroughStyles"
optionLabel="label"
placeholder="Select a metric"
class="ml-auto md:w-14rem"
class="grow-0"
unstyled
/>
</div>
<TrendLegend class="ml-auto mb-4"/>
<TimelineFilters></TimelineFilters>
<div class="flex flex-col space-y-6">
<template v-if="gtList.length > 0">
<TimelineItem v-for="gt in gtList" :key="gt.id" :gt="gt" :metric="selectedMetricValue" />
<template v-if="sortedGtList.length > 0">
<TimelineItem v-for="gt in sortedGtList" :key="gt.id" :gt="gt" :metric="selectedMetricValue" />
</template>
<template v-else-if="workflowsStore.gt.length > 0 ">
<div class="my-6">{{ $t('no_documents_selected') }}</div>
Expand Down
55 changes: 55 additions & 0 deletions src/components/workflows/timeline/TimelineSorting.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<script setup lang="ts">
import type { DropdownOption, EvaluationResultsDocumentWide, GroundTruth } from "@/types"
import { computed, ref, watch } from "vue"
import Dropdown from "primevue/dropdown"
import { GTTimelineSortingOptions, sortByOption } from "@/helpers/sorting"
import { useI18n } from "vue-i18n"
import { DropdownPassThroughStyles } from "@/helpers/pt"
const { t } = useI18n()
const props = defineProps<{
modelValue: GroundTruth[],
selectedMetric: keyof EvaluationResultsDocumentWide
}>()
const emit = defineEmits<{
(event: 'update:modelValue', payload: GroundTruth[]): void
}>()
const sortOptions = computed<DropdownOption[]>(() =>
Object.keys(GTTimelineSortingOptions).map(key =>
({ value: GTTimelineSortingOptions[key as keyof typeof GTTimelineSortingOptions],
label: t(GTTimelineSortingOptions[key as keyof typeof GTTimelineSortingOptions])
})
)
)
const selectedSortOption = ref<DropdownOption>(sortOptions.value[0])
watch(() => props.modelValue, () => {
updateSortedList(selectedSortOption.value)
})
watch(() => props.selectedMetric, () => {
updateSortedList(selectedSortOption.value)
})
function updateSortedList(event: any) {
const sortedGtList = sortByOption(props.modelValue, event.value, props.selectedMetric)
emit('update:modelValue', sortedGtList)
}
</script>
<template>
<div>
<p class="font-semibold mb-2">Sort by:</p>
<Dropdown
v-model="selectedSortOption"
@update:model-value="updateSortedList($event)"
:options="sortOptions"
:pt="DropdownPassThroughStyles"
option-label="label"
unstyled
/>
</div>
</template>
64 changes: 64 additions & 0 deletions src/helpers/sorting.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import workflowsStore from "@/store/workflows-store"
import type { EvaluationResultsDocumentWide, EvaluationRun, GroundTruth, TimeSpan } from "@/types"

const GTTimelineSortingOptions = {
LABEL_ASC: 'label_asc',
LABEL_DESC: 'label_desc',
METRIC_DESC: 'metric_desc',
METRIC_ASC: 'metric_asc',
YEAR_ASC: 'year_asc',
YEAR_DESC: 'year_desc'
}

function sortByOption(gtList: GroundTruth[], sortingOption: string, metric: keyof EvaluationResultsDocumentWide): GroundTruth[] {
if (sortingOption === GTTimelineSortingOptions.METRIC_DESC) return sortByMetric(gtList, true, metric)
if (sortingOption === GTTimelineSortingOptions.METRIC_ASC) return sortByMetric(gtList, false, metric)
if (sortingOption === GTTimelineSortingOptions.LABEL_DESC) return sortByLabel(gtList, true)
if (sortingOption === GTTimelineSortingOptions.LABEL_ASC) return sortByLabel(gtList, false)
if (sortingOption === GTTimelineSortingOptions.YEAR_DESC) return sortByYear(gtList, true)
if (sortingOption === GTTimelineSortingOptions.YEAR_ASC) return sortByYear(gtList, false)
return gtList
}

function sortByMetric(gtList: GroundTruth[], desc: boolean, metric: keyof EvaluationResultsDocumentWide): GroundTruth[] {
return gtList.sort((left, right) => {
const compareMetric = (left: GroundTruth, right: GroundTruth) => {
const leftRuns = workflowsStore.getRuns(left.id) //assume getLatestRuns(id) TODO -> change to latestRuns
const rightRuns = workflowsStore.getRuns(right.id) //same here

const getAverageValue = (runs: EvaluationRun[]) => {
if (runs.length === 0) return 0
return runs.reduce((acc, curr) => {
const value = <number | null>curr.evaluation_results.document_wide[metric]
return acc += value ?? 0
}, 0) / runs.length
}

return getAverageValue(leftRuns) - getAverageValue(rightRuns)
}
return desc ? compareMetric(right, left) : compareMetric(left, right)
})
}

function sortByLabel(gtList: GroundTruth[], desc: boolean): GroundTruth[] {
return gtList.sort((left, right) => {
const leftLabel = left.label.toLocaleLowerCase()
const rightLabel = right.label.toLocaleLowerCase()
return desc ? rightLabel.localeCompare(leftLabel) : leftLabel.localeCompare(rightLabel)
})
}

function sortByYear(gtList: GroundTruth[], desc: boolean): GroundTruth[] {
return gtList.sort((left, right) => {
const compareTimeSpan = (leftTime: TimeSpan, rightTime: TimeSpan) => {
return (leftTime.notBefore > rightTime.notBefore) ? 1 : ((rightTime.notBefore > leftTime.notBefore) ? -1 : 0)
}
return desc ? compareTimeSpan(right.metadata.time, left.metadata.time) : compareTimeSpan(left.metadata.time, right.metadata.time)
})
}



export {
GTTimelineSortingOptions, sortByOption
}
8 changes: 7 additions & 1 deletion src/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,5 +86,11 @@
"filter_by_processor": "Nach Prozessor filtern",
"select_a_date_range": "Zeitraum auswählen",
"select_a_workflow": "Workflow auswählen",
"select_a_processor": "Prozessor auswählen"
"select_a_processor": "Prozessor auswählen",
"label_asc": "Titel (a - z)",
"label_desc": "Titel (z - a)",
"metric_desc": "Ausgewählte Metrik (absteigend)",
"metric_asc": "Ausgewählte Metrik (aufsteigend)",
"year_asc": "Zeitraum (ältester - neuster)",
"year_desc": "Zeitraum (neuster - ältester)"
}
8 changes: 7 additions & 1 deletion src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,5 +80,11 @@
"filter_by_processor": "Filter by processor",
"select_a_date_range": "Select a date range",
"select_a_workflow": "Select a workflow",
"select_a_processor": "Select a processor"
"select_a_processor": "Select a processor",
"label_asc": "Label (a - z)",
"label_desc": "Label (z - a)",
"metric_desc": "Selected metric (descending)",
"metric_asc": "Selected metric (ascending)",
"year_asc": "Time period (oldest - latest)",
"year_desc": "Time period (latest - oldest)"
}
10 changes: 6 additions & 4 deletions src/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,7 @@ export interface GroundTruthMetadata {
reference: string,
link: string
}[],
time: {
notBefore: string,
notAfter: string
},
time: TimeSpan
title: string,
'transcription-guidelines': string,
url: string,
Expand All @@ -54,6 +51,11 @@ export interface GroundTruthMetadata {
}[],
}

export interface TimeSpan {
notBefore: string,
notAfter: string
}

export interface Workflow {
id: string,
label: string,
Expand Down

0 comments on commit b6dd235

Please sign in to comment.