diff --git a/app/api/exceptions.py b/app/api/exceptions.py index 02adb1d0..dce31684 100644 --- a/app/api/exceptions.py +++ b/app/api/exceptions.py @@ -10,3 +10,8 @@ class FileParseException(APIException): def __init__(self, line_num, line, code=None): detail = self.default_detail.format(line_num, line) super().__init__(detail, code) + + +class AutoLabelingException(APIException): + status_code = status.HTTP_400_BAD_REQUEST + default_detail = 'Auto labeling not allowed for the document with labels.' diff --git a/app/api/views.py b/app/api/views.py index 9a38ca23..7deb01a9 100644 --- a/app/api/views.py +++ b/app/api/views.py @@ -25,6 +25,7 @@ from rest_framework.views import APIView from rest_framework.parsers import MultiPartParser from rest_framework_csv.renderers import CSVRenderer +from .exceptions import AutoLabelingException from .filters import DocumentFilter from .models import Project, Label, Document, RoleMapping, Role, Comment, AutoLabelingConfig from .permissions import IsProjectAdmin, IsAnnotatorAndReadOnly, IsAnnotator, IsAnnotationApproverAndReadOnly, IsOwnAnnotation, IsAnnotationApprover, IsOwnComment @@ -595,6 +596,9 @@ class AutoLabelingAnnotation(generics.CreateAPIView): return queryset def create(self, request, *args, **kwargs): + queryset = self.get_queryset() + if queryset.exists(): + raise AutoLabelingException() labels = self.extract() labels = self.transform(labels) serializer = self.get_serializer(data=labels, many=True) @@ -609,7 +613,7 @@ class AutoLabelingAnnotation(generics.CreateAPIView): def extract(self): project = get_object_or_404(Project, pk=self.kwargs['project_id']) doc = get_object_or_404(Document, pk=self.kwargs['doc_id']) - config = project.auto_labeling_config.get(default=True) + config = project.auto_labeling_config.first() task = TaskFactory.create(project.project_type) model = RequestModelFactory.create( model_name=config.model_name, diff --git a/frontend/components/containers/annotation/Settings.vue b/frontend/components/containers/annotation/Settings.vue new file mode 100644 index 00000000..0c2db177 --- /dev/null +++ b/frontend/components/containers/annotation/Settings.vue @@ -0,0 +1,70 @@ + + + diff --git a/frontend/layouts/annotation.vue b/frontend/layouts/annotation.vue index b964b4ec..2941594c 100644 --- a/frontend/layouts/annotation.vue +++ b/frontend/layouts/annotation.vue @@ -41,6 +41,7 @@ + @@ -84,6 +85,7 @@ import CommentButton from '@/components/containers/annotation/CommentButton' import Pagination from '~/components/containers/annotation/Pagination' import TheHeader from '~/components/organisms/layout/TheHeader' import TheSideBar from '~/components/organisms/layout/TheSideBar' +import Settings from '~/components/containers/annotation/Settings.vue' export default { middleware: ['check-auth', 'auth', 'set-project'], @@ -98,7 +100,8 @@ export default { ApproveButton, MetadataBox, ClearAnnotationsButton, - CommentButton + CommentButton, + Settings }, fetch() { @@ -115,7 +118,10 @@ export default { data() { return { drawerLeft: null, - limit: 10 + limit: 10, + options: { + onAutoLabeling: false + } } }, @@ -187,16 +193,24 @@ export default { current: { handler() { this.setCurrent(this.current) + if (this.options.onAutoLabeling) { + this.autoLabeling({ projectId: this.$route.params.id }) + } }, immediate: true }, searchOptions() { this.saveSearchOptions(JSON.parse(this.searchOptions)) + }, + "options.onAutoLabeling": function(val) { + if (val) { + this.autoLabeling({ projectId: this.$route.params.id }) + } } }, methods: { - ...mapActions('documents', ['getDocumentList']), + ...mapActions('documents', ['getDocumentList', 'autoLabeling']), ...mapMutations('documents', ['setCurrent']), ...mapMutations('projects', ['saveSearchOptions']) } diff --git a/frontend/services/annotation.service.js b/frontend/services/annotation.service.js index fa29d6db..c87a4d02 100644 --- a/frontend/services/annotation.service.js +++ b/frontend/services/annotation.service.js @@ -24,6 +24,10 @@ class AnnotationService { updateAnnotation(projectId, docId, annotationId, payload) { return this.request.patch(`/projects/${projectId}/docs/${docId}/annotations/${annotationId}`, payload) } + + autoLabel(projectId, docId) { + return this.request.post(`/projects/${projectId}/docs/${docId}/auto-labeling`) + } } export default new AnnotationService() diff --git a/frontend/store/documents.js b/frontend/store/documents.js index 79220f52..49cd1fbd 100644 --- a/frontend/store/documents.js +++ b/frontend/store/documents.js @@ -64,6 +64,9 @@ export const mutations = { addAnnotation(state, payload) { state.items[state.current].annotations.push(payload) }, + setAnnotations(state, payload) { + state.items[state.current].annotations = payload + }, deleteAnnotation(state, annotationId) { state.items[state.current].annotations = state.items[state.current].annotations.filter(item => item.id !== annotationId) }, @@ -263,5 +266,21 @@ export const actions = { .catch((error) => { alert(error) }) - } + }, + autoLabeling({ commit, state }, payload) { + const document = state.items[state.current] + if (document) { + commit('setLoading', true) + AnnotationService.autoLabel(payload.projectId, document.id) + .then((response) => { + commit('setAnnotations', response.data) + }) + .catch((error) => { + console.log(error) + }) + .finally(() => { + commit('setLoading', false) + }) + } + }, }