diff --git a/app/db.sqlite3 b/app/db.sqlite3 index c490718c..0df78685 100644 Binary files a/app/db.sqlite3 and b/app/db.sqlite3 differ diff --git a/app/server/static/bundle/sequence_labeling.js b/app/server/static/bundle/sequence_labeling.js index fc234b93..6f9ce4a9 100644 --- a/app/server/static/bundle/sequence_labeling.js +++ b/app/server/static/bundle/sequence_labeling.js @@ -185,7 +185,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _htt /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.js\");\n/* harmony import */ var _mixin_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./mixin.js */ \"./static/js/mixin.js\");\n/* harmony import */ var _http_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./http.js */ \"./static/js/http.js\");\n\nvue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].use(__webpack_require__(/*! vue-shortkey */ \"./node_modules/vue-shortkey/dist/index.js\"), { prevent: ['input', 'textarea'] });\n\n\n\nvue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].component('annotator', {\n template: '
\\\n {{ text.slice(r.start_offset, r.end_offset) }}\\\n
',\n props: {\n 'labels': Array, // [{id: Integer, color: String, text: String}]\n 'text': String,\n 'entityPositions': Array, //[{'startOffset': 10, 'endOffset': 15, 'label_id': 1}]\n },\n data() {\n return {\n startOffset: 0,\n endOffset: 0,\n }\n },\n methods: {\n setSelectedRange: function (e) {\n if (window.getSelection) {\n var range = window.getSelection().getRangeAt(0);\n var preSelectionRange = range.cloneRange();\n preSelectionRange.selectNodeContents(this.$el);\n preSelectionRange.setEnd(range.startContainer, range.startOffset);\n var start = preSelectionRange.toString().length;\n var end = start + range.toString().length;\n } else if (document.selection && document.selection.type != 'Control') {\n var selectedTextRange = document.selection.createRange();\n var preSelectionTextRange = document.body.createTextRange();\n preSelectionTextRange.moveToElementText(this.$el);\n preSelectionTextRange.setEndPoint('EndToStart', selectedTextRange);\n var start = preSelectionTextRange.text.length;\n var end = start + selectedTextRange.text.length;\n }\n this.startOffset = start;\n this.endOffset = end;\n console.log(start, end);\n },\n validRange: function () {\n if (this.startOffset == this.endOffset) {\n return false\n } else if (this.startOffset > this.text.length || this.endOffset > this.text.length) {\n return false\n } else if (this.startOffset < 0 || this.endOffset < 0) {\n return false\n } else {\n return true\n }\n },\n resetRange: function () {\n this.startOffset = 0;\n this.endOffset = 0\n },\n addLabel: function (label_id) {\n if (this.validRange()) {\n var label = {\n start_offset: this.startOffset,\n end_offset: this.endOffset,\n label_id: label_id\n };\n this.$emit('add-label', label);\n }\n },\n deleteLabel: function (index) {\n this.$emit('delete-label', index);\n },\n makeLabel: function (start_offset, end_offset) {\n var label = {\n id: 0,\n label: {\n id: -1,\n text: '',\n shortcut: '',\n background_color: '',\n text_color: ''\n },\n start_offset: start_offset,\n end_offset: end_offset\n }\n return label\n }\n },\n watch: {\n entityPositions: function () {\n this.resetRange()\n }\n },\n computed: {\n sortedEntityPositions: function () {\n this.entityPositions = this.entityPositions.sort((a, b) => a.start_offset - b.start_offset);\n return this.entityPositions\n },\n chunks: function () {\n var res = [];\n var left = 0;\n for (let i in this.sortedEntityPositions) {\n var e = this.sortedEntityPositions[i];\n var l = this.makeLabel(left, e['start_offset'])\n res.push(l);\n res.push(e);\n left = e['end_offset'];\n }\n var l = this.makeLabel(left, this.text.length)\n res.push(l)\n\n return res\n }\n }\n})\n\nvar vm = new vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"]({\n el: '#mail-app',\n delimiters: ['[[', ']]'],\n mixins: [_mixin_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]],\n methods: {\n annotate: function (label_id) {\n var payload = this.$refs.annotator.addLabel(label_id);\n },\n addLabel: function (label) {\n var payload = label;\n var doc_id = this.items[this.cur].id;\n payload['label'] = label.label_id;\n _http_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].post(`docs/${doc_id}/annotations/`, payload).then(response => {\n this.items[this.cur]['labels'].push(response.data);\n })\n },\n deleteLabel: function (label) {\n var doc_id = this.items[this.cur].id;\n _http_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].delete(`docs/${doc_id}/annotations/${label.id}`).then(response => {\n this.items[this.cur]['labels'].splice(this.items[this.cur]['labels'].indexOf(label), 1)\n });\n },\n }\n});\n\n//# sourceURL=webpack:///./static/js/sequence_labeling.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.js\");\n/* harmony import */ var _mixin__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./mixin */ \"./static/js/mixin.js\");\n/* harmony import */ var _http__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./http */ \"./static/js/http.js\");\n\n\n\n\nvue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].use(__webpack_require__(/*! vue-shortkey */ \"./node_modules/vue-shortkey/dist/index.js\"), {\n prevent: ['input', 'textarea'],\n});\n\nvue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].component('annotator', {\n template: '
\\\n {{ text.slice(r.start_offset, r.end_offset) }}\\\n
',\n props: {\n labels: Array, // [{id: Integer, color: String, text: String}]\n text: String,\n entityPositions: Array, // [{'startOffset': 10, 'endOffset': 15, 'label_id': 1}]\n },\n data() {\n return {\n startOffset: 0,\n endOffset: 0,\n };\n },\n\n methods: {\n setSelectedRange(e) {\n let start;\n let end;\n if (window.getSelection) {\n const range = window.getSelection().getRangeAt(0);\n const preSelectionRange = range.cloneRange();\n preSelectionRange.selectNodeContents(this.$el);\n preSelectionRange.setEnd(range.startContainer, range.startOffset);\n start = preSelectionRange.toString().length;\n end = start + range.toString().length;\n } else if (document.selection && document.selection.type !== 'Control') {\n const selectedTextRange = document.selection.createRange();\n const preSelectionTextRange = document.body.createTextRange();\n preSelectionTextRange.moveToElementText(this.$el);\n preSelectionTextRange.setEndPoint('EndToStart', selectedTextRange);\n start = preSelectionTextRange.text.length;\n end = start + selectedTextRange.text.length;\n }\n this.startOffset = start;\n this.endOffset = end;\n console.log(start, end);\n },\n\n validRange() {\n if (this.startOffset === this.endOffset) {\n return false;\n }\n if (this.startOffset > this.text.length || this.endOffset > this.text.length) {\n return false;\n }\n if (this.startOffset < 0 || this.endOffset < 0) {\n return false;\n }\n return true;\n },\n\n resetRange() {\n this.startOffset = 0;\n this.endOffset = 0;\n },\n\n addLabel(labelId) {\n if (this.validRange()) {\n const label = {\n start_offset: this.startOffset,\n end_offset: this.endOffset,\n label: labelId,\n };\n this.$emit('add-label', label);\n }\n },\n\n removeLabel(index) {\n this.$emit('remove-label', index);\n },\n\n makeLabel(startOffset, endOffset) {\n const label = {\n id: 0,\n label: -1,\n start_offset: startOffset,\n end_offset: endOffset,\n };\n return label;\n },\n },\n\n watch: {\n entityPositions() {\n this.resetRange();\n },\n },\n\n computed: {\n sortedEntityPositions() {\n this.entityPositions = this.entityPositions.sort((a, b) => a.start_offset - b.start_offset);\n return this.entityPositions;\n },\n\n chunks() {\n const res = [];\n let left = 0;\n for (let i = 0; i < this.sortedEntityPositions.length; i++) {\n const e = this.sortedEntityPositions[i];\n const l = this.makeLabel(left, e.start_offset);\n res.push(l);\n res.push(e);\n left = e.end_offset;\n }\n const l = this.makeLabel(left, this.text.length);\n res.push(l);\n\n return res;\n },\n\n id2label() {\n let id2label = {};\n // default value;\n id2label[-1] = {\n text_color: '',\n background_color: '',\n };\n for (let i = 0; i < this.labels.length; i++) {\n const label = this.labels[i];\n id2label[label.id] = label;\n }\n return id2label;\n },\n },\n});\n\nconst vm = new vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"]({\n el: '#mail-app',\n delimiters: ['[[', ']]'],\n mixins: [_mixin__WEBPACK_IMPORTED_MODULE_1__[\"default\"]],\n methods: {\n annotate(labelId) {\n this.$refs.annotator.addLabel(labelId);\n },\n\n addLabel(annotation) {\n const docId = this.docs[this.pageNumber].id;\n _http__WEBPACK_IMPORTED_MODULE_2__[\"default\"].post(`docs/${docId}/annotations/`, annotation).then((response) => {\n this.annotations[this.pageNumber].push(response.data);\n });\n },\n },\n});\n\n\n//# sourceURL=webpack:///./static/js/sequence_labeling.js?"); /***/ }) diff --git a/app/server/static/js/sequence_labeling.js b/app/server/static/js/sequence_labeling.js index d8a7b8c1..079f2aea 100644 --- a/app/server/static/js/sequence_labeling.js +++ b/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: '
\ + template: '
\ {{ text.slice(r.start_offset, r.end_offset) }}\ + v-if="id2label[r.label].text_color"\ + @click="removeLabel(r)">\
', - 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) - }); - }, - } -}); \ No newline at end of file + addLabel(annotation) { + const docId = this.docs[this.pageNumber].id; + HTTP.post(`docs/${docId}/annotations/`, annotation).then((response) => { + this.annotations[this.pageNumber].push(response.data); + }); + }, + }, +}); diff --git a/app/server/templates/annotation/sequence_labeling.html b/app/server/templates/annotation/sequence_labeling.html index 8d857ff6..12b295fd 100644 --- a/app/server/templates/annotation/sequence_labeling.html +++ b/app/server/templates/annotation/sequence_labeling.html @@ -22,12 +22,12 @@
-
+