From 4c228f3207c3cd130ff744ecbb99ed96b35d300d Mon Sep 17 00:00:00 2001 From: jfrer Date: Fri, 14 Jun 2024 14:55:15 +0200 Subject: [PATCH 1/8] fix: use api for latest runs instead of local filtering --- src/components/Workflows.vue | 6 ++++++ src/helpers/api.ts | 2 +- src/store/workflows-store.ts | 9 +++------ 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/components/Workflows.vue b/src/components/Workflows.vue index 9ad66e6..773a57c 100644 --- a/src/components/Workflows.vue +++ b/src/components/Workflows.vue @@ -50,6 +50,7 @@ } workflowsStore.runs = await api.getRuns() + workflowsStore.latestRuns = await api.getLatestRuns() workflowsStore.gt = await api.getGroundTruth() workflowsStore.workflows = await api.getWorkflows() @@ -58,6 +59,11 @@ if (!workflowsStore.gt.find(gt => gt.id === gtId)) console.log(gtId) }) + workflowsStore.latestRuns.forEach(run => { + const gtId = mapGtId(run.metadata.gt_workspace.id) + + if (!workflowsStore.gt.find(gt => gt.id === gtId)) console.log(gtId) + }) const releasesObj = workflowsStore.runs.reduce((acc, cur) => { acc[cur.metadata.release_info.tag_name] = cur.metadata.release_info diff --git a/src/helpers/api.ts b/src/helpers/api.ts index 98dc337..6e09a71 100644 --- a/src/helpers/api.ts +++ b/src/helpers/api.ts @@ -39,7 +39,7 @@ async function getLatestRuns(gtId?: string, workflowId?: string): Promise EvaluationRun[] getLatestRuns: () => EvaluationRun[], @@ -19,6 +20,7 @@ export default reactive<{ gt: [], workflows: [], runs: [], + latestRuns: [], releases: [], getRuns(gtId: string, workflowId?: string) { return this.runs @@ -32,12 +34,7 @@ export default reactive<{ ) }, getLatestRuns() { - const dates = Object.keys(this.runs.reduce((acc, cur) => { - acc[normalizeDate(cur.metadata.timestamp)] = null - return acc - }, <{ [key: string]: null}>{})) - - return this.runs.filter(({ metadata }) => normalizeDate(metadata.timestamp) === dates[dates.length - 1]) + return this.latestRuns }, getGtById(id: string): GroundTruth | null { return this.gt.find((item) => item.id === id) ?? null From 6d904fd6dcc7ac15218cdd250fc980d8adbd3851 Mon Sep 17 00:00:00 2001 From: jfrer Date: Fri, 5 Jul 2024 15:07:04 +0200 Subject: [PATCH 2/8] refactor: use explicit types --- src/components/workflows/WorkflowsTable.vue | 22 ++++++++++---------- src/helpers/api.ts | 4 ++-- src/types/index.d.ts | 23 +++++++++++++++++++++ 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/components/workflows/WorkflowsTable.vue b/src/components/workflows/WorkflowsTable.vue index f42c6f2..964c0a3 100644 --- a/src/components/workflows/WorkflowsTable.vue +++ b/src/components/workflows/WorkflowsTable.vue @@ -2,7 +2,7 @@ import { watch, ref, onMounted, computed } from "vue" import { useI18n } from "vue-i18n" import { createReadableMetricValue, getEvalColor, mapGtId } from "@/helpers/utils" -import type { EvaluationRun } from "@/types" +import type { EvalDefinitions, EvaluationResultsDocumentWide, EvaluationRun, GroupedTableData } from "@/types" import Dropdown from 'primevue/dropdown' import workflowsStore from "@/store/workflows-store" import api from "@/helpers/api" @@ -11,8 +11,8 @@ import TrendLegend from "@/components/workflows/TrendLegend.vue" const { t } = useI18n() -const groupedData = ref({}) -const evals = ref([]) +const groupedData = ref({}) +const evals = ref([]) const sortOptions = ref([{ value: 'documents', @@ -25,7 +25,7 @@ const sortOptions = ref([{ const sortBy = ref(sortOptions.value[0]) const latestRuns = ref([]) const filteredRuns = ref([]) -const evalDefinitions = ref([]) +const evalDefinitions = ref({}) const loading = ref(false) onMounted(async () => { @@ -66,7 +66,7 @@ const groupByWorkflows = () => { label: workflowsStore.getGtById(mapGtId(cur.metadata.gt_workspace.id))?.label, evaluations: Object.keys(cur.evaluation_results.document_wide).map(key => ({ name: key, - value: cur.evaluation_results.document_wide[key] + value: cur.evaluation_results.document_wide[key as keyof EvaluationResultsDocumentWide] })) } if (!acc[ocrWorkflowId]) { @@ -77,12 +77,12 @@ const groupByWorkflows = () => { } else { acc[ocrWorkflowId].subjects.push(subject) acc[ocrWorkflowId].subjects.sort((a, b) => { - if (a.label > b.label) return 1 + if ((a.label && b.label) && a.label > b.label) return 1 else return -1 }) } return acc - }, {}) + }, {} as GroupedTableData) } const groupByDocuments = () => { @@ -94,7 +94,7 @@ const groupByDocuments = () => { label: workflowsStore.getWorkflowById(mapGtId(cur.metadata.ocr_workflow['id']))?.label, evaluations: Object.keys(cur.evaluation_results.document_wide).map(key => ({ name: key, - value: cur.evaluation_results.document_wide[key] + value: cur.evaluation_results.document_wide[key as keyof EvaluationResultsDocumentWide] })) } if (!acc[gtWorkspaceId]) { @@ -105,12 +105,12 @@ const groupByDocuments = () => { } else { acc[gtWorkspaceId].subjects.push(subject) acc[gtWorkspaceId].subjects.sort((a, b) => { - if (a.label > b.label) return 1 + if ((a.label && b.label) && a.label > b.label) return 1 else return -1 }) } return acc - }, {}) + }, {} as GroupedTableData) } @@ -161,7 +161,7 @@ const groupByDocuments = () => { - {{ createReadableMetricValue(name, value) }} + {{ createReadableMetricValue(name as keyof EvaluationResultsDocumentWide, value) }} diff --git a/src/helpers/api.ts b/src/helpers/api.ts index 98dc337..912ab10 100644 --- a/src/helpers/api.ts +++ b/src/helpers/api.ts @@ -1,4 +1,4 @@ -import type { EvaluationRun, GroundTruth, Workflow } from "@/types" +import type { EvalDefinition, EvaluationRun, GroundTruth, Workflow } from "@/types" const baseUrlOld = 'https://raw.githubusercontent.com/OCR-D/quiver-back-end/main/data' const baseUrl = 'https://quiver-dev.sub.uni-goettingen.de/api' @@ -10,7 +10,7 @@ async function getOcrdAllReleases() { return await request(baseUrlOld + '/ocrd_all_releases.json') } -async function getEvalDefinitions() { +async function getEvalDefinitions(): Promise { return await request(baseUrlOld + '/metrics_definitions.json') } diff --git a/src/types/index.d.ts b/src/types/index.d.ts index 2776794..79561ae 100644 --- a/src/types/index.d.ts +++ b/src/types/index.d.ts @@ -141,3 +141,26 @@ export interface ReleaseInfo { html_url: string } +export interface EvalDefinition { + label: string, + short_descr: string, + url: string +} + +export interface EvalDefinitions { + [id: string]: EvalDefinition +} + +export interface GroupedTableData { + [gtWorkId: string]: { + label: string | undefined, + subjects: { + label: string | undefined + evaluations: { + name: string + value: number | number[] | null + }[] + }[] + } +} + From 6cd3d17aa25911770c6748a3c79cc93b33e6d141 Mon Sep 17 00:00:00 2001 From: jfrer Date: Fri, 5 Jul 2024 16:08:28 +0200 Subject: [PATCH 3/8] docs: add comment explaining the workaround --- src/helpers/api.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/helpers/api.ts b/src/helpers/api.ts index 6e09a71..dccf74c 100644 --- a/src/helpers/api.ts +++ b/src/helpers/api.ts @@ -38,7 +38,13 @@ async function getLatestRuns(gtId?: string, workflowId?: string): Promise Date: Tue, 9 Jul 2024 13:51:27 +0200 Subject: [PATCH 4/8] wip --- src/components/workflows/WorkflowsTable.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/workflows/WorkflowsTable.vue b/src/components/workflows/WorkflowsTable.vue index 964c0a3..17e864b 100644 --- a/src/components/workflows/WorkflowsTable.vue +++ b/src/components/workflows/WorkflowsTable.vue @@ -44,6 +44,7 @@ watch(() => filtersStore.gt, () => { watch(sortBy, () => { groupRuns(sortBy.value.value) + console.log(groupedData.value) //TODO: remove, continue here }) function setFilteredRuns() { From 38dbe0c2eb67457193cb2e5deed18d187432f1f4 Mon Sep 17 00:00:00 2001 From: jfrer Date: Tue, 9 Jul 2024 16:09:40 +0200 Subject: [PATCH 5/8] wip --- src/components/workflows/WorkflowsTable.vue | 1 - src/helpers/api.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/workflows/WorkflowsTable.vue b/src/components/workflows/WorkflowsTable.vue index 17e864b..964c0a3 100644 --- a/src/components/workflows/WorkflowsTable.vue +++ b/src/components/workflows/WorkflowsTable.vue @@ -44,7 +44,6 @@ watch(() => filtersStore.gt, () => { watch(sortBy, () => { groupRuns(sortBy.value.value) - console.log(groupedData.value) //TODO: remove, continue here }) function setFilteredRuns() { diff --git a/src/helpers/api.ts b/src/helpers/api.ts index 912ab10..a641f6b 100644 --- a/src/helpers/api.ts +++ b/src/helpers/api.ts @@ -10,7 +10,7 @@ async function getOcrdAllReleases() { return await request(baseUrlOld + '/ocrd_all_releases.json') } -async function getEvalDefinitions(): Promise { +async function getEvalDefinitions(): Promise { return await request(baseUrlOld + '/metrics_definitions.json') } From fa5db7ede2b79232682a0d161b16659e46699fcf Mon Sep 17 00:00:00 2001 From: jfrer Date: Fri, 12 Jul 2024 11:29:19 +0200 Subject: [PATCH 6/8] wip --- src/components/workflows/WorkflowsTable.vue | 6 ++- .../timeline/WorkflowTableSorter.vue | 51 +++++++++++++++++++ src/helpers/api.ts | 4 +- src/types/index.d.ts | 12 ++--- 4 files changed, 63 insertions(+), 10 deletions(-) create mode 100644 src/components/workflows/timeline/WorkflowTableSorter.vue diff --git a/src/components/workflows/WorkflowsTable.vue b/src/components/workflows/WorkflowsTable.vue index 964c0a3..cac7e75 100644 --- a/src/components/workflows/WorkflowsTable.vue +++ b/src/components/workflows/WorkflowsTable.vue @@ -8,6 +8,7 @@ import workflowsStore from "@/store/workflows-store" import api from "@/helpers/api" import filtersStore from "@/store/filters-store" import TrendLegend from "@/components/workflows/TrendLegend.vue" +import WorkflowsTableSorter from "@/components/workflows/timeline/WorkflowTableSorter.vue" const { t } = useI18n() @@ -53,6 +54,7 @@ function setFilteredRuns() { function groupRuns(groupBy: string) { if (groupBy === 'workflows') groupByWorkflows() else if (groupBy === 'documents') groupByDocuments() + console.log(groupedData.value) } const groupByWorkflows = () => { @@ -133,7 +135,9 @@ const groupByDocuments = () => { {{ sortBy.value === 'documents' ? $t('workflows') : $t('documents') }} - {{ evalDefinitions[evalKey] ? evalDefinitions[evalKey].label : evalKey }} + + {{ evalDefinitions[evalKey] ? evalDefinitions[evalKey].label : evalKey }} +
diff --git a/src/components/workflows/timeline/WorkflowTableSorter.vue b/src/components/workflows/timeline/WorkflowTableSorter.vue new file mode 100644 index 0000000..7fe2b40 --- /dev/null +++ b/src/components/workflows/timeline/WorkflowTableSorter.vue @@ -0,0 +1,51 @@ + + \ No newline at end of file diff --git a/src/helpers/api.ts b/src/helpers/api.ts index c7be0e8..f44b999 100644 --- a/src/helpers/api.ts +++ b/src/helpers/api.ts @@ -1,4 +1,4 @@ -import type { EvalDefinition, EvaluationRun, GroundTruth, Workflow } from "@/types" +import type { EvalDefinitions, EvaluationRun, GroundTruth, Workflow } from "@/types" const baseUrlOld = 'https://raw.githubusercontent.com/OCR-D/quiver-back-end/main/data' const baseUrl = 'https://quiver-dev.sub.uni-goettingen.de/api' @@ -10,7 +10,7 @@ async function getOcrdAllReleases() { return await request(baseUrlOld + '/ocrd_all_releases.json') } -async function getEvalDefinitions(): Promise { +async function getEvalDefinitions(): Promise { return await request(baseUrlOld + '/metrics_definitions.json') } diff --git a/src/types/index.d.ts b/src/types/index.d.ts index 79561ae..5f7b4ff 100644 --- a/src/types/index.d.ts +++ b/src/types/index.d.ts @@ -141,14 +141,12 @@ export interface ReleaseInfo { html_url: string } -export interface EvalDefinition { - label: string, - short_descr: string, - url: string -} - export interface EvalDefinitions { - [id: string]: EvalDefinition + [id: string]: { + label: string, + short_descr: string, + url: string + } } export interface GroupedTableData { From 8a5f60128bcf662d39fa80aa0bf3e1e59e53a94e Mon Sep 17 00:00:00 2001 From: jfrer Date: Tue, 16 Jul 2024 16:11:58 +0200 Subject: [PATCH 7/8] feat: sort table by metrics while keeping the grouping as is --- src/components/workflows/WorkflowsTable.vue | 57 +++++++++----- .../timeline/WorkflowTableSorter.vue | 76 +++++++++++++++---- src/types/index.d.ts | 16 ++-- 3 files changed, 110 insertions(+), 39 deletions(-) diff --git a/src/components/workflows/WorkflowsTable.vue b/src/components/workflows/WorkflowsTable.vue index cac7e75..2b55837 100644 --- a/src/components/workflows/WorkflowsTable.vue +++ b/src/components/workflows/WorkflowsTable.vue @@ -13,9 +13,15 @@ import WorkflowsTableSorter from "@/components/workflows/timeline/WorkflowTableS const { t } = useI18n() const groupedData = ref({}) +const sortedData = ref({}) const evals = ref([]) +const sortBy = ref(null) -const sortOptions = ref([{ +const tableData = computed(() => { + return (sortBy.value === null || Object.keys(sortedData.value).length === 0) ? groupedData.value : sortedData.value +}) + +const groupingOptions = ref([{ value: 'documents', label: t('documents') }, { @@ -23,7 +29,7 @@ const sortOptions = ref([{ label: t('workflows') }]) -const sortBy = ref(sortOptions.value[0]) +const groupBy = ref(groupingOptions.value[0]) const latestRuns = ref([]) const filteredRuns = ref([]) const evalDefinitions = ref({}) @@ -34,17 +40,17 @@ onMounted(async () => { latestRuns.value = workflowsStore.getLatestRuns() evalDefinitions.value = await api.getEvalDefinitions() setFilteredRuns() - groupRuns(sortBy.value.value) + groupRuns(groupBy.value.value) loading.value = false }) watch(() => filtersStore.gt, () => { setFilteredRuns() - groupRuns(sortBy.value.value) + groupRuns(groupBy.value.value) }) -watch(sortBy, () => { - groupRuns(sortBy.value.value) +watch(groupBy, () => { + groupRuns(groupBy.value.value) }) function setFilteredRuns() { @@ -54,7 +60,7 @@ function setFilteredRuns() { function groupRuns(groupBy: string) { if (groupBy === 'workflows') groupByWorkflows() else if (groupBy === 'documents') groupByDocuments() - console.log(groupedData.value) + sortBy.value = null } const groupByWorkflows = () => { @@ -114,6 +120,15 @@ const groupByDocuments = () => { return acc }, {} as GroupedTableData) } + +const getSortValue = (key: keyof EvaluationResultsDocumentWide) => { + return sortBy.value === key +} + +const setSorted = (event: GroupedTableData, key: keyof EvaluationResultsDocumentWide) => { + sortBy.value = key + sortedData.value = event +}