|
@@ -1,28 +1,15 @@
|
|
|
<template>
|
|
|
- <!-- TODO missing labeled images -->
|
|
|
-
|
|
|
<div class="project-labels-window">
|
|
|
- <h1 class="headline">Labels</h1>
|
|
|
-
|
|
|
- <div class="label" v-for="label in sortedLabels" :key="label.identifier">
|
|
|
- <editable-headline :value="label.name"
|
|
|
- @change="editLabel(label.identifier, $event)"
|
|
|
- @remove="removeLabel(label.identifier)">
|
|
|
- {{ label.name }}
|
|
|
- </editable-headline>
|
|
|
-
|
|
|
- <!--
|
|
|
- <media-selector v-if="labeledImages[label.identifier].length > 0"
|
|
|
- :project-id="currentProject.identifier"
|
|
|
- :media="labeledImages[label.identifier]"
|
|
|
- current="-1"
|
|
|
- :socket="socket"></media-selector>
|
|
|
- <div v-else
|
|
|
- class="no-elements">
|
|
|
- No labeled images found...
|
|
|
- </div>
|
|
|
- -->
|
|
|
- </div>
|
|
|
+ <h1 class="headline"
|
|
|
+ :class="{target: target}"
|
|
|
+ @dragover="dragover" @dragleave="dragleave" @drop="drop">
|
|
|
+ Labels
|
|
|
+ </h1>
|
|
|
+
|
|
|
+ <label-tree-view v-for="label in labelTree" :key="label.identifier"
|
|
|
+ :label="label"
|
|
|
+ :targetable="true"
|
|
|
+ indent="2rem"/>
|
|
|
|
|
|
<div class="label">
|
|
|
<input-group>
|
|
@@ -39,13 +26,13 @@
|
|
|
|
|
|
<script>
|
|
|
import TextInput from "@/components/base/text-input";
|
|
|
-import EditableHeadline from "@/components/base/editable-headline";
|
|
|
import ButtonInput from "@/components/base/button-input";
|
|
|
import InputGroup from "@/components/base/input-group";
|
|
|
+import LabelTreeView from "@/components/other/LabelTreeView";
|
|
|
|
|
|
export default {
|
|
|
name: "project-labels-window",
|
|
|
- components: {InputGroup, ButtonInput, EditableHeadline, TextInput},
|
|
|
+ components: {LabelTreeView, InputGroup, ButtonInput, TextInput},
|
|
|
created: function () {
|
|
|
// get labels
|
|
|
this.getLabels();
|
|
@@ -65,12 +52,53 @@ export default {
|
|
|
data: function () {
|
|
|
return {
|
|
|
labels: [],
|
|
|
- createLabelValue: ''
|
|
|
+ createLabelValue: '',
|
|
|
+ target: false
|
|
|
}
|
|
|
},
|
|
|
computed: {
|
|
|
+ // TODO remove
|
|
|
sortedLabels: function () {
|
|
|
return [...this.labels].sort((a, b) => a.name < b.name ? -1 : +1);
|
|
|
+ },
|
|
|
+ labelTree: function () {
|
|
|
+ const labels = [...this.labels].sort((a, b) => a.name < b.name ? +1 : -1);
|
|
|
+
|
|
|
+ const tree = [];
|
|
|
+ const references = {};
|
|
|
+
|
|
|
+ while (labels.length > 0) {
|
|
|
+ const length = labels.length;
|
|
|
+
|
|
|
+ for (let i = labels.length - 1; i >= 0; i--) {
|
|
|
+ if (labels[i]['parent_id'] === null) {
|
|
|
+ const label = Object.assign({
|
|
|
+ // parent: null,
|
|
|
+ children: []
|
|
|
+ }, labels.splice(i, 1)[0]);
|
|
|
+
|
|
|
+ tree.push(label);
|
|
|
+ references[label.identifier] = label;
|
|
|
+ } else if (labels[i]['parent_id'] in references) {
|
|
|
+ const parent = references[labels[i]['parent_id']];
|
|
|
+ const label = Object.assign({
|
|
|
+ // parent: parent,
|
|
|
+ children: []
|
|
|
+ }, labels.splice(i, 1)[0]);
|
|
|
+
|
|
|
+ parent.children.push(label);
|
|
|
+ references[label.identifier] = label;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (labels.length === length) {
|
|
|
+ // TODO show in ui
|
|
|
+ console.log('I could not parse all items. Sorry!')
|
|
|
+ return tree;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return tree;
|
|
|
}
|
|
|
},
|
|
|
methods: {
|
|
@@ -116,13 +144,18 @@ export default {
|
|
|
this.$root.socket.post(`/projects/${this.$root.project.identifier}/labels`, {name: this.createLabelValue});
|
|
|
this.createLabelValue = '';
|
|
|
},
|
|
|
- removeLabel: function (id) {
|
|
|
- // TODO then / error
|
|
|
- this.$root.socket.post(`/projects/${this.$root.project.identifier}/labels/${id}/remove`, {remove: true});
|
|
|
+ dragover: function (e) {
|
|
|
+ e.preventDefault();
|
|
|
+ this.target = true;
|
|
|
},
|
|
|
- editLabel: function (id, value) {
|
|
|
- // TODO then / error
|
|
|
- this.$root.socket.post(`/projects/${this.$root.project.identifier}/labels/${id}/name`, {name: value});
|
|
|
+ dragleave: function () {
|
|
|
+ this.target = false;
|
|
|
+ },
|
|
|
+ drop: function (e) {
|
|
|
+ this.dragleave();
|
|
|
+
|
|
|
+ const element = e.dataTransfer.getData('text/identifier');
|
|
|
+ this.$root.socket.post(`/projects/${this.$root.project.identifier}/labels/${element}/parent`, {parent: null});
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -134,10 +167,11 @@ export default {
|
|
|
overflow: auto;
|
|
|
}
|
|
|
|
|
|
-.label {
|
|
|
- margin-bottom: 1rem;
|
|
|
+h1.target {
|
|
|
+ text-decoration: underline;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
/deep/ .element {
|
|
|
border: none;
|
|
|
}
|
|
@@ -153,4 +187,5 @@ export default {
|
|
|
.no-elements {
|
|
|
margin-top: 0.5rem;
|
|
|
}
|
|
|
-</style>
|
|
|
+*/
|
|
|
+</style>
|