Browse Source

Add LabelingMenu.vue

pull/1703/head
Hironsan 3 years ago
parent
commit
da463914d2
2 changed files with 144 additions and 72 deletions
  1. 94
      frontend/components/tasks/sequenceLabeling/EntityEditor.vue
  2. 122
      frontend/components/tasks/sequenceLabeling/LabelingMenu.vue

94
frontend/components/tasks/sequenceLabeling/EntityEditor.vue

@ -11,75 +11,33 @@
:allow-overlapping="allowOverlapping"
:grapheme-mode="graphemeMode"
@add:entity="handleAddEvent"
@click:entity="handleEntityClickEvent"
@click:entity="onEntityClicked"
@click:relation="updateRelation"
@contextmenu:entity="deleteEntity"
@contextmenu:relation="deleteRelation"
/>
<v-menu
v-model="showMenu"
:position-x="x"
:position-y="y"
absolute
offset-y
@input="cleanUp"
>
<v-list
dense
min-width="150"
max-height="400"
class="overflow-y-auto"
>
<v-list-item>
<v-autocomplete
ref="autocomplete"
:value="currentLabel"
:items="entityLabels"
autofocus
dense
deletable-chips
hide-details
item-text="text"
item-value="id"
label="Label List"
small-chips
@input="addOrUpdateEntity"
/>
</v-list-item>
<v-list-item
v-for="(label, i) in entityLabels"
:key="i"
@click="addOrUpdateEntity(label.id)"
>
<v-list-item-action
v-if="hasAnySuffixKey"
>
<v-chip
v-if="label.suffixKey"
:color="label.backgroundColor"
outlined
small
v-text="label.suffixKey"
/>
<span v-else class="mr-8" />
</v-list-item-action>
<v-list-item-content>
<v-list-item-title v-text="label.text"/>
</v-list-item-content>
</v-list-item>
</v-list>
</v-menu>
<labeling-menu
:opened="entityMenuOpened"
:x="x"
:y="y"
:selected-label="currentLabel"
:labels="entityLabels"
@close="cleanUp"
@click:label="addOrUpdateEntity"
/>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
import VAnnotator from 'v-annotator'
import LabelingMenu from './LabelingMenu.vue'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
export default Vue.extend({
components: {
VAnnotator,
LabelingMenu,
},
props: {
@ -136,7 +94,8 @@ export default Vue.extend({
data() {
return {
showMenu: false,
entityMenuOpened: false,
relationMenuOpened: false,
x: 0,
y: 0,
startOffset: 0,
@ -148,10 +107,6 @@ export default Vue.extend({
},
computed: {
hasAnySuffixKey(): boolean {
return this.entityLabels.some((label: any) => label.suffixKey !== null)
},
currentLabel(): any {
if (this.entity) {
const label = this.entityLabels.find((label: any) => label.id === this.entity!.label)
@ -172,7 +127,7 @@ export default Vue.extend({
this.entity = this.entities.find((entity: any) => entity.id === entityId)
},
setEntityForRelation(entityId: number) {
setEntityForRelation(e: any, entityId: number) {
const entity = this.entities.find((entity: any) => entity.id === entityId)
if (!this.fromEntity) {
this.fromEntity = entity
@ -180,17 +135,19 @@ export default Vue.extend({
this.toEntity = entity
if (this.selectedLabel) {
this.addRelation()
} else {
// this.showEntityLabelMenu(e)
}
}
},
showEntityLabelMenu(e: any) {
e.preventDefault()
this.showMenu = false
this.entityMenuOpened = false
this.x = e.clientX || e.changedTouches[0].clientX
this.y = e.clientY || e.changedTouches[0].clientY
this.$nextTick(() => {
this.showMenu = true
this.entityMenuOpened = true
})
},
@ -203,9 +160,9 @@ export default Vue.extend({
}
},
handleEntityClickEvent(e: any, entityId: number) {
onEntityClicked(e: any, entityId: number) {
if (this.relationMode) {
this.setEntityForRelation(entityId)
this.setEntityForRelation(e, entityId)
} else {
this.setEntity(entityId)
this.showEntityLabelMenu(e)
@ -239,17 +196,10 @@ export default Vue.extend({
},
cleanUp() {
this.showMenu = false
this.entityMenuOpened = false
this.entity = null
this.startOffset = 0
this.endOffset = 0
// Todo: a bit hacky. I want to fix this problem.
// https://github.com/vuetifyjs/vuetify/issues/10765
this.$nextTick(() => {
if (this.$refs.autocomplete) {
(this.$refs.autocomplete as any).selectedItems = []
}
})
},
addRelation() {

122
frontend/components/tasks/sequenceLabeling/LabelingMenu.vue

@ -0,0 +1,122 @@
<template>
<v-menu
:value="opened"
:position-x="x"
:position-y="y"
absolute
offset-y
@input="close"
>
<v-list
dense
min-width="150"
max-height="400"
class="overflow-y-auto"
>
<v-list-item>
<v-autocomplete
ref="autocomplete"
:value="selectedLabel"
:items="labels"
autofocus
dense
deletable-chips
hide-details
item-text="text"
item-value="id"
label="Select a label"
small-chips
@input="onLabelSelected"
/>
</v-list-item>
<v-list-item
v-for="(label, i) in labels"
:key="i"
@click="onLabelSelected(label.id)"
>
<v-list-item-action
v-if="hasAnySuffixKey"
>
<v-chip
v-if="label.suffixKey"
:color="label.backgroundColor"
outlined
small
v-text="label.suffixKey"
/>
<span v-else class="mr-8" />
</v-list-item-action>
<v-list-item-content>
<v-list-item-title v-text="label.text"/>
</v-list-item-content>
</v-list-item>
</v-list>
</v-menu>
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
props: {
labels: {
type: Array,
default: () => [],
required: true,
},
opened: {
type: Boolean,
default: false,
required: true,
},
selectedLabel: {
type: Object,
default: null,
required: false,
},
x: {
type: Number,
default: 0,
required: true,
},
y: {
type: Number,
default: 0,
required: true,
}
},
data() {
return {
startOffset: 0,
endOffset: 0,
entity: null as any,
fromEntity: null as any,
toEntity: null as any,
};
},
computed: {
hasAnySuffixKey(): boolean {
return this.labels.some((label: any) => label.suffixKey !== null)
}
},
methods: {
close() {
// Todo: a bit hacky. I want to fix this problem.
// https://github.com/vuetifyjs/vuetify/issues/10765
this.$nextTick(() => {
if (this.$refs.autocomplete) {
(this.$refs.autocomplete as any).selectedItems = []
}
})
this.$emit('close')
},
onLabelSelected(labelId: number) {
this.$emit('click:label', labelId)
this.close()
}
}
})
</script>
Loading…
Cancel
Save