Browse Source

Update document_classification.js

pull/10/head
Hironsan 6 years ago
parent
commit
e8464077a1
10 changed files with 208 additions and 155 deletions
  1. BIN
      app/db.sqlite3
  2. 4
      app/server/static/bundle/document_classification.js
  3. 2
      app/server/static/bundle/seq2seq.js
  4. 2
      app/server/static/bundle/sequence_labeling.js
  5. 3
      app/server/static/css/admin.css
  6. 4
      app/server/static/js/.jsbeautifyrc
  7. 58
      app/server/static/js/document_classification.js
  8. 271
      app/server/static/js/mixin.js
  9. 2
      app/server/templates/annotation/annotation_base.html
  10. 17
      app/server/templates/annotation/document_classification.html

BIN
app/db.sqlite3

4
app/server/static/bundle/document_classification.js

@ -161,7 +161,7 @@ eval("var g;\n\n// This works in non-strict mode\ng = (function() {\n\treturn th
/***/ (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\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\n methods: {\n addLabel: async function (label_id) {\n for (var i = 0; i < this.items[this.cur]['labels'].length; i++) {\n var item = this.items[this.cur]['labels'][i];\n if (label_id == item.label.id) {\n this.deleteLabel(i);\n return;\n }\n }\n\n var payload = {\n 'label': label_id\n };\n\n var doc_id = this.items[this.cur].id;\n await _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 }\n});\n\n//# sourceURL=webpack:///./static/js/document_classification.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\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\n methods: {\n isIn(label) {\n for (let i = 0; i < this.annotations[this.cur].length; i++) {\n const a = this.annotations[this.cur][i];\n if (a.label === label.id) {\n return a;\n }\n }\n return false;\n },\n\n async addLabel(label) {\n const a = this.isIn(label);\n if (a) {\n this.removeLabel(a);\n } else {\n const docId = this.items[this.cur].id;\n const payload = {\n label: label.id,\n };\n await _http__WEBPACK_IMPORTED_MODULE_2__[\"default\"].post(`docs/${docId}/annotations/`, payload).then((response) => {\n this.annotations[this.cur].push(response.data);\n });\n }\n },\n },\n});\n\n//# sourceURL=webpack:///./static/js/document_classification.js?");
/***/ }),
@ -185,7 +185,7 @@ eval("__webpack_require__.r(__webpack_exports__);\naxios.defaults.xsrfCookieName
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _http_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./http.js */ \"./static/js/http.js\");\n\n\nvar annotationMixin = {\n data: function () {\n return {\n cur: 0,\n items: [{\n id: null,\n text: '',\n labels: []\n }],\n labels: [],\n guideline: 'Here is the Annotation Guideline Text',\n total: 0,\n remaining: 0,\n searchQuery: '',\n url: '',\n picked: 'all',\n }\n },\n methods: {\n nextPage: async function () {\n this.cur += 1;\n if (this.cur == this.items.length) {\n if (this.next) {\n this.url = this.next;\n await this.search();\n this.cur = 0;\n } else {\n this.cur = this.items.length - 1;\n }\n }\n this.showMessage(this.cur);\n },\n prevPage: async function () {\n this.cur -= 1;\n if (this.cur == -1) {\n if (this.prev) {\n this.url = this.prev;\n await this.search();\n this.cur = this.items.length - 1;\n } else {\n this.cur = 0;\n }\n }\n this.showMessage(this.cur);\n },\n search: async function () {\n await _http_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].get(this.url).then(response => {\n this.items = response.data['results'];\n this.next = response.data['next'];\n this.prev = response.data['previous'];\n })\n },\n showMessage: function (index) {\n this.cur = index;\n },\n getState: function () {\n if (this.picked == 'all') {\n return ''\n } else if (this.picked == 'active') {\n return 'true'\n } else {\n return 'false'\n }\n },\n submit: async function () {\n var state = this.getState();\n this.url = `docs/?q=${this.searchQuery}&is_checked=${state}`;\n await this.search();\n this.cur = 0;\n },\n deleteLabel: async function (index) {\n var doc_id = this.items[this.cur].id;\n var annotation_id = this.items[this.cur]['labels'][index].id;\n _http_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].delete(`docs/${doc_id}/annotations/${annotation_id}`).then(response => {\n this.items[this.cur]['labels'].splice(index, 1)\n })\n },\n\n removeLabel: function (label) {\n var doc_id = this.items[this.cur].id;\n _http_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].delete(`docs/${doc_id}/annotations/${label.id}`).then(response => {\n var index = this.items[this.cur]['labels'].indexOf(label)\n this.items[this.cur]['labels'].splice(index, 1)\n })\n }\n },\n watch: {\n picked: function (){\n this.submit();\n },\n items: function () {\n // fetch progress info.\n _http_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].get('progress').then(response => {\n this.total = response.data['total'];\n this.remaining = response.data['remaining'];\n })\n }\n },\n created: function () {\n _http_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].get('labels').then(response => {\n this.labels = response.data\n });\n this.submit();\n },\n computed: {\n achievement: function () {\n var done = this.total - this.remaining;\n var percentage = Math.round(done / this.total * 100);\n return this.total > 0 ? percentage : 0;\n },\n progressColor: function () {\n if (this.achievement < 30) {\n return 'is-danger'\n } else if (this.achievement < 70) {\n return 'is-warning'\n } else {\n return 'is-primary'\n }\n }\n }\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (annotationMixin);\n\n//# sourceURL=webpack:///./static/js/mixin.js?");
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _http__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./http */ \"./static/js/http.js\");\n\n\nconst annotationMixin = {\n data() {\n return {\n cur: 0,\n items: [{\n id: null,\n text: '',\n labels: [],\n }],\n labels: [],\n guideline: '',\n total: 0,\n remaining: 0,\n searchQuery: '',\n url: '',\n picked: 'all',\n annotations: [],\n };\n },\n\n methods: {\n async nextPage() {\n this.cur += 1;\n if (this.cur === this.items.length) {\n if (this.next) {\n this.url = this.next;\n await this.search();\n this.cur = 0;\n } else {\n this.cur = this.items.length - 1;\n }\n }\n this.showMessage(this.cur);\n },\n\n async prevPage() {\n this.cur -= 1;\n if (this.cur === -1) {\n if (this.prev) {\n this.url = this.prev;\n await this.search();\n this.cur = this.items.length - 1;\n } else {\n this.cur = 0;\n }\n }\n this.showMessage(this.cur);\n },\n\n async search() {\n await _http__WEBPACK_IMPORTED_MODULE_0__[\"default\"].get(this.url).then((response) => {\n this.items = response.data.results;\n this.next = response.data.next;\n this.prev = response.data.previous;\n });\n for (let i = 0; i < this.items.length; i++) {\n const docId = this.items[i].id;\n _http__WEBPACK_IMPORTED_MODULE_0__[\"default\"].get(`docs/${docId}/annotations/`).then((response) => {\n this.annotations.push(response.data);\n });\n }\n },\n\n showMessage(index) {\n this.cur = index;\n },\n\n getState() {\n if (this.picked === 'all') {\n return '';\n }\n if (this.picked === 'active') {\n return 'true';\n }\n return 'false';\n },\n\n async submit() {\n const state = this.getState();\n this.url = `docs/?q=${this.searchQuery}&is_checked=${state}`;\n await this.search();\n this.cur = 0;\n },\n\n getTextColor(labelId) {\n for (let i = 0; i < this.labels.length; i++) {\n const label = this.labels[i];\n if (label.id === labelId) {\n return label.text_color;\n }\n }\n return '#ffffff';\n },\n\n getBgColor(labelId) {\n for (let i = 0; i < this.labels.length; i++) {\n const label = this.labels[i];\n if (label.id === labelId) {\n return label.background_color;\n }\n }\n return '#333333';\n },\n\n getLabelText(labelId) {\n for (let i = 0; i < this.labels.length; i++) {\n const label = this.labels[i];\n if (label.id === labelId) {\n return label.text;\n }\n }\n return 'NO';\n },\n\n removeLabel(label) {\n const docId = this.items[this.cur].id;\n _http__WEBPACK_IMPORTED_MODULE_0__[\"default\"].delete(`docs/${docId}/annotations/${label.id}`).then((response) => {\n const index = this.annotations[this.cur].indexOf(response.data);\n this.annotations[this.cur].splice(index, 1);\n });\n },\n },\n\n watch: {\n picked() {\n this.submit();\n },\n\n items() {\n // fetch progress info.\n _http__WEBPACK_IMPORTED_MODULE_0__[\"default\"].get('progress').then((response) => {\n this.total = response.data.total;\n this.remaining = response.data.remaining;\n });\n },\n },\n\n created() {\n _http__WEBPACK_IMPORTED_MODULE_0__[\"default\"].get('labels').then((response) => {\n this.labels = response.data;\n });\n this.submit();\n },\n\n computed: {\n achievement() {\n const done = this.total - this.remaining;\n const percentage = Math.round(done / this.total * 100);\n return this.total > 0 ? percentage : 0;\n },\n\n progressColor() {\n if (this.achievement < 30) {\n return 'is-danger';\n }\n if (this.achievement < 70) {\n return 'is-warning';\n }\n return 'is-primary';\n },\n },\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (annotationMixin);\n\n\n//# sourceURL=webpack:///./static/js/mixin.js?");
/***/ })

2
app/server/static/bundle/seq2seq.js

@ -173,7 +173,7 @@ eval("__webpack_require__.r(__webpack_exports__);\naxios.defaults.xsrfCookieName
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _http_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./http.js */ \"./static/js/http.js\");\n\n\nvar annotationMixin = {\n data: function () {\n return {\n cur: 0,\n items: [{\n id: null,\n text: '',\n labels: []\n }],\n labels: [],\n guideline: 'Here is the Annotation Guideline Text',\n total: 0,\n remaining: 0,\n searchQuery: '',\n url: '',\n picked: 'all',\n }\n },\n methods: {\n nextPage: async function () {\n this.cur += 1;\n if (this.cur == this.items.length) {\n if (this.next) {\n this.url = this.next;\n await this.search();\n this.cur = 0;\n } else {\n this.cur = this.items.length - 1;\n }\n }\n this.showMessage(this.cur);\n },\n prevPage: async function () {\n this.cur -= 1;\n if (this.cur == -1) {\n if (this.prev) {\n this.url = this.prev;\n await this.search();\n this.cur = this.items.length - 1;\n } else {\n this.cur = 0;\n }\n }\n this.showMessage(this.cur);\n },\n search: async function () {\n await _http_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].get(this.url).then(response => {\n this.items = response.data['results'];\n this.next = response.data['next'];\n this.prev = response.data['previous'];\n })\n },\n showMessage: function (index) {\n this.cur = index;\n },\n getState: function () {\n if (this.picked == 'all') {\n return ''\n } else if (this.picked == 'active') {\n return 'true'\n } else {\n return 'false'\n }\n },\n submit: async function () {\n var state = this.getState();\n this.url = `docs/?q=${this.searchQuery}&is_checked=${state}`;\n await this.search();\n this.cur = 0;\n },\n deleteLabel: async function (index) {\n var doc_id = this.items[this.cur].id;\n var annotation_id = this.items[this.cur]['labels'][index].id;\n _http_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].delete(`docs/${doc_id}/annotations/${annotation_id}`).then(response => {\n this.items[this.cur]['labels'].splice(index, 1)\n })\n },\n\n removeLabel: function (label) {\n var doc_id = this.items[this.cur].id;\n _http_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].delete(`docs/${doc_id}/annotations/${label.id}`).then(response => {\n var index = this.items[this.cur]['labels'].indexOf(label)\n this.items[this.cur]['labels'].splice(index, 1)\n })\n }\n },\n watch: {\n picked: function (){\n this.submit();\n },\n items: function () {\n // fetch progress info.\n _http_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].get('progress').then(response => {\n this.total = response.data['total'];\n this.remaining = response.data['remaining'];\n })\n }\n },\n created: function () {\n _http_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].get('labels').then(response => {\n this.labels = response.data\n });\n this.submit();\n },\n computed: {\n achievement: function () {\n var done = this.total - this.remaining;\n var percentage = Math.round(done / this.total * 100);\n return this.total > 0 ? percentage : 0;\n },\n progressColor: function () {\n if (this.achievement < 30) {\n return 'is-danger'\n } else if (this.achievement < 70) {\n return 'is-warning'\n } else {\n return 'is-primary'\n }\n }\n }\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (annotationMixin);\n\n//# sourceURL=webpack:///./static/js/mixin.js?");
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _http__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./http */ \"./static/js/http.js\");\n\n\nconst annotationMixin = {\n data() {\n return {\n cur: 0,\n items: [{\n id: null,\n text: '',\n labels: [],\n }],\n labels: [],\n guideline: '',\n total: 0,\n remaining: 0,\n searchQuery: '',\n url: '',\n picked: 'all',\n annotations: [],\n };\n },\n\n methods: {\n async nextPage() {\n this.cur += 1;\n if (this.cur === this.items.length) {\n if (this.next) {\n this.url = this.next;\n await this.search();\n this.cur = 0;\n } else {\n this.cur = this.items.length - 1;\n }\n }\n this.showMessage(this.cur);\n },\n\n async prevPage() {\n this.cur -= 1;\n if (this.cur === -1) {\n if (this.prev) {\n this.url = this.prev;\n await this.search();\n this.cur = this.items.length - 1;\n } else {\n this.cur = 0;\n }\n }\n this.showMessage(this.cur);\n },\n\n async search() {\n await _http__WEBPACK_IMPORTED_MODULE_0__[\"default\"].get(this.url).then((response) => {\n this.items = response.data.results;\n this.next = response.data.next;\n this.prev = response.data.previous;\n });\n for (let i = 0; i < this.items.length; i++) {\n const docId = this.items[i].id;\n _http__WEBPACK_IMPORTED_MODULE_0__[\"default\"].get(`docs/${docId}/annotations/`).then((response) => {\n this.annotations.push(response.data);\n });\n }\n },\n\n showMessage(index) {\n this.cur = index;\n },\n\n getState() {\n if (this.picked === 'all') {\n return '';\n }\n if (this.picked === 'active') {\n return 'true';\n }\n return 'false';\n },\n\n async submit() {\n const state = this.getState();\n this.url = `docs/?q=${this.searchQuery}&is_checked=${state}`;\n await this.search();\n this.cur = 0;\n },\n\n getTextColor(labelId) {\n for (let i = 0; i < this.labels.length; i++) {\n const label = this.labels[i];\n if (label.id === labelId) {\n return label.text_color;\n }\n }\n return '#ffffff';\n },\n\n getBgColor(labelId) {\n for (let i = 0; i < this.labels.length; i++) {\n const label = this.labels[i];\n if (label.id === labelId) {\n return label.background_color;\n }\n }\n return '#333333';\n },\n\n getLabelText(labelId) {\n for (let i = 0; i < this.labels.length; i++) {\n const label = this.labels[i];\n if (label.id === labelId) {\n return label.text;\n }\n }\n return 'NO';\n },\n\n removeLabel(label) {\n const docId = this.items[this.cur].id;\n _http__WEBPACK_IMPORTED_MODULE_0__[\"default\"].delete(`docs/${docId}/annotations/${label.id}`).then((response) => {\n const index = this.annotations[this.cur].indexOf(response.data);\n this.annotations[this.cur].splice(index, 1);\n });\n },\n },\n\n watch: {\n picked() {\n this.submit();\n },\n\n items() {\n // fetch progress info.\n _http__WEBPACK_IMPORTED_MODULE_0__[\"default\"].get('progress').then((response) => {\n this.total = response.data.total;\n this.remaining = response.data.remaining;\n });\n },\n },\n\n created() {\n _http__WEBPACK_IMPORTED_MODULE_0__[\"default\"].get('labels').then((response) => {\n this.labels = response.data;\n });\n this.submit();\n },\n\n computed: {\n achievement() {\n const done = this.total - this.remaining;\n const percentage = Math.round(done / this.total * 100);\n return this.total > 0 ? percentage : 0;\n },\n\n progressColor() {\n if (this.achievement < 30) {\n return 'is-danger';\n }\n if (this.achievement < 70) {\n return 'is-warning';\n }\n return 'is-primary';\n },\n },\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (annotationMixin);\n\n\n//# sourceURL=webpack:///./static/js/mixin.js?");
/***/ }),

2
app/server/static/bundle/sequence_labeling.js

@ -173,7 +173,7 @@ eval("__webpack_require__.r(__webpack_exports__);\naxios.defaults.xsrfCookieName
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _http_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./http.js */ \"./static/js/http.js\");\n\n\nvar annotationMixin = {\n data: function () {\n return {\n cur: 0,\n items: [{\n id: null,\n text: '',\n labels: []\n }],\n labels: [],\n guideline: 'Here is the Annotation Guideline Text',\n total: 0,\n remaining: 0,\n searchQuery: '',\n url: '',\n picked: 'all',\n }\n },\n methods: {\n nextPage: async function () {\n this.cur += 1;\n if (this.cur == this.items.length) {\n if (this.next) {\n this.url = this.next;\n await this.search();\n this.cur = 0;\n } else {\n this.cur = this.items.length - 1;\n }\n }\n this.showMessage(this.cur);\n },\n prevPage: async function () {\n this.cur -= 1;\n if (this.cur == -1) {\n if (this.prev) {\n this.url = this.prev;\n await this.search();\n this.cur = this.items.length - 1;\n } else {\n this.cur = 0;\n }\n }\n this.showMessage(this.cur);\n },\n search: async function () {\n await _http_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].get(this.url).then(response => {\n this.items = response.data['results'];\n this.next = response.data['next'];\n this.prev = response.data['previous'];\n })\n },\n showMessage: function (index) {\n this.cur = index;\n },\n getState: function () {\n if (this.picked == 'all') {\n return ''\n } else if (this.picked == 'active') {\n return 'true'\n } else {\n return 'false'\n }\n },\n submit: async function () {\n var state = this.getState();\n this.url = `docs/?q=${this.searchQuery}&is_checked=${state}`;\n await this.search();\n this.cur = 0;\n },\n deleteLabel: async function (index) {\n var doc_id = this.items[this.cur].id;\n var annotation_id = this.items[this.cur]['labels'][index].id;\n _http_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].delete(`docs/${doc_id}/annotations/${annotation_id}`).then(response => {\n this.items[this.cur]['labels'].splice(index, 1)\n })\n },\n\n removeLabel: function (label) {\n var doc_id = this.items[this.cur].id;\n _http_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].delete(`docs/${doc_id}/annotations/${label.id}`).then(response => {\n var index = this.items[this.cur]['labels'].indexOf(label)\n this.items[this.cur]['labels'].splice(index, 1)\n })\n }\n },\n watch: {\n picked: function (){\n this.submit();\n },\n items: function () {\n // fetch progress info.\n _http_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].get('progress').then(response => {\n this.total = response.data['total'];\n this.remaining = response.data['remaining'];\n })\n }\n },\n created: function () {\n _http_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].get('labels').then(response => {\n this.labels = response.data\n });\n this.submit();\n },\n computed: {\n achievement: function () {\n var done = this.total - this.remaining;\n var percentage = Math.round(done / this.total * 100);\n return this.total > 0 ? percentage : 0;\n },\n progressColor: function () {\n if (this.achievement < 30) {\n return 'is-danger'\n } else if (this.achievement < 70) {\n return 'is-warning'\n } else {\n return 'is-primary'\n }\n }\n }\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (annotationMixin);\n\n//# sourceURL=webpack:///./static/js/mixin.js?");
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _http__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./http */ \"./static/js/http.js\");\n\n\nconst annotationMixin = {\n data() {\n return {\n cur: 0,\n items: [{\n id: null,\n text: '',\n labels: [],\n }],\n labels: [],\n guideline: '',\n total: 0,\n remaining: 0,\n searchQuery: '',\n url: '',\n picked: 'all',\n annotations: [],\n };\n },\n\n methods: {\n async nextPage() {\n this.cur += 1;\n if (this.cur === this.items.length) {\n if (this.next) {\n this.url = this.next;\n await this.search();\n this.cur = 0;\n } else {\n this.cur = this.items.length - 1;\n }\n }\n this.showMessage(this.cur);\n },\n\n async prevPage() {\n this.cur -= 1;\n if (this.cur === -1) {\n if (this.prev) {\n this.url = this.prev;\n await this.search();\n this.cur = this.items.length - 1;\n } else {\n this.cur = 0;\n }\n }\n this.showMessage(this.cur);\n },\n\n async search() {\n await _http__WEBPACK_IMPORTED_MODULE_0__[\"default\"].get(this.url).then((response) => {\n this.items = response.data.results;\n this.next = response.data.next;\n this.prev = response.data.previous;\n });\n for (let i = 0; i < this.items.length; i++) {\n const docId = this.items[i].id;\n _http__WEBPACK_IMPORTED_MODULE_0__[\"default\"].get(`docs/${docId}/annotations/`).then((response) => {\n this.annotations.push(response.data);\n });\n }\n },\n\n showMessage(index) {\n this.cur = index;\n },\n\n getState() {\n if (this.picked === 'all') {\n return '';\n }\n if (this.picked === 'active') {\n return 'true';\n }\n return 'false';\n },\n\n async submit() {\n const state = this.getState();\n this.url = `docs/?q=${this.searchQuery}&is_checked=${state}`;\n await this.search();\n this.cur = 0;\n },\n\n getTextColor(labelId) {\n for (let i = 0; i < this.labels.length; i++) {\n const label = this.labels[i];\n if (label.id === labelId) {\n return label.text_color;\n }\n }\n return '#ffffff';\n },\n\n getBgColor(labelId) {\n for (let i = 0; i < this.labels.length; i++) {\n const label = this.labels[i];\n if (label.id === labelId) {\n return label.background_color;\n }\n }\n return '#333333';\n },\n\n getLabelText(labelId) {\n for (let i = 0; i < this.labels.length; i++) {\n const label = this.labels[i];\n if (label.id === labelId) {\n return label.text;\n }\n }\n return 'NO';\n },\n\n removeLabel(label) {\n const docId = this.items[this.cur].id;\n _http__WEBPACK_IMPORTED_MODULE_0__[\"default\"].delete(`docs/${docId}/annotations/${label.id}`).then((response) => {\n const index = this.annotations[this.cur].indexOf(response.data);\n this.annotations[this.cur].splice(index, 1);\n });\n },\n },\n\n watch: {\n picked() {\n this.submit();\n },\n\n items() {\n // fetch progress info.\n _http__WEBPACK_IMPORTED_MODULE_0__[\"default\"].get('progress').then((response) => {\n this.total = response.data.total;\n this.remaining = response.data.remaining;\n });\n },\n },\n\n created() {\n _http__WEBPACK_IMPORTED_MODULE_0__[\"default\"].get('labels').then((response) => {\n this.labels = response.data;\n });\n this.submit();\n },\n\n computed: {\n achievement() {\n const done = this.total - this.remaining;\n const percentage = Math.round(done / this.total * 100);\n return this.total > 0 ? percentage : 0;\n },\n\n progressColor() {\n if (this.achievement < 30) {\n return 'is-danger';\n }\n if (this.achievement < 70) {\n return 'is-warning';\n }\n return 'is-primary';\n },\n },\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (annotationMixin);\n\n\n//# sourceURL=webpack:///./static/js/mixin.js?");
/***/ }),

3
app/server/static/css/admin.css

@ -77,5 +77,4 @@
border-top-style: dashed;
align-items: center;
padding-top: .75rem;
}
}

4
app/server/static/js/.jsbeautifyrc

@ -0,0 +1,4 @@
{
"indent_size": 2,
"indent_char": " "
}

58
app/server/static/js/document_classification.js

@ -1,31 +1,41 @@
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';
var vm = new Vue({
el: '#mail-app',
delimiters: ['[[', ']]'],
mixins: [annotationMixin],
Vue.use(require('vue-shortkey'), {
prevent: ['input', 'textarea'],
});
methods: {
addLabel: async function (label_id) {
for (var i = 0; i < this.items[this.cur]['labels'].length; i++) {
var item = this.items[this.cur]['labels'][i];
if (label_id == item.label.id) {
this.deleteLabel(i);
return;
}
}
var payload = {
'label': label_id
};
const vm = new Vue({
el: '#mail-app',
delimiters: ['[[', ']]'],
mixins: [annotationMixin],
var doc_id = this.items[this.cur].id;
await HTTP.post(`docs/${doc_id}/annotations/`, payload).then(response => {
this.items[this.cur]['labels'].push(response.data);
})
methods: {
isIn(label) {
for (let i = 0; i < this.annotations[this.cur].length; i++) {
const a = this.annotations[this.cur][i];
if (a.label === label.id) {
return a;
}
}
}
return false;
},
async addLabel(label) {
const a = this.isIn(label);
if (a) {
this.removeLabel(a);
} else {
const docId = this.items[this.cur].id;
const payload = {
label: label.id,
};
await HTTP.post(`docs/${docId}/annotations/`, payload).then((response) => {
this.annotations[this.cur].push(response.data);
});
}
},
},
});

271
app/server/static/js/mixin.js

@ -1,125 +1,166 @@
import HTTP from './http.js';
var annotationMixin = {
data: function () {
return {
cur: 0,
items: [{
id: null,
text: '',
labels: []
}],
labels: [],
guideline: 'Here is the Annotation Guideline Text',
total: 0,
remaining: 0,
searchQuery: '',
url: '',
picked: 'all',
import HTTP from './http';
const annotationMixin = {
data() {
return {
cur: 0,
items: [{
id: null,
text: '',
labels: [],
}],
labels: [],
guideline: '',
total: 0,
remaining: 0,
searchQuery: '',
url: '',
picked: 'all',
annotations: [],
};
},
methods: {
async nextPage() {
this.cur += 1;
if (this.cur === this.items.length) {
if (this.next) {
this.url = this.next;
await this.search();
this.cur = 0;
} else {
this.cur = this.items.length - 1;
}
}
this.showMessage(this.cur);
},
methods: {
nextPage: async function () {
this.cur += 1;
if (this.cur == this.items.length) {
if (this.next) {
this.url = this.next;
await this.search();
this.cur = 0;
} else {
this.cur = this.items.length - 1;
}
}
this.showMessage(this.cur);
},
prevPage: async function () {
this.cur -= 1;
if (this.cur == -1) {
if (this.prev) {
this.url = this.prev;
await this.search();
this.cur = this.items.length - 1;
} else {
this.cur = 0;
}
}
this.showMessage(this.cur);
},
search: async function () {
await HTTP.get(this.url).then(response => {
this.items = response.data['results'];
this.next = response.data['next'];
this.prev = response.data['previous'];
})
},
showMessage: function (index) {
this.cur = index;
},
getState: function () {
if (this.picked == 'all') {
return ''
} else if (this.picked == 'active') {
return 'true'
} else {
return 'false'
}
},
submit: async function () {
var state = this.getState();
this.url = `docs/?q=${this.searchQuery}&is_checked=${state}`;
await this.search();
this.cur = 0;
},
deleteLabel: async function (index) {
var doc_id = this.items[this.cur].id;
var annotation_id = this.items[this.cur]['labels'][index].id;
HTTP.delete(`docs/${doc_id}/annotations/${annotation_id}`).then(response => {
this.items[this.cur]['labels'].splice(index, 1)
})
},
removeLabel: function (label) {
var doc_id = this.items[this.cur].id;
HTTP.delete(`docs/${doc_id}/annotations/${label.id}`).then(response => {
var index = this.items[this.cur]['labels'].indexOf(label)
this.items[this.cur]['labels'].splice(index, 1)
})
async prevPage() {
this.cur -= 1;
if (this.cur === -1) {
if (this.prev) {
this.url = this.prev;
await this.search();
this.cur = this.items.length - 1;
} else {
this.cur = 0;
}
}
this.showMessage(this.cur);
},
async search() {
await HTTP.get(this.url).then((response) => {
this.items = response.data.results;
this.next = response.data.next;
this.prev = response.data.previous;
});
for (let i = 0; i < this.items.length; i++) {
const docId = this.items[i].id;
HTTP.get(`docs/${docId}/annotations/`).then((response) => {
this.annotations.push(response.data);
});
}
},
showMessage(index) {
this.cur = index;
},
watch: {
picked: function (){
this.submit();
},
items: function () {
// fetch progress info.
HTTP.get('progress').then(response => {
this.total = response.data['total'];
this.remaining = response.data['remaining'];
})
getState() {
if (this.picked === 'all') {
return '';
}
if (this.picked === 'active') {
return 'true';
}
return 'false';
},
async submit() {
const state = this.getState();
this.url = `docs/?q=${this.searchQuery}&is_checked=${state}`;
await this.search();
this.cur = 0;
},
getTextColor(labelId) {
for (let i = 0; i < this.labels.length; i++) {
const label = this.labels[i];
if (label.id === labelId) {
return label.text_color;
}
}
return '#ffffff';
},
created: function () {
HTTP.get('labels').then(response => {
this.labels = response.data
});
this.submit();
getBgColor(labelId) {
for (let i = 0; i < this.labels.length; i++) {
const label = this.labels[i];
if (label.id === labelId) {
return label.background_color;
}
}
return '#333333';
},
computed: {
achievement: function () {
var done = this.total - this.remaining;
var percentage = Math.round(done / this.total * 100);
return this.total > 0 ? percentage : 0;
},
progressColor: function () {
if (this.achievement < 30) {
return 'is-danger'
} else if (this.achievement < 70) {
return 'is-warning'
} else {
return 'is-primary'
}
getLabelText(labelId) {
for (let i = 0; i < this.labels.length; i++) {
const label = this.labels[i];
if (label.id === labelId) {
return label.text;
}
}
}
return 'NO';
},
removeLabel(label) {
const docId = this.items[this.cur].id;
HTTP.delete(`docs/${docId}/annotations/${label.id}`).then((response) => {
const index = this.annotations[this.cur].indexOf(response.data);
this.annotations[this.cur].splice(index, 1);
});
},
},
watch: {
picked() {
this.submit();
},
items() {
// fetch progress info.
HTTP.get('progress').then((response) => {
this.total = response.data.total;
this.remaining = response.data.remaining;
});
},
},
created() {
HTTP.get('labels').then((response) => {
this.labels = response.data;
});
this.submit();
},
computed: {
achievement() {
const done = this.total - this.remaining;
const percentage = Math.round(done / this.total * 100);
return this.total > 0 ? percentage : 0;
},
progressColor() {
if (this.achievement < 30) {
return 'is-danger';
}
if (this.achievement < 70) {
return 'is-warning';
}
return 'is-primary';
},
},
};
export default annotationMixin;
export default annotationMixin;

2
app/server/templates/annotation/annotation_base.html

@ -51,7 +51,7 @@
<a href="#" class="item" v-for="(msg, index) in items" v-bind:class="{ active: index == cur }" v-on:click="showMessage(index)"
v-bind:data-preview-id="index">
<span class="icon">
<i class="fa fa-check" v-if="msg.labels.length"></i>
<i class="fa fa-check" v-show="annotations[index] && annotations[index].length"></i>
</span>
<span class="name">[[ msg.text.slice(0, 40) ]]...</span>
</a>

17
app/server/templates/annotation/document_classification.html

@ -10,9 +10,9 @@
<div class="tags has-addons">
<a class="tag is-medium"
v-bind:style="{ color: label.text_color, backgroundColor: label.background_color }"
v-on:click="addLabel(label.id)"
v-on:click="addLabel(label)"
v-shortkey.once="[ label.shortcut ]"
@shortkey="addLabel(label.id)">
@shortkey="addLabel(label)">
[[ label.text ]]
</a>
<span class="tag is-medium">[[ label.shortcut ]]</span>
@ -22,20 +22,19 @@
</div>
</header>
<div class="card-content" v-if="items.length">
<div class="card-content">
<div class="field is-grouped is-grouped-multiline">
<div class="control" v-for="(annotation, index) in items[cur].labels">
<div class="control" v-for="(annotation, index) in annotations[cur]">
<div class="tags has-addons">
<span class="tag is-medium"
v-bind:style="{ color: annotation.label.text_color, backgroundColor: annotation.label.background_color }">
[[ annotation.label.text ]]
<button class="delete is-small" v-on:click="deleteLabel(index)"></button>
v-bind:style="{ color: getTextColor(annotation.label), 'background-color': getBgColor(annotation.label) }">
[[ getLabelText(annotation.label) ]]
<button class="delete is-small" v-on:click="removeLabel(annotation)"></button>
</span>
<span class="tag is-primary" v-if="annotation.label.prob">[[ annotation.label.prob ]]</span>
</div>
</div>
</div>
<hr v-if="items[cur].labels.length">
<hr>
<div class="content">
[[ items[cur].text ]]
</div>

Loading…
Cancel
Save