Browse Source

Refactor sequence_labeling.js

pull/10/head
Hironsan 6 years ago
parent
commit
4d652ac6ce
4 changed files with 151 additions and 135 deletions
  1. BIN
      app/db.sqlite3
  2. 2
      app/server/static/bundle/sequence_labeling.js
  3. 276
      app/server/static/js/sequence_labeling.js
  4. 8
      app/server/templates/annotation/sequence_labeling.html

BIN
app/db.sqlite3

2
app/server/static/bundle/sequence_labeling.js
File diff suppressed because it is too large
View File

276
app/server/static/js/sequence_labeling.js

@ -1,142 +1,158 @@
import Vue from 'vue';
Vue.use(require('vue-shortkey'), { prevent: ['input', 'textarea'] });
import annotationMixin from './mixin.js';
import HTTP from './http.js';
import annotationMixin from './mixin';
import HTTP from './http';
Vue.use(require('vue-shortkey'), {
prevent: ['input', 'textarea'],
});
Vue.component('annotator', {
template: '<div @click="setSelectedRange">\
template: '<div @click="setSelectedRange">\
<span v-for="r in chunks"\
v-bind:class="{tag: r.label.text_color}"\
v-bind:style="{ color: r.label.text_color, backgroundColor: r.label.background_color }"\
v-bind:class="{tag: id2label[r.label].text_color}"\
v-bind:style="{ color: id2label[r.label].text_color, backgroundColor: id2label[r.label].background_color }"\
>{{ text.slice(r.start_offset, r.end_offset) }}<button class="delete is-small"\
v-if="r.label.text_color"\
@click="deleteLabel(r)"></button></span>\
v-if="id2label[r.label].text_color"\
@click="removeLabel(r)"></button></span>\
</div>',
props: {
'labels': Array, // [{id: Integer, color: String, text: String}]
'text': String,
'entityPositions': Array, //[{'startOffset': 10, 'endOffset': 15, 'label_id': 1}]
props: {
labels: Array, // [{id: Integer, color: String, text: String}]
text: String,
entityPositions: Array, // [{'startOffset': 10, 'endOffset': 15, 'label_id': 1}]
},
data() {
return {
startOffset: 0,
endOffset: 0,
};
},
methods: {
setSelectedRange(e) {
let start;
let end;
if (window.getSelection) {
const range = window.getSelection().getRangeAt(0);
const preSelectionRange = range.cloneRange();
preSelectionRange.selectNodeContents(this.$el);
preSelectionRange.setEnd(range.startContainer, range.startOffset);
start = preSelectionRange.toString().length;
end = start + range.toString().length;
} else if (document.selection && document.selection.type !== 'Control') {
const selectedTextRange = document.selection.createRange();
const preSelectionTextRange = document.body.createTextRange();
preSelectionTextRange.moveToElementText(this.$el);
preSelectionTextRange.setEndPoint('EndToStart', selectedTextRange);
start = preSelectionTextRange.text.length;
end = start + selectedTextRange.text.length;
}
this.startOffset = start;
this.endOffset = end;
console.log(start, end);
},
validRange() {
if (this.startOffset === this.endOffset) {
return false;
}
if (this.startOffset > this.text.length || this.endOffset > this.text.length) {
return false;
}
if (this.startOffset < 0 || this.endOffset < 0) {
return false;
}
return true;
},
resetRange() {
this.startOffset = 0;
this.endOffset = 0;
},
addLabel(labelId) {
if (this.validRange()) {
const label = {
start_offset: this.startOffset,
end_offset: this.endOffset,
label: labelId,
};
this.$emit('add-label', label);
}
},
removeLabel(index) {
this.$emit('remove-label', index);
},
data() {
return {
startOffset: 0,
endOffset: 0,
}
makeLabel(startOffset, endOffset) {
const label = {
id: 0,
label: -1,
start_offset: startOffset,
end_offset: endOffset,
};
return label;
},
},
watch: {
entityPositions() {
this.resetRange();
},
},
computed: {
sortedEntityPositions() {
this.entityPositions = this.entityPositions.sort((a, b) => a.start_offset - b.start_offset);
return this.entityPositions;
},
methods: {
setSelectedRange: function (e) {
if (window.getSelection) {
var range = window.getSelection().getRangeAt(0);
var preSelectionRange = range.cloneRange();
preSelectionRange.selectNodeContents(this.$el);
preSelectionRange.setEnd(range.startContainer, range.startOffset);
var start = preSelectionRange.toString().length;
var end = start + range.toString().length;
} else if (document.selection && document.selection.type != 'Control') {
var selectedTextRange = document.selection.createRange();
var preSelectionTextRange = document.body.createTextRange();
preSelectionTextRange.moveToElementText(this.$el);
preSelectionTextRange.setEndPoint('EndToStart', selectedTextRange);
var start = preSelectionTextRange.text.length;
var end = start + selectedTextRange.text.length;
}
this.startOffset = start;
this.endOffset = end;
console.log(start, end);
},
validRange: function () {
if (this.startOffset == this.endOffset) {
return false
} else if (this.startOffset > this.text.length || this.endOffset > this.text.length) {
return false
} else if (this.startOffset < 0 || this.endOffset < 0) {
return false
} else {
return true
}
},
resetRange: function () {
this.startOffset = 0;
this.endOffset = 0
},
addLabel: function (label_id) {
if (this.validRange()) {
var label = {
start_offset: this.startOffset,
end_offset: this.endOffset,
label_id: label_id
};
this.$emit('add-label', label);
}
},
deleteLabel: function (index) {
this.$emit('delete-label', index);
},
makeLabel: function (start_offset, end_offset) {
var label = {
id: 0,
label: {
id: -1,
text: '',
shortcut: '',
background_color: '',
text_color: ''
},
start_offset: start_offset,
end_offset: end_offset
}
return label
}
chunks() {
const res = [];
let left = 0;
for (let i = 0; i < this.sortedEntityPositions.length; i++) {
const e = this.sortedEntityPositions[i];
const l = this.makeLabel(left, e.start_offset);
res.push(l);
res.push(e);
left = e.end_offset;
}
const l = this.makeLabel(left, this.text.length);
res.push(l);
return res;
},
watch: {
entityPositions: function () {
this.resetRange()
}
id2label() {
let id2label = {};
// default value;
id2label[-1] = {
text_color: '',
background_color: '',
};
for (let i = 0; i < this.labels.length; i++) {
const label = this.labels[i];
id2label[label.id] = label;
}
return id2label;
},
computed: {
sortedEntityPositions: function () {
this.entityPositions = this.entityPositions.sort((a, b) => a.start_offset - b.start_offset);
return this.entityPositions
},
chunks: function () {
var res = [];
var left = 0;
for (let i in this.sortedEntityPositions) {
var e = this.sortedEntityPositions[i];
var l = this.makeLabel(left, e['start_offset'])
res.push(l);
res.push(e);
left = e['end_offset'];
}
var l = this.makeLabel(left, this.text.length)
res.push(l)
},
});
return res
}
}
})
const vm = new Vue({
el: '#mail-app',
delimiters: ['[[', ']]'],
mixins: [annotationMixin],
methods: {
annotate(labelId) {
this.$refs.annotator.addLabel(labelId);
},
var vm = new Vue({
el: '#mail-app',
delimiters: ['[[', ']]'],
mixins: [annotationMixin],
methods: {
annotate: function (label_id) {
var payload = this.$refs.annotator.addLabel(label_id);
},
addLabel: function (label) {
var payload = label;
var doc_id = this.items[this.cur].id;
payload['label'] = label.label_id;
HTTP.post(`docs/${doc_id}/annotations/`, payload).then(response => {
this.items[this.cur]['labels'].push(response.data);
})
},
deleteLabel: function (label) {
var doc_id = this.items[this.cur].id;
HTTP.delete(`docs/${doc_id}/annotations/${label.id}`).then(response => {
this.items[this.cur]['labels'].splice(this.items[this.cur]['labels'].indexOf(label), 1)
});
},
}
});
addLabel(annotation) {
const docId = this.docs[this.pageNumber].id;
HTTP.post(`docs/${docId}/annotations/`, annotation).then((response) => {
this.annotations[this.pageNumber].push(response.data);
});
},
},
});

8
app/server/templates/annotation/sequence_labeling.html

@ -22,12 +22,12 @@
</div>
</header>
<div class="card-content">
<div class="content">
<div class="content" v-if="docs[pageNumber] && annotations[pageNumber]">
<annotator ref="annotator"
v-bind:labels="labels"
v-bind:entity-positions="items[cur].labels"
v-bind:text="items[cur].text"
@delete-label="deleteLabel"
v-bind:entity-positions="annotations[pageNumber]"
v-bind:text="docs[pageNumber].text"
@remove-label="removeLabel"
@add-label="addLabel"></annotator>
</div>
</div>

Loading…
Cancel
Save