|
@@ -1,7 +1,14 @@
|
|
|
<template>
|
|
|
<div class="annotation-box"
|
|
|
:style="style"
|
|
|
- :class="{draggable: draggable}"
|
|
|
+ :class="{
|
|
|
+ draggable,
|
|
|
+ deletable,
|
|
|
+ taggable,
|
|
|
+ confirmable,
|
|
|
+ croppable,
|
|
|
+ }"
|
|
|
+ @contextmenu.prevent
|
|
|
@mousedown.prevent="click" @touchstart.prevent="click">
|
|
|
<template v-if="draggable">
|
|
|
<div class="nw" @mousedown.prevent.stop="resize('nw')" @touchstart.prevent.stop="resize('nw')"/>
|
|
@@ -23,6 +30,21 @@
|
|
|
<script>
|
|
|
export default {
|
|
|
name: "annotation-box",
|
|
|
+ data: function(){
|
|
|
+ return {
|
|
|
+ clickCounter: 0,
|
|
|
+ dblClickInterval: 200, // in ms
|
|
|
+
|
|
|
+ colors: {
|
|
|
+ default: '255, 255, 255',
|
|
|
+ pipeline: '0, 0, 255',
|
|
|
+ user: '255, 0, 0',
|
|
|
+ other_user: '136, 0, 136',
|
|
|
+ confirmed: '0, 180, 0',
|
|
|
+ other_confirmed: '180, 180, 136',
|
|
|
+ }
|
|
|
+ };
|
|
|
+ },
|
|
|
props: [
|
|
|
'box',
|
|
|
'position',
|
|
@@ -48,20 +70,7 @@ export default {
|
|
|
return 'unknown';
|
|
|
},
|
|
|
style: function () {
|
|
|
- let color = '255, 255, 255';
|
|
|
- if (this.box) {
|
|
|
- switch (this.box.origin) {
|
|
|
- case 'user':
|
|
|
- color = '136, 0, 136';
|
|
|
- if (this.box.origin_user === this.$root.socket.username) {
|
|
|
- color = '255, 0, 0';
|
|
|
- }
|
|
|
- break;
|
|
|
- case 'pipeline':
|
|
|
- color = '0, 0, 255';
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
+ let color = this.color();
|
|
|
|
|
|
return {
|
|
|
backgroundColor: `rgba(${color}, ${this.shine ? 0.6 : 0.3})`,
|
|
@@ -71,42 +80,128 @@ export default {
|
|
|
width: this.position.w * 100 + '%',
|
|
|
height: this.position.h * 100 + '%'
|
|
|
}
|
|
|
- }
|
|
|
+ },
|
|
|
},
|
|
|
methods: {
|
|
|
- click: function (event) {
|
|
|
+
|
|
|
+ color: function() {
|
|
|
+ let box = this.box;
|
|
|
+ let current_user = this.$root.socket.username
|
|
|
+
|
|
|
+ if(!box)
|
|
|
+ return this.colors.default;
|
|
|
+
|
|
|
+ switch(box.origin) {
|
|
|
+ case 'user':
|
|
|
+ for (let confirmer of box.confirmations)
|
|
|
+ if (confirmer.confirming_user == current_user)
|
|
|
+ return this.colors.confirmed;
|
|
|
+
|
|
|
+ if (box.confirmations.length !== 0)
|
|
|
+ return this.colors.other_confirmed;
|
|
|
+
|
|
|
+ if (box.origin_user === current_user)
|
|
|
+ return this.colors.user;
|
|
|
+
|
|
|
+ return this.colors.other_user;
|
|
|
+
|
|
|
+ case 'pipeline':
|
|
|
+ return this.colors.pipeline;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ doubleLeftClick(event) {
|
|
|
+ console.debug("double left click", event);
|
|
|
+ this.$emit('interaction', "info-box");
|
|
|
+ this.$emit('crop', this.box);
|
|
|
+ },
|
|
|
+
|
|
|
+ doubleRightClick(event) {
|
|
|
+ console.debug("double right click", event);
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ singleLeftClick(event) {
|
|
|
+ console.debug("single left click", event);
|
|
|
+
|
|
|
if (this.deletable) {
|
|
|
// TODO then / error
|
|
|
this.$root.socket.post(`/results/${this.box.identifier}/remove`, {remove: true});
|
|
|
- event.stopPropagation();
|
|
|
}
|
|
|
- if (this.draggable) {
|
|
|
+ else if (this.draggable) {
|
|
|
// TODO then / error
|
|
|
this.$emit('move', event, this.position, this.update);
|
|
|
- event.stopPropagation();
|
|
|
}
|
|
|
- if (this.taggable) {
|
|
|
+ else if (this.taggable) {
|
|
|
// TODO then / error
|
|
|
this.$root.socket.post(`/results/${this.box.identifier}/label`, {
|
|
|
label: this.taggable.identifier
|
|
|
});
|
|
|
- event.stopPropagation();
|
|
|
+ this.$emit('crop', this.box);
|
|
|
}
|
|
|
- if (this.confirmable) {
|
|
|
+ else if (this.confirmable) {
|
|
|
// TODO then / error
|
|
|
this.$root.socket.post(`/results/${this.box.identifier}/confirm`, {
|
|
|
confirm: true
|
|
|
});
|
|
|
- event.stopPropagation();
|
|
|
}
|
|
|
- if (this.zoomable) {
|
|
|
+ else if (this.zoomable) {
|
|
|
this.$emit('zoom', this.position);
|
|
|
- event.stopPropagation();
|
|
|
}
|
|
|
- if (this.croppable) {
|
|
|
+ else if (this.croppable) {
|
|
|
this.$emit('crop', this.box);
|
|
|
- event.stopPropagation();
|
|
|
+ } else{
|
|
|
+ return
|
|
|
}
|
|
|
+
|
|
|
+ event.stopPropagation();
|
|
|
+ },
|
|
|
+
|
|
|
+ singleRightClick(event) {
|
|
|
+ console.debug("single right click", event);
|
|
|
+ this.$emit('interaction', "label-box");
|
|
|
+ this.$emit('crop', this.box);
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ singleClick(event) {
|
|
|
+ if (event.which == 1){
|
|
|
+ this.singleLeftClick(event);
|
|
|
+ }
|
|
|
+ else if (event.which == 2){
|
|
|
+ console.debug("single middle click");
|
|
|
+ }
|
|
|
+ else if (event.which == 3){
|
|
|
+ this.singleRightClick(event);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ doubleClick(event) {
|
|
|
+ if (event.which == 1){
|
|
|
+ this.doubleLeftClick(event);
|
|
|
+ }
|
|
|
+ else if (event.which == 2){
|
|
|
+ console.debug("double middle click");
|
|
|
+ }
|
|
|
+ else if (event.which == 3){
|
|
|
+ this.doubleRightClick(event);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ click: function (event) {
|
|
|
+ this.clickCounter++;
|
|
|
+
|
|
|
+ if (this.clickCounter == 1) {
|
|
|
+ this.timer = setTimeout( () => {
|
|
|
+ this.clickCounter = 0;
|
|
|
+ this.singleClick(event);
|
|
|
+ }, this.dblClickInterval);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ clearTimeout(this.timer);
|
|
|
+ this.clickCounter = 0;
|
|
|
+ this.doubleClick(event);
|
|
|
},
|
|
|
resize: function (mode) {
|
|
|
this.$emit('resize', mode, this.position, this.update);
|
|
@@ -216,4 +311,24 @@ export default {
|
|
|
cursor: nwse-resize;
|
|
|
/* background-color: brown; */
|
|
|
}
|
|
|
+
|
|
|
+.draggable {
|
|
|
+ cursor: url('~@/assets/icons/four-directions.svg') 8 8, move;
|
|
|
+}
|
|
|
+
|
|
|
+.deletable {
|
|
|
+ cursor: url('~@/assets/icons/trash.svg') 8 8, not-allowed;
|
|
|
+}
|
|
|
+
|
|
|
+.taggable {
|
|
|
+ cursor: url('~@/assets/icons/tag.svg') 8 8, alias;
|
|
|
+}
|
|
|
+
|
|
|
+.confirmable {
|
|
|
+ cursor: url('~@/assets/icons/check.svg') 8 8, pointer;
|
|
|
+}
|
|
|
+
|
|
|
+.croppable {
|
|
|
+ cursor: url('~@/assets/icons/info.svg') 8 8, move;
|
|
|
+}
|
|
|
</style>
|