diff --git a/Pipfile b/Pipfile index 9e887c66..bacbd998 100644 --- a/Pipfile +++ b/Pipfile @@ -52,3 +52,4 @@ isort = "isort . -c" wait_for_db = "python manage.py wait_for_db" test = "python manage.py test api.tests" migrate = "python manage.py migrate" +collectstatic = "python manage.py collectstatic --noinput" diff --git a/README.md b/README.md index f9ffeddb..ac5c73e9 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,14 @@ $ docker-compose -f docker-compose.dev.yml up Go to . + +Run Backend API-Tests: + +You can run the API-Tests for the backend with the following command: +```bash +docker exec doccano_backend_1 pipenv run app/manage.py test api +``` + ### Add annotators (optionally) If you want to add annotators/annotation approvers, see [Frequently Asked Questions](./docs/faq.md) diff --git a/app/server/static/components/annotation.pug b/app/server/static/components/annotation.pug index 9101db8c..6206b540 100644 --- a/app/server/static/components/annotation.pug +++ b/app/server/static/components/annotation.pug @@ -106,28 +106,11 @@ div.columns(v-cloak="") ) section.modal-card-body.modal-card-body-footer vue-json-pretty( - v-bind:data="documentMetadata" + v-bind:data="displayDocumentMetadata" v-bind:show-double-quotes="false" v-bind:show-line="false" ) - div.modal(v-bind:class="{ 'is-active': isCommentActive }") - div.modal-background - div.modal-card - header.modal-card-head - p.modal-card-title Document Comment - button.delete( - v-on:click="toggleCommentModal()" - aria-label="close" - ) - section.modal-card-body.modal-card-body-footer - textarea.textarea( - v-model="comment" - v-debounce="syncComment" - type="text" - placeholder="Add document comment here..." - ) - div.columns.is-multiline.is-gapless.is-mobile.is-vertical-center div.column.is-3 progress.progress.is-inline-block( @@ -135,7 +118,7 @@ div.columns(v-cloak="") v-bind:value="achievement" max="100" ) 30% - div.column.is-5 + div.column.is-6 span.ml10 strong {{ total - remaining }} | / @@ -161,13 +144,6 @@ div.columns(v-cloak="") ) span.icon i.fas.fa-box - div.column.is-1.has-text-right - a.button.tooltip.is-tooltip-bottom( - v-on:click="toggleCommentModal()" - v-bind:data-tooltip="'Click to comment on document.'" - ) - span.icon - i.fas.fa-comment div.columns div.column diff --git a/app/server/static/components/annotationMixin.js b/app/server/static/components/annotationMixin.js index 5bb29ea1..d8e41d11 100644 --- a/app/server/static/components/annotationMixin.js +++ b/app/server/static/components/annotationMixin.js @@ -88,53 +88,18 @@ export default { offset: getOffsetFromUrl(window.location.href), picked: 'all', ordering: '', - comments: [], - comment: '', count: 0, prevLimit: 0, paginationPages: 0, paginationPage: 0, singleClassClassification: false, isAnnotationApprover: false, - isCommentActive: false, isMetadataActive: false, isAnnotationGuidelineActive: false, }; }, methods: { - async syncComment(text) { - const docId = this.docs[this.pageNumber].id; - const commentId = this.comments[this.pageNumber].id; - const hasText = text.trim().length > 0; - - if (commentId && !hasText) { - await HTTP.delete(`docs/${docId}/comments/${commentId}`); - const comments = this.comments.slice(); - comments[this.pageNumber] = { text: '', id: null }; - this.comments = comments; - } else if (commentId && hasText) { - await HTTP.patch(`docs/${docId}/comments/${commentId}`, { text }); - const comments = this.comments.slice(); - comments[this.pageNumber].text = text; - this.comments = comments; - } else { - const response = await HTTP.post(`docs/${docId}/comments`, { text }); - const comments = this.comments.slice(); - comments[this.pageNumber] = response.data; - this.comments = comments; - } - }, - - async toggleCommentModal() { - if (this.isCommentActive) { - this.isCommentActive = false; - return; - } - - this.comment = this.comments[this.pageNumber].text; - this.isCommentActive = true; - }, resetScrollbar() { const textbox = this.$refs.textbox; @@ -278,20 +243,9 @@ export default { }); }, - async fetchComments() { - const responses = await Promise.all(this.docs.map(doc => HTTP.get(`docs/${doc.id}/comments`))); - this.comments = responses.map(response => response.data.results[0] || { text: '', id: null }); - }, }, watch: { - pageNumber() { - this.comment = this.comments[this.pageNumber].text; - }, - - docs() { - this.fetchComments(); - }, picked() { this.submit(); @@ -336,7 +290,13 @@ export default { }, compiledMarkdown() { - return marked(this.guideline, { + const documentMetadata = this.documentMetadata; + + const guideline = documentMetadata && documentMetadata.guideline + ? documentMetadata.guideline + : this.guideline; + + return marked(guideline, { sanitize: true, }); }, @@ -354,6 +314,18 @@ export default { : 'Click to approve annotations'; }, + displayDocumentMetadata() { + let documentMetadata = this.documentMetadata; + if (documentMetadata == null) { + return null; + } + + documentMetadata = { ...documentMetadata }; + delete documentMetadata.guideline; + delete documentMetadata.documentSourceUrl; + return documentMetadata; + }, + documentMetadata() { return this.documentMetadataFor(this.pageNumber); }, diff --git a/docs/project_structure.md b/docs/project_structure.md index c7615f97..4690e196 100644 --- a/docs/project_structure.md +++ b/docs/project_structure.md @@ -16,11 +16,11 @@ Consider them: **[app/](https://github.com/doccano/doccano/tree/master/app)** -The `app/api` directory contains backend code. See [below](#Backend). +The `app/` directory contains backend code. See [below](#Backend). **[frontend/](https://github.com/doccano/doccano/tree/master/frontend)** -The `app/api` directory contains frontend code. See [below](#Frontend). +The `frontend/` directory contains frontend code. See [below](#Frontend). **[docker-compose.dev.yml](https://github.com/doccano/doccano/blob/master/docker-compose.dev.yml)** diff --git a/frontend/components/containers/comments/Comment.vue b/frontend/components/containers/comments/Comment.vue new file mode 100644 index 00000000..0424e05d --- /dev/null +++ b/frontend/components/containers/comments/Comment.vue @@ -0,0 +1,99 @@ + + + diff --git a/frontend/components/containers/comments/CommentSection.vue b/frontend/components/containers/comments/CommentSection.vue new file mode 100644 index 00000000..d8ab1eaa --- /dev/null +++ b/frontend/components/containers/comments/CommentSection.vue @@ -0,0 +1,114 @@ + + + diff --git a/frontend/components/containers/documents/DocumentList.vue b/frontend/components/containers/documents/DocumentList.vue index ded182fe..baa2a54c 100644 --- a/frontend/components/containers/documents/DocumentList.vue +++ b/frontend/components/containers/documents/DocumentList.vue @@ -42,6 +42,9 @@ + + + diff --git a/frontend/pages/projects/_id/settings/index.vue b/frontend/pages/projects/_id/settings/index.vue new file mode 100644 index 00000000..e2f7974b --- /dev/null +++ b/frontend/pages/projects/_id/settings/index.vue @@ -0,0 +1,225 @@ + + + diff --git a/frontend/rules/index.js b/frontend/rules/index.js index 3f5219b3..edaad7e8 100644 --- a/frontend/rules/index.js +++ b/frontend/rules/index.js @@ -57,7 +57,7 @@ export const fileFormatRules = (msg) => { export const uploadFileRules = (msg) => { return [ v => !!v || msg.fileRequired, - v => !v || v.size < 1000000 || msg.fileLessThan1MB + v => !v || v.some(file => file.size < 100000000) || msg.fileLessThan1MB ] } diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 6fefd772..e2e59391 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -1946,6 +1946,16 @@ lodash "^4.17.15" pretty "^2.0.0" +"@vuejs-community/vue-filter-date-format@^1.6.3": + version "1.6.3" + resolved "https://registry.yarnpkg.com/@vuejs-community/vue-filter-date-format/-/vue-filter-date-format-1.6.3.tgz#10a9b11425f4288f3ebc14c79c7de29322dafec7" + integrity sha512-fUjAAI/1qzJPR6AYoK00TBA6/aRYKTXjLY/rSYsWV4G5nwywKfrpOYOJi5exWyzozohyV6nrzliDlWcl32+IPg== + +"@vuejs-community/vue-filter-date-parse@^1.1.6": + version "1.1.6" + resolved "https://registry.yarnpkg.com/@vuejs-community/vue-filter-date-parse/-/vue-filter-date-parse-1.1.6.tgz#8679a990af0f74b24c58d210ff2341e5b884a059" + integrity sha512-OzeiL5wrq+5+sw9hJfcfaIxcG953lpe37Lf0JnRKzVvfBRTHX2t8SIVxtDmgLhSGoGx9B4bGbpv4NaIqeEofXA== + "@webassemblyjs/ast@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" diff --git a/nginx/nginx.conf b/nginx/nginx.conf index 3d482f4c..22ac7d7f 100644 --- a/nginx/nginx.conf +++ b/nginx/nginx.conf @@ -1,7 +1,7 @@ server { listen 80; charset utf-8; - + client_max_body_size 100M; add_header X-Frame-Options DENY; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block"; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..f17ed285 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,16 @@ +{ + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "@vuejs-community/vue-filter-date-format": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@vuejs-community/vue-filter-date-format/-/vue-filter-date-format-1.6.3.tgz", + "integrity": "sha512-fUjAAI/1qzJPR6AYoK00TBA6/aRYKTXjLY/rSYsWV4G5nwywKfrpOYOJi5exWyzozohyV6nrzliDlWcl32+IPg==" + }, + "@vuejs-community/vue-filter-date-parse": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@vuejs-community/vue-filter-date-parse/-/vue-filter-date-parse-1.1.6.tgz", + "integrity": "sha512-OzeiL5wrq+5+sw9hJfcfaIxcG953lpe37Lf0JnRKzVvfBRTHX2t8SIVxtDmgLhSGoGx9B4bGbpv4NaIqeEofXA==" + } + } +}