Browse Source

Add clear annotations and bulk delete functionality

pull/1115/head
Prab Dhaliwal 4 years ago
parent
commit
8e8e6f1fd0
10 changed files with 157 additions and 13 deletions
  1. 11
      app/api/views.py
  2. 41
      frontend/components/containers/annotation/ClearAnnotationsButton.vue
  3. 25
      frontend/components/containers/annotation/EntityItemBox.vue
  4. 51
      frontend/components/containers/documents/DocumentBulkDeletionButton.vue
  5. 1
      frontend/i18n/en/generic.js
  6. 2
      frontend/i18n/en/projects/dataset.js
  7. 5
      frontend/pages/projects/_id/dataset/index.vue
  8. 4
      frontend/services/annotation.service.js
  9. 4
      frontend/services/document.service.js
  10. 26
      frontend/store/documents.js

11
app/api/views.py

@ -184,6 +184,12 @@ class DocumentList(generics.ListCreateAPIView):
project = get_object_or_404(Project, pk=self.kwargs['project_id'])
serializer.save(project=project)
def delete(self, request, *args, **kwargs):
project = get_object_or_404(Project, pk=self.kwargs['project_id'])
queryset = project.documents
queryset.all().delete()
return Response(status=status.HTTP_204_NO_CONTENT)
class DocumentDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Document.objects.all()
@ -220,6 +226,11 @@ class AnnotationList(generics.ListCreateAPIView):
def perform_create(self, serializer):
serializer.save(document_id=self.kwargs['doc_id'], user=self.request.user)
def delete(self, request, *args, **kwargs):
queryset = self.get_queryset()
queryset.all().delete()
return Response(status=status.HTTP_204_NO_CONTENT)
@staticmethod
def check_single_class_classification(project_id, doc_id, user):

41
frontend/components/containers/annotation/ClearAnnotationsButton.vue

@ -0,0 +1,41 @@
<template>
<div>
<v-btn
:disabled="false"
class="text-capitalize"
outlined
@click="handleClear()"
>
{{ "Clear Annotations" }}
</v-btn>
</div>
</template>
<script>
import { mapState, mapActions } from 'vuex'
export default {
components: {
},
data() {
return {
dialog: false
}
},
computed: {
...mapState('documents', ['selected'])
},
methods: {
...mapActions('documents', ['clearAnnotations']),
handleClear() {
const projectId = this.$route.params.id
this.clearAnnotations(projectId)
}
}
}
</script>

25
frontend/components/containers/annotation/EntityItemBox.vue

@ -1,22 +1,27 @@
<template>
<entity-item-box
v-if="isReady"
:labels="items"
:text="currentDoc.text"
:entities="currentDoc.annotations"
:delete-annotation="removeEntity"
:update-entity="updateEntity"
:add-entity="addEntity"
/>
<div>
<clear-annotations-button />
<entity-item-box
v-if="isReady"
:labels="items"
:text="currentDoc.text"
:entities="currentDoc.annotations"
:delete-annotation="removeEntity"
:update-entity="updateEntity"
:add-entity="addEntity"
/>
</div>
</template>
<script>
import { mapActions, mapGetters, mapState } from 'vuex'
import ClearAnnotationsButton from '@/components/containers/annotation/ClearAnnotationsButton.vue'
import EntityItemBox from '~/components/organisms/annotation/EntityItemBox'
export default {
components: {
EntityItemBox
EntityItemBox,
ClearAnnotationsButton
},
computed: {

51
frontend/components/containers/documents/DocumentBulkDeletionButton.vue

@ -0,0 +1,51 @@
<template>
<div>
<v-btn
:disabled="!total"
class="text-capitalize"
outlined
@click="dialog=true"
>
{{ $t('generic.deleteAll') }}
</v-btn>
<v-dialog
v-model="dialog"
width="800"
>
<confirm-form
:title="$t('dataset.deleteBulkDocumentsTitle')"
:message="$t('dataset.deleteBulkDocumentsMessage')"
:button-true-text="$t('generic.yes')"
:button-false-text="$t('generic.cancel')"
item-key="text"
@ok="deleteAllDocuments($route.params.id);dialog=false"
@cancel="dialog=false"
/>
</v-dialog>
</div>
</template>
<script>
import { mapState, mapActions } from 'vuex'
import ConfirmForm from '@/components/organisms/utils/ConfirmForm'
export default {
components: {
ConfirmForm
},
data() {
return {
dialog: false
}
},
computed: {
...mapState('documents', ['total'])
},
methods: {
...mapActions('documents', ['deleteAllDocuments'])
}
}
</script>

1
frontend/i18n/en/generic.js

@ -10,6 +10,7 @@ export default {
upload: 'Upload',
add: 'Add',
delete: 'Delete',
deleteAll: 'Delete All',
search: 'Search',
name: 'Name',
import: 'Import',

2
frontend/i18n/en/projects/dataset.js

@ -15,5 +15,7 @@ export default {
exportDataMessage: 'Select a file format',
deleteDocumentsTitle: 'Delete Document',
deleteDocumentsMessage: 'Are you sure you want to delete these documents from this project?',
deleteBulkDocumentsTitle: 'Delete All Documents',
deleteBulkDocumentsMessage: 'Are you sure you want to delete all documents from this project?',
pageText: '{0}-{1} of {2}'
}

5
frontend/pages/projects/_id/dataset/index.vue

@ -3,6 +3,7 @@
<v-card-title class="mb-2">
<document-action-menu />
<document-deletion-button class="ms-2" />
<document-bulk-deletion-button class="ms-2" />
</v-card-title>
<document-list />
</v-card>
@ -12,6 +13,7 @@
import DocumentList from '@/components/containers/documents/DocumentList'
import DocumentActionMenu from '@/components/containers/documents/DocumentActionMenu'
import DocumentDeletionButton from '@/components/containers/documents/DocumentDeletionButton'
import DocumentBulkDeletionButton from '@/components/containers/documents/DocumentBulkDeletionButton'
export default {
layout: 'project',
@ -19,7 +21,8 @@ export default {
components: {
DocumentList,
DocumentActionMenu,
DocumentDeletionButton
DocumentDeletionButton,
DocumentBulkDeletionButton
},
validate({ params, query }) {

4
frontend/services/annotation.service.js

@ -17,6 +17,10 @@ class AnnotationService {
return this.request.delete(`/projects/${projectId}/docs/${docId}/annotations/${annotationId}`)
}
clearAnnotations(projectId, docid) {
return this.request.delete(`/projects/${projectId}/docs/${docid}/annotations`)
}
updateAnnotation(projectId, docId, annotationId, payload) {
return this.request.patch(`/projects/${projectId}/docs/${docId}/annotations/${annotationId}`, payload)
}

4
frontend/services/document.service.js

@ -13,6 +13,10 @@ class DocumentService {
return this.request.post(`/projects/${projectId}/docs`, payload)
}
deleteAllDocuments(projectId) {
return this.request.delete(`/projects/${projectId}/docs`)
}
deleteDocument(projectId, docId) {
return this.request.delete(`/projects/${projectId}/docs/${docId}`)
}

26
frontend/store/documents.js

@ -31,7 +31,6 @@ export const getters = {
return state.items[state.current]
}
}
export const mutations = {
setCurrent(state, payload) {
state.current = payload
@ -67,6 +66,9 @@ export const mutations = {
deleteAnnotation(state, annotationId) {
state.items[state.current].annotations = state.items[state.current].annotations.filter(item => item.id !== annotationId)
},
clearAnnotations(state) {
state.items[state.current].annotations = []
},
updateAnnotation(state, payload) {
const item = state.items[state.current].annotations.find(item => item.id === payload.id)
Object.assign(item, payload)
@ -88,7 +90,6 @@ export const mutations = {
export const actions = {
getDocumentList({ commit, state }, payload) {
commit('setLoading', true)
// payload = Object.assign(payload, state.searchOptions)
return DocumentService.getDocumentList(payload)
.then((response) => {
commit('setDocumentList', response.data.results)
@ -146,6 +147,17 @@ export const actions = {
alert(error)
})
},
deleteAllDocuments({ commit, state }, projectId) {
DocumentService.deleteAllDocuments(projectId)
.then((response) => {
commit('setDocumentList', [])
commit('setTotalItems', 0)
commit('resetSelected')
})
.catch((error) => {
alert(error)
})
},
deleteDocument({ commit, state }, projectId) {
for (const document of state.selected) {
DocumentService.deleteDocument(projectId, document.id)
@ -188,6 +200,16 @@ export const actions = {
alert(error)
})
},
clearAnnotations({ commit, state }, projectId) {
const documentId = state.items[state.current].id
AnnotationService.clearAnnotations(projectId, documentId)
.then((response) => {
commit('clearAnnotations')
})
.catch((error) => {
alert(error)
})
},
approve({ commit, getters }, payload) {
const documentId = getters.currentDoc.id
const data = {

Loading…
Cancel
Save