diff --git a/backend/api/tests/api/test_statistics.py b/backend/api/tests/api/test_statistics.py index 352816da..ab8a81b5 100644 --- a/backend/api/tests/api/test_statistics.py +++ b/backend/api/tests/api/test_statistics.py @@ -1,11 +1,13 @@ from django.conf import settings from django.contrib.auth.models import User from model_mommy import mommy +from rest_framework import status from rest_framework.reverse import reverse from rest_framework.test import APITestCase from ...models import DOCUMENT_CLASSIFICATION, Example -from .utils import (TestUtilsMixin, assign_user_to_role, create_default_roles, +from .utils import (CRUDMixin, TestUtilsMixin, assign_user_to_role, + create_default_roles, make_doc, prepare_project, remove_all_role_mappings) @@ -73,3 +75,23 @@ class TestStatisticsAPI(APITestCase, TestUtilsMixin): password=self.super_user_pass) response = self.client.get(f'{self.url}?include=user', format='json') self.assertEqual(list(response.data.keys()), ['user']) + + +class TestMemberProgress(CRUDMixin): + + def setUp(self): + self.project = prepare_project(DOCUMENT_CLASSIFICATION) + self.example = make_doc(self.project.item) + self.url = reverse(viewname='member_progress', args=[self.project.item.id]) + + def test_fetch_initial_progress(self): + response = self.assert_fetch(self.project.users[0], status.HTTP_200_OK) + expected_progress = {user.username: 0 for user in self.project.users} + self.assertEqual(response.data, {'total': 1, 'progress': expected_progress}) + + def test_fetch_progress(self): + mommy.make('ExampleState', example=self.example, confirmed_by=self.project.users[0]) + response = self.assert_fetch(self.project.users[0], status.HTTP_200_OK) + expected_progress = {user.username: 0 for user in self.project.users} + expected_progress[self.project.users[0].username] = 1 + self.assertEqual(response.data, {'total': 1, 'progress': expected_progress}) diff --git a/backend/api/urls.py b/backend/api/urls.py index 2142170b..14fc5686 100644 --- a/backend/api/urls.py +++ b/backend/api/urls.py @@ -30,22 +30,18 @@ urlpatterns_project = [ path( route='statistics', view=statistics.StatisticsAPI.as_view(), - name='statistics'), - # path( - # route='labels', - # view=label.LabelList.as_view(), - # name='label_list' - # ), - # path( - # route='label-upload', - # view=label.LabelUploadAPI.as_view(), - # name='label_upload' - # ), - # path( - # route='labels/', - # view=label.LabelDetail.as_view(), - # name='label_detail' - # ), + name='statistics' + ), + path( + route='progress', + view=statistics.ProgressAPI.as_view(), + name='progress' + ), + path( + route='member-progress', + view=statistics.MemberProgressAPI.as_view(), + name='member_progress' + ), path( route='category-types', view=label.DocTypeList.as_view(), diff --git a/backend/api/views/statistics.py b/backend/api/views/statistics.py index bb913df0..1bfa65bc 100644 --- a/backend/api/views/statistics.py +++ b/backend/api/views/statistics.py @@ -3,6 +3,7 @@ import abc from django.conf import settings from django.db.models import Count from django.shortcuts import get_object_or_404 +from rest_framework import status from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework.views import APIView @@ -42,10 +43,11 @@ class StatisticsAPI(APIView): return Response(response) def progress(self): + project = get_object_or_404(Project, pk=self.kwargs['project_id']) examples = Example.objects.filter(project=self.kwargs['project_id']).values('id') total = examples.count() done = ExampleState.objects.count_done(examples) - done_by_user = ExampleState.objects.count_user(examples) + done_by_user = ExampleState.objects.measure_member_progress(examples, project.users.all()) remaining = total - done return {'total': total, 'remaining': remaining, 'user': done_by_user} @@ -69,14 +71,25 @@ class StatisticsAPI(APIView): class ProgressAPI(APIView): + permission_classes = [IsAuthenticated & IsInProjectReadOnlyOrAdmin] def get(self, request, *args, **kwargs): examples = Example.objects.filter(project=self.kwargs['project_id']).values('id') total = examples.count() - done = ExampleState.objects.count_done(examples) + done = ExampleState.objects.count_done(examples, user=self.request.user) return {'total': total, 'remaining': total - done} +class MemberProgressAPI(APIView): + permission_classes = [IsAuthenticated & IsInProjectReadOnlyOrAdmin] + + def get(self, request, *args, **kwargs): + project = get_object_or_404(Project, pk=self.kwargs['project_id']) + examples = Example.objects.filter(project=self.kwargs['project_id']).values('id') + data = ExampleState.objects.measure_member_progress(examples, project.users.all()) + return Response(data=data, status=status.HTTP_200_OK) + + class LabelFrequency(abc.ABC, APIView): permission_classes = [IsAuthenticated & IsInProjectReadOnlyOrAdmin] model = Annotation