Skip to content
Snippets Groups Projects
WorkflowsList.vue 8.08 KiB
Newer Older
  • Learn to ignore specific revisions
  • paulpestov's avatar
    paulpestov committed
    <template>
    
      <div class="container">
        <div class="grid mb-4">
          <div class="flex align-items-center ml-auto">
            <p class="mr-2">{{ $t('sort_by')}}:</p>
            <Dropdown
                v-model="sortBy"
                :options="sortOptions"
                option-label="label"
                @change="onChange($event.value)"
            />
          </div>
        </div>
    
        <Card v-for="(item, i) in list" :key="i" class="mb-3 shadow-3 border-gray-200 p-4">
    
    paulpestov's avatar
    paulpestov committed
          <template #header>
    
            <div class="grid align-items-center gap-2">
              <h3 class="text-xl font-bold">{{ item.label }}</h3>
              <Tag :value="item.metadata.workflow_model" class="bg-gray-300 text-gray-700 ml-3"></Tag>
    
              <template v-if="item.metadata.document_metadata">
    
                  v-for="font in item.metadata.document_metadata.data_properties.fonts"
    
                  :key="font"
                  :value="font"
                  class="bg-gray-300 text-gray-700">
                </Tag>
    
    paulpestov's avatar
    paulpestov committed
          </template>
          <template #content>
            <div class="grid">
    
              <div class="col-7 grid">
    
                <div class="mr-3">
                  <template v-if="item.metadata.gt_workspace">
                    <Accordion class="text-sm">
                      <AccordionTab :header="item.metadata.gt_workspace.label">
                        <div class="grid">
                          <div class="col">
                            <p class="font-bold">{{ $t('number_of_pages') }}:</p>
    
                            <p>{{ item.metadata.document_metadata.data_properties.number_of_pages }}</p>
    
                            <p class="mt-2 font-bold">{{ $t('publication_year') }}:</p>
    
                            <p> {{ item.metadata.document_metadata.data_properties.publication_year }}</p>
    
                          </div>
                          <div class="col">
                            <p class="font-bold">{{ $t('layout') }}:</p>
    
                            <p>{{ item.metadata.document_metadata.data_properties.layout }}</p>
    
                          </div>
                        </div>
                      </AccordionTab>
                    </Accordion>
                  </template>
                  <template v-else>
                    <p class="font-bold text-gray-400 mt-3">{{$t('no_gt_workspace')}}</p>
                  </template>
                </div>
                <div class="flex-1">
                  <Accordion class="text-sm">
                    <AccordionTab :header="item.metadata.ocr_workflow?.label || $t('unknown_workflow')">
                      <div class="flex gap-2" v-if="item.metadata.workflow_steps">
                        <div v-for="step in item.metadata.workflow_steps" :key="step">
                          <Chip :label="step" class="text-sm" />
                        </div>
                      </div>
                      <template v-else>
                        <span class="font-bold text-gray-400">{{$t('no_ocr_workflow')}}</span>
                      </template>
                    </AccordionTab>
                  </Accordion>
                </div>
    
    paulpestov's avatar
    paulpestov committed
              <div class="col-5 py-0 ml-auto">
    
                <div class="grid mb-1">
                  <div class="col py-0 text-center" v-for="(evalKey, i) in evals" :key="i">
    
                    <span class="font-bold">{{defs[evalKey] ? defs[evalKey].label : evalKey}}</span>
    
    paulpestov's avatar
    paulpestov committed
                  </div>
                </div>
                <div class="grid">
    
                  <div v-for="({ name, value }, i) in item.evaluations" :key="i" class="col text-center">
    
    paulpestov's avatar
    paulpestov committed
                  <span
    
                      class="border-round-3xl py-1 px-3 cursor-pointer"
                      :class="getEvalColor(name, value)" :title="value">
    
                    <template v-if=" name === 'cer'">{{ shortenCER(value) }}</template>
                    <template v-else-if="name === 'cer_min_max'">{{ shortenCER(value[0]) + '/' + shortenCER(value[1])}}</template>
                    <template v-else>{{ value }}</template>
    
    paulpestov's avatar
    paulpestov committed
                  </span>
                  </div>
                </div>
              </div>
            </div>
          </template>
        </Card>
      </div>
    </template>
    
    <script setup>
    import { ref, onMounted, watch } from "vue";
    import { getEvalColor } from "@/helpers/eval-colors";
    
    import { useI18n } from "vue-i18n";
    
    paulpestov's avatar
    paulpestov committed
    
    
    const props = defineProps(['data', 'defs']);
    
    paulpestov's avatar
    paulpestov committed
    const list = ref([]);
    const evals = ref([]);
    
    const { t } = useI18n();
    
    
    const sortOptions = ref([
      {
        value: 'none',
        label: t('-')
      },
      {
        value: 'wall_time_asc',
        label: t('wall_time_asc')
      },
      {
        value: 'wall_time_desc',
        label: t('wall_time_desc')
      },
      {
        value: 'cer_asc',
        label: t('cer_asc')
      },
      {
        value: 'cer_desc',
        label: t('cer_desc')
      },
      {
        value: 'cer_min_asc',
        label: t('cer_min_asc')
      },
      {
        value: 'cer_min_desc',
        label: t('cer_min_desc')
      },
      {
        value: 'cer_max_asc',
        label: t('cer_max_asc')
      },
      {
        value: 'cer_max_desc',
        label: t('cer_max_desc')
      }
    ]);
    
    const sortBy = ref(sortOptions.value[0]);
    
    const onChange = ({ value }) => {
      if (value === 'wall_time_asc') sortByWallTime('asc');
      else if (value === 'wall_time_desc') sortByWallTime('desc');
      else if (value === 'cer_asc') sortByCER('asc');
      else if (value === 'cer_desc') sortByCER('desc');
      else if (value === 'cer_min_asc') sortByCERMin('asc');
      else if (value === 'cer_min_desc') sortByCERMin('desc');
      else if (value === 'cer_max_asc') sortByCERMax('asc');
      else if (value === 'cer_max_desc') sortByCERMax('desc');
    };
    
    const sortByWallTime = (order = 'asc') => {
      list.value.sort((a, b) => {
        const wallTimeA = a.evaluations.find(e => e.name === 'wall_time')?.value || 0;
        const wallTimeB = b.evaluations.find(e => e.name === 'wall_time')?.value || 0;
    
        if (order === 'asc') return wallTimeA > wallTimeB ? 1 : -1;
        if (order === 'desc') return wallTimeA < wallTimeB ? 1 : -1;
        return 0;
      });
    };
    
    const sortByCER = (order = 'asc') => {
      list.value.sort((a, b) => {
        const cerA = a.evaluations.find(e => e.name === 'cer')?.value || 0;
        const cerB = b.evaluations.find(e => e.name === 'cer')?.value || 0;
    
        if (order === 'asc') return cerA > cerB ? 1 : -1;
        if (order === 'desc') return cerA < cerB ? 1 : -1;
        return 0;
      });
    };
    
    const sortByCERMin = (order = 'asc') => {
      list.value.sort((a, b) => {
        const cerMinA = a.evaluations.find(e => e.name === 'cer_min_max')?.value[0] || 0;
        const cerMinB = b.evaluations.find(e => e.name === 'cer_min_max')?.value[0] || 0;
    
        if (order === 'asc') return cerMinA > cerMinB ? 1 : -1;
        if (order === 'desc') return cerMinA < cerMinB ? 1 : -1;
        return 0;
      });
    };
    
    const sortByCERMax = (order = 'asc') => {
      list.value.sort((a, b) => {
        const cerMaxA = a.evaluations.find(e => e.name === 'cer_min_max')?.value[1] || 0;
        const cerMaxB = b.evaluations.find(e => e.name === 'cer_min_max')?.value[1] || 0;
    
        if (order === 'asc') return cerMaxA > cerMaxB ? 1 : -1;
        if (order === 'desc') return cerMaxA < cerMaxB ? 1 : -1;
        return 0;
      });
    };
    
    
    const mapMetadata = ({
      workflow_model = t('no_workflow_model'),
      document_metadata = {
        fonts: []
      },
      gt_workspace = null,
      ocr_workflow = null,
      workflow_steps = null
    }) => {
    
      return {
        workflow_model,
        document_metadata,
        gt_workspace,
        ocr_workflow,
        workflow_steps
      };
    };
    
    const mapEvaluationResults = ({ document_wide = [] }) => {
      return Object.keys(document_wide).map(key => ({
        name: key,
        value: document_wide[key]
      }));
    };
    
    paulpestov's avatar
    paulpestov committed
    
    const setListData = (data) => {
    
      list.value = data.map(({ label, evaluation_results = [], metadata }) => ({
    
    paulpestov's avatar
    paulpestov committed
        label,
    
        metadata: mapMetadata(metadata),
    
        evaluations: mapEvaluationResults(evaluation_results)
    
    paulpestov's avatar
    paulpestov committed
      }));
    };
    
    const setEvals = (data) => {
    
      evals.value =
          data &&
          data.length > 0 &&
          data[0].evaluation_results
    
              ? Object.keys(data[0].evaluation_results.document_wide) || []
    
              : [];
    };
    
    const shortenCER = (value) => {
      return Math.round(value * 1000) / 1000;
    
    paulpestov's avatar
    paulpestov committed
    };
    
     onMounted(() => {
       setEvals(props.data);
       setListData(props.data);
     });
    
    
    watch(() => props.data, () => {
      setEvals(props.data);
      setListData(props.data);
    });
    
    </script>
    
    <style scoped lang="scss">
    @import 'primeflex/primeflex.scss';
    
    .p-card {
      :deep(.p-card-content) {
        padding: 0;
      }
      :deep(.p-card-body) {
    
        @include styleclass('p-0 pt-5')
    
    paulpestov's avatar
    paulpestov committed
      }
    }
    </style>