|
|
@ -1,62 +1,48 @@ |
|
|
|
<template> |
|
|
|
<layout-text v-if="image.id"> |
|
|
|
<layout-text v-if="example.id"> |
|
|
|
<template #header> |
|
|
|
<toolbar-laptop |
|
|
|
:doc-id="image.id" |
|
|
|
:doc-id="example.id" |
|
|
|
:enable-auto-labeling.sync="enableAutoLabeling" |
|
|
|
:guideline-text="project.guideline" |
|
|
|
:is-reviewd="image.isConfirmed" |
|
|
|
:total="images.count" |
|
|
|
:is-reviewd="example.isConfirmed" |
|
|
|
:total="totalExample" |
|
|
|
class="d-none d-sm-block" |
|
|
|
@click:clear-label="clear(image.id)" |
|
|
|
@click:review="confirm" |
|
|
|
> |
|
|
|
<v-btn-toggle v-model="labelOption" mandatory class="ms-2"> |
|
|
|
<v-btn icon> |
|
|
|
<v-icon>{{ mdiFormatListBulleted }}</v-icon> |
|
|
|
</v-btn> |
|
|
|
<v-btn icon> |
|
|
|
<v-icon>{{ mdiText }}</v-icon> |
|
|
|
</v-btn> |
|
|
|
</v-btn-toggle> |
|
|
|
</toolbar-laptop> |
|
|
|
<toolbar-mobile :total="images.count" class="d-flex d-sm-none" /> |
|
|
|
@click:clear-label="clear(example.id)" |
|
|
|
@click:review="confirm(projectId)" |
|
|
|
/> |
|
|
|
<toolbar-mobile :total="totalExample" class="d-flex d-sm-none" /> |
|
|
|
</template> |
|
|
|
<template #content> |
|
|
|
<v-snackbar |
|
|
|
:value="!!error" |
|
|
|
color="error" |
|
|
|
timeout="2000" |
|
|
|
> |
|
|
|
<v-snackbar :value="!!error" color="error" timeout="2000"> |
|
|
|
{{ error }} |
|
|
|
</v-snackbar> |
|
|
|
<v-card> |
|
|
|
<v-img contain :src="image.url" :max-height="imageSize.height" class="grey lighten-2" /> |
|
|
|
<v-img contain :src="example.url" :max-height="imageSize.height" class="grey lighten-2" /> |
|
|
|
<seq2seq-box |
|
|
|
:annotations="labels" |
|
|
|
@delete:annotation="(labelId) => remove(image.id, labelId)" |
|
|
|
@update:annotation="(labelId, text) => update(image.id, labelId, text)" |
|
|
|
@create:annotation="(text) => add(image.id, text)" |
|
|
|
@delete:annotation="(labelId) => remove(example.id, labelId)" |
|
|
|
@update:annotation="(labelId, text) => update(example.id, labelId, text)" |
|
|
|
@create:annotation="(text) => add(example.id, text)" |
|
|
|
/> |
|
|
|
</v-card> |
|
|
|
</template> |
|
|
|
<template #sidebar> |
|
|
|
<annotation-progress :progress="progress" /> |
|
|
|
<list-metadata :metadata="image.meta" class="mt-4" /> |
|
|
|
<list-metadata :metadata="example.meta" class="mt-4" /> |
|
|
|
</template> |
|
|
|
</layout-text> |
|
|
|
</template> |
|
|
|
|
|
|
|
<script> |
|
|
|
import { mdiFormatListBulleted, mdiText } from '@mdi/js' |
|
|
|
import { toRefs, useContext } from '@nuxtjs/composition-api' |
|
|
|
import _ from 'lodash' |
|
|
|
import { reactive, ref, toRefs, useContext, useFetch, watch } from '@nuxtjs/composition-api' |
|
|
|
import LayoutText from '@/components/tasks/layout/LayoutText' |
|
|
|
import ListMetadata from '@/components/tasks/metadata/ListMetadata' |
|
|
|
import AnnotationProgress from '@/components/tasks/sidebar/AnnotationProgress.vue' |
|
|
|
import ToolbarLaptop from '@/components/tasks/toolbar/ToolbarLaptop' |
|
|
|
import ToolbarMobile from '@/components/tasks/toolbar/ToolbarMobile' |
|
|
|
import Seq2seqBox from '~/components/tasks/seq2seq/Seq2seqBox' |
|
|
|
import { useExampleItem } from '~/composables/useExampleItem' |
|
|
|
import { useTextLabel } from '~/composables/useTextLabel' |
|
|
|
|
|
|
|
export default { |
|
|
@ -68,7 +54,7 @@ export default { |
|
|
|
ToolbarLaptop, |
|
|
|
ToolbarMobile |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
layout: 'workspace', |
|
|
|
|
|
|
|
validate({ params, query }) { |
|
|
@ -76,54 +62,69 @@ export default { |
|
|
|
}, |
|
|
|
|
|
|
|
setup() { |
|
|
|
const { app, params } = useContext() |
|
|
|
const { state, error, autoLabel, list, clear, remove, add, update } = useTextLabel( |
|
|
|
const { app, params, query } = useContext() |
|
|
|
const projectId = params.value.id |
|
|
|
const { state, autoLabel, list, clear, remove, add, update } = useTextLabel( |
|
|
|
app.$repositories.textLabel, |
|
|
|
params.value.id |
|
|
|
projectId |
|
|
|
) |
|
|
|
const { state: exampleState, confirm, getExample, updateProgress } = useExampleItem() |
|
|
|
const enableAutoLabeling = ref(false) |
|
|
|
const imageSize = reactive({ |
|
|
|
height: 0, |
|
|
|
width: 0 |
|
|
|
}) |
|
|
|
|
|
|
|
updateProgress(projectId) |
|
|
|
|
|
|
|
const setImageSize = (val) => { |
|
|
|
const img = new Image() |
|
|
|
img.onload = function () { |
|
|
|
imageSize.height = this.height |
|
|
|
imageSize.width = this.width |
|
|
|
} |
|
|
|
img.src = val.url |
|
|
|
} |
|
|
|
|
|
|
|
const { fetch } = useFetch(async () => { |
|
|
|
await getExample(projectId, query.value) |
|
|
|
setImageSize(exampleState.example) |
|
|
|
if (enableAutoLabeling.value) { |
|
|
|
try { |
|
|
|
await autoLabel(projectId, exampleState.example.id) |
|
|
|
} catch (e) { |
|
|
|
enableAutoLabeling.value = false |
|
|
|
} |
|
|
|
} else { |
|
|
|
await list(exampleState.example.id) |
|
|
|
} |
|
|
|
}) |
|
|
|
watch(query, fetch) |
|
|
|
watch(enableAutoLabeling, async (val) => { |
|
|
|
if (val && !exampleState.example.isConfirmed) { |
|
|
|
await autoLabel(exampleState.example.id) |
|
|
|
} |
|
|
|
}) |
|
|
|
|
|
|
|
return { |
|
|
|
...toRefs(state), |
|
|
|
error, |
|
|
|
...toRefs(exampleState), |
|
|
|
add, |
|
|
|
autoLabel, |
|
|
|
list, |
|
|
|
clear, |
|
|
|
remove, |
|
|
|
update |
|
|
|
update, |
|
|
|
confirm, |
|
|
|
getExample, |
|
|
|
enableAutoLabeling, |
|
|
|
imageSize |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
data() { |
|
|
|
return { |
|
|
|
images: [], |
|
|
|
project: {}, |
|
|
|
enableAutoLabeling: false, |
|
|
|
labelOption: 0, |
|
|
|
imageSize: { |
|
|
|
height: 0, |
|
|
|
width: 0 |
|
|
|
}, |
|
|
|
mdiText, |
|
|
|
mdiFormatListBulleted, |
|
|
|
progress: {} |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
async fetch() { |
|
|
|
this.images = await this.$services.example.fetchOne( |
|
|
|
this.projectId, |
|
|
|
this.$route.query.page, |
|
|
|
this.$route.query.q, |
|
|
|
this.$route.query.isChecked, |
|
|
|
this.$route.query.ordering |
|
|
|
) |
|
|
|
const image = this.images.items[0] |
|
|
|
this.setImageSize(image) |
|
|
|
if (this.enableAutoLabeling) { |
|
|
|
await this.autoLabel(image.id) |
|
|
|
} else { |
|
|
|
await this.list(image.id) |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
@ -131,55 +132,11 @@ export default { |
|
|
|
projectId() { |
|
|
|
return this.$route.params.id |
|
|
|
}, |
|
|
|
image() { |
|
|
|
if (_.isEmpty(this.images) || this.images.items.length === 0) { |
|
|
|
return {} |
|
|
|
} else { |
|
|
|
return this.images.items[0] |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
watch: { |
|
|
|
'$route.query': '$fetch', |
|
|
|
async enableAutoLabeling(val) { |
|
|
|
if (val && !this.image.isConfirmed) { |
|
|
|
await this.autoLabel(this.image.id) |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
async created() { |
|
|
|
this.project = await this.$services.project.findById(this.projectId) |
|
|
|
this.progress = await this.$repositories.metrics.fetchMyProgress(this.projectId) |
|
|
|
}, |
|
|
|
|
|
|
|
methods: { |
|
|
|
async updateProgress() { |
|
|
|
this.progress = await this.$repositories.metrics.fetchMyProgress(this.projectId) |
|
|
|
}, |
|
|
|
|
|
|
|
async confirm() { |
|
|
|
await this.$services.example.confirm(this.projectId, this.image.id) |
|
|
|
await this.$fetch() |
|
|
|
this.updateProgress() |
|
|
|
}, |
|
|
|
|
|
|
|
setImageSize(val) { |
|
|
|
const img = new Image() |
|
|
|
const self = this |
|
|
|
img.onload = function () { |
|
|
|
self.imageSize.height = this.height |
|
|
|
self.imageSize.width = this.width |
|
|
|
} |
|
|
|
img.src = val.url |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
</script> |
|
|
|
|
|
|
|
<style scoped> |
|
|
|
.text-pre-wrap { |
|
|
|
white-space: pre-wrap !important; |
|
|
|
} |
|
|
|
</style> |