From 2e740ea7ef4c810af2699bc77203c49e163c887b Mon Sep 17 00:00:00 2001 From: Durim Morina Date: Mon, 8 Jan 2018 10:55:32 -0800 Subject: [PATCH 1/3] added payments docs and refactoring --- csp/urls.py | 25 ++++---- static/js/crowdsource.routes.js | 13 +++++ static/js/payment/services/payment.service.js | 2 +- .../controllers/project-review.controller.js | 2 +- static/js/project/services/project.service.js | 10 ++-- static/js/task/services/task.service.js | 2 +- .../js/template/services/template.service.js | 6 +- static/templates/docs/navigation.html | 2 +- static/templates/docs/payments.html | 57 +++++++++++++++++++ 9 files changed, 96 insertions(+), 23 deletions(-) create mode 100644 static/templates/docs/payments.html diff --git a/csp/urls.py b/csp/urls.py index 46d9ed2c2..d751ffa0b 100644 --- a/csp/urls.py +++ b/csp/urls.py @@ -27,6 +27,11 @@ router.register(r'assignments', TaskWorkerViewSet) router.register(r'templates', TemplateViewSet) router.register(r'template-items', TemplateItemViewSet) +router.register(r'qualification-items', QualificationItemViewSet) +router.register(r'payments', ChargeViewSet) +router.register(r'transfers', TransferViewSet) +router.register(r'qualifications', QualificationViewSet) +router.register(r'files', FileViewSet) router.register(r'profile', UserProfileViewSet) router.register(r'user', UserViewSet) @@ -39,21 +44,19 @@ router.register(r'task-worker', TaskWorkerViewSet) router.register(r'task-worker-result', TaskWorkerResultViewSet) -router.register(r'template', TemplateViewSet) -router.register(r'template-item', TemplateItemViewSet) -router.register(r'template-item-properties', TemplateItemPropertiesViewSet) +# router.register(r'template', TemplateViewSet) +# router.register(r'template-item', TemplateItemViewSet) +# router.register(r'template-item-properties', TemplateItemPropertiesViewSet) router.register(r'return-feedback', ReturnFeedbackViewSet) -router.register(r'conversation', ConversationViewSet) -router.register(r'conversation-recipients', ConversationRecipientViewSet) -router.register(r'message', MessageViewSet) +# router.register(r'conversation', ConversationViewSet) +# router.register(r'conversation-recipients', ConversationRecipientViewSet) +# router.register(r'message', MessageViewSet) router.register(r'inbox', RedisMessageViewSet, base_name='redis-message') -router.register(r'file', FileViewSet) -router.register(r'qualification', QualificationViewSet) + + router.register(r'requester-access-group', RequesterACGViewSet) router.register(r'worker-access-entry', WorkerACEViewSet) -router.register(r'qualification-item', QualificationItemViewSet) -router.register(r'charges', ChargeViewSet) -router.register(r'transfers', TransferViewSet) + mturk_router = SimpleRouter(trailing_slash=False) mturk_router.register(r'mturk', MTurkAssignmentViewSet) diff --git a/static/js/crowdsource.routes.js b/static/js/crowdsource.routes.js index dbf38b669..3eaeb6b42 100644 --- a/static/js/crowdsource.routes.js +++ b/static/js/crowdsource.routes.js @@ -308,6 +308,12 @@ templateUrl: '/static/templates/docs/template-items.html' }; + var docsPayments = { + controller: 'DocsController', + controllerAs: 'docs', + templateUrl: '/static/templates/docs/payments.html' + }; + var docsOAuth2 = { controller: 'DocsController', controllerAs: 'docs', @@ -466,6 +472,13 @@ }, authenticate: false }) + .state('docs.payments', { + url: '/payments', + views: { + 'content': docsPayments + }, + authenticate: false + }) .state('docs.oauth2', { url: '/oauth2-authentication', views: { diff --git a/static/js/payment/services/payment.service.js b/static/js/payment/services/payment.service.js index cf5dfe9ca..f9774314c 100644 --- a/static/js/payment/services/payment.service.js +++ b/static/js/payment/services/payment.service.js @@ -27,7 +27,7 @@ function createCharge(data) { var settings = { - url: '/api/charges/', + url: '/api/payments/', method: 'POST', data: data }; diff --git a/static/js/project/controllers/project-review.controller.js b/static/js/project/controllers/project-review.controller.js index dab60bc30..8e07d3247 100644 --- a/static/js/project/controllers/project-review.controller.js +++ b/static/js/project/controllers/project-review.controller.js @@ -248,7 +248,7 @@ } function downloadResults() { - window.open('api/file/download-results/?project_id=' + self.resolvedData.id, '_self', ''); + window.open('v1/files/download-results/?project_id=' + self.resolvedData.id, '_self', ''); } function returnTask(taskWorker, worker_alias, e) { diff --git a/static/js/project/services/project.service.js b/static/js/project/services/project.service.js index f4ca7693d..c20b4fcc9 100644 --- a/static/js/project/services/project.service.js +++ b/static/js/project/services/project.service.js @@ -257,7 +257,7 @@ function createQualificationItem(data) { var settings = { - url: '/api/qualification-item/', + url: '/api/qualification-items/', method: 'POST', data: data }; @@ -266,7 +266,7 @@ function deleteQualificationItem(pk) { var settings = { - url: '/api/qualification-item/' + pk + '/', + url: '/api/qualification-items/' + pk + '/', method: 'DELETE' }; return HttpService.doRequest(settings); @@ -274,7 +274,7 @@ function updateQualificationItem(pk, expression) { var settings = { - url: '/api/qualification-item/' + pk + '/', + url: '/api/qualification-items/' + pk + '/', method: 'PUT', data: { expression: expression @@ -285,7 +285,7 @@ function createQualification(data) { var settings = { - url: '/api/qualification/', + url: '/api/qualifications/', method: 'POST', data: data }; @@ -294,7 +294,7 @@ function getQualificationItems(qualification_id) { var settings = { - url: '/api/qualification-item/?qualification=' + qualification_id, + url: '/api/qualification-items/?qualification=' + qualification_id, method: 'GET' }; return HttpService.doRequest(settings); diff --git a/static/js/task/services/task.service.js b/static/js/task/services/task.service.js index cad32baac..dcecfe21d 100644 --- a/static/js/task/services/task.service.js +++ b/static/js/task/services/task.service.js @@ -142,7 +142,7 @@ function downloadResults(params) { var settings = { - url: '/api/file/download-results/', + url: '/api/files/download-results/', method: 'GET', params: params }; diff --git a/static/js/template/services/template.service.js b/static/js/template/services/template.service.js index 2a0602e02..f6c5694c5 100644 --- a/static/js/template/services/template.service.js +++ b/static/js/template/services/template.service.js @@ -280,7 +280,7 @@ function addItem(data) { var settings = { - url: '/api/template-item/', + url: '/api/template-items/', method: 'POST', data: data }; @@ -289,7 +289,7 @@ function updateItem(pk, data) { var settings = { - url: '/api/template-item/' + pk + '/', + url: '/api/template-items/' + pk + '/', method: 'PUT', data: data }; @@ -298,7 +298,7 @@ function deleteItem(pk) { var settings = { - url: '/api/template-item/' + pk + '/', + url: '/api/template-items/' + pk + '/', method: 'DELETE' }; return HttpService.doRequest(settings); diff --git a/static/templates/docs/navigation.html b/static/templates/docs/navigation.html index 4628f9f43..909c50ef2 100644 --- a/static/templates/docs/navigation.html +++ b/static/templates/docs/navigation.html @@ -11,7 +11,7 @@ Template Items Ratings Qualifications/Filters - Payments + Payments diff --git a/static/templates/docs/payments.html b/static/templates/docs/payments.html new file mode 100644 index 000000000..cc8ab3ed8 --- /dev/null +++ b/static/templates/docs/payments.html @@ -0,0 +1,57 @@ +
+
+
+

Payments

+
Used for depositing money to your Daemo account.
+

Resource definition

+
+ {{ '{' }}
+
+ "id": integer,
+ "amount": string,
+ "created_at": string,
+ "updated_at": string +
+ {{ '}' }} +
+
 
+

Payments: create

+
Create a new payment/charge.
+

Request

+
POST /v1/payments/ +
+

Request Data

+
+ {{ '{' }}
+
+ "amount": integer
+
+ {{ '}' }} +
+
+ + + + + + + + + + + + + + + +
Field NameData TypeDescription
amountintegerAmount to be deposited in USD.
+
+

Response

+
{{ '{' }}"id": integer{{ '}' }} +
+
 
+ +
+
+
+
From c6765eac33188ff6c20a5d2e02dcfce94c71c2a8 Mon Sep 17 00:00:00 2001 From: Durim Morina Date: Mon, 8 Jan 2018 17:00:22 -0800 Subject: [PATCH 2/3] added ratings docs and refactored the viewset --- crowdsourcing/viewsets/rating.py | 111 ++++---------------- csp/urls.py | 10 +- static/js/crowdsource.routes.js | 13 +++ static/js/rating/services/rating.service.js | 14 +-- static/templates/docs/navigation.html | 2 +- static/templates/docs/ratings.html | 70 ++++++++++++ 6 files changed, 114 insertions(+), 106 deletions(-) create mode 100644 static/templates/docs/ratings.html diff --git a/crowdsourcing/viewsets/rating.py b/crowdsourcing/viewsets/rating.py index a024bea89..cfa8a4536 100644 --- a/crowdsourcing/viewsets/rating.py +++ b/crowdsourcing/viewsets/rating.py @@ -1,45 +1,44 @@ +from django.contrib.auth.models import User from django.db import transaction from django.db.models import Q -from rest_framework import status, viewsets, serializers +from rest_framework import status, viewsets, serializers, mixins from rest_framework.decorators import list_route from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from crowdsourcing.models import Rating, TaskWorker, Project, RawRatingFeedback, Match from crowdsourcing.permissions.rating import IsRatingOwner -from crowdsourcing.serializers.project import ProjectSerializer from crowdsourcing.serializers.rating import RatingSerializer from crowdsourcing.utils import get_pk from mturk.tasks import update_worker_boomerang -class WorkerRequesterRatingViewset(viewsets.ModelViewSet): +class RatingViewSet(mixins.CreateModelMixin, viewsets.GenericViewSet): queryset = Rating.objects.all() serializer_class = RatingSerializer permission_classes = [IsAuthenticated, IsRatingOwner] def create(self, request, *args, **kwargs): - wrr_serializer = RatingSerializer(data=request.data) - if wrr_serializer.is_valid(): - wrr = wrr_serializer.create(origin=request.user) - wrr_serializer = RatingSerializer(instance=wrr) - if wrr.origin_type == Rating.RATING_REQUESTER: - update_worker_boomerang.delay(wrr.origin_id, wrr.task.project.group_id) - return Response(wrr_serializer.data, status=status.HTTP_201_CREATED) - else: - raise serializers.ValidationError(detail=wrr_serializer.errors) - - def update(self, request, *args, **kwargs): - wrr_serializer = RatingSerializer(data=request.data, partial=True) - wrr = self.get_object() - if wrr_serializer.is_valid(): - wrr = wrr_serializer.update(wrr, wrr_serializer.validated_data) - wrr_serializer = RatingSerializer(instance=wrr) - if wrr.origin_type == Rating.RATING_REQUESTER: - update_worker_boomerang.delay(wrr.origin_id, wrr.task.project.group_id) - return Response(wrr_serializer.data, status=status.HTTP_200_OK) + worker = request.data.get('target') + target = User.objects.filter(profile__handle=worker).first() + if target is None: + return Response({"message": "User with handle {} not found!".format(worker)}, + status=status.HTTP_404_NOT_FOUND) + origin_type = request.data.get('origin_type', Rating.RATING_REQUESTER) + if target.id == request.user.id: + return Response({"message": "Cannot rate self!"}, status=status.HTTP_400_BAD_REQUEST) + if origin_type == 'worker': + origin_type = Rating.RATING_WORKER + elif origin_type == 'requester': + origin_type = Rating.RATING_REQUESTER + + serializer = RatingSerializer( + data={"origin_type": origin_type, "target": target.id, "weight": request.data.get('weight')}) + if serializer.is_valid(): + rating = serializer.create(origin=request.user) + return Response({"id": rating.id}, status=status.HTTP_201_CREATED) else: - raise serializers.ValidationError(detail=wrr_serializer.errors) + raise serializers.ValidationError(detail=serializer.errors) @staticmethod def get_true_skill_ratings(match_group_id): @@ -141,7 +140,6 @@ def list_by_target(self, request, *args, **kwargs): @list_route(methods=['post'], url_path='by-project') def by_project(self, request, *args, **kwargs): project_id = request.data.get('project') - origin_type = request.data.get('origin_type', Rating.RATING_REQUESTER) target = request.data.get('target') weight = request.data.get('weight') @@ -164,68 +162,3 @@ def by_project(self, request, *args, **kwargs): Rating.objects.filter(target_id=target, origin_id=origin, task__in=tasks, origin_type=origin_type).delete() Rating.objects.bulk_create(rating_objects) return Response({"message": "Ratings saved successfully"}) - - -class RatingViewset(viewsets.ModelViewSet): - queryset = Project.objects.filter(deleted_at__isnull=True) - serializer_class = ProjectSerializer - permission_classes = [IsAuthenticated] - - @list_route(methods=['GET']) - def workers_ratings_by_project(self, request, **kwargs): - project_id = request.query_params.get('project', -1) - # noinspection SqlResolve - data = TaskWorker.objects.raw( - ''' - SELECT - r.id id, - 2 origin_type, - r.weight weight, - u.id target, - u.username username, - p.owner_id origin, - COUNT(tw.task_id) AS "task_count" - FROM crowdsourcing_taskworker tw - INNER JOIN crowdsourcing_task t ON (tw.task_id = t.id) - INNER JOIN crowdsourcing_project p - ON (t.project_id = p.id) - INNER JOIN auth_user u - ON (u.id = p.owner_id) - LEFT OUTER JOIN crowdsourcing_rating r - ON (u.id = r.target_id) - WHERE (tw.status IN (3, 4, 5) AND o.id = %s) - GROUP BY - r.weight, - p.owner_id, - r.id - ORDER BY "task_count" DESC, username; - ''', params=[project_id] - ) - - serializer = RatingSerializer(data, many=True, context={'request': request}) - response_data = serializer.data - return Response(data=response_data, status=status.HTTP_200_OK) - - @list_route(methods=['GET']) - def requesters_ratings(self, request, **kwargs): - data = TaskWorker.objects.raw( - ''' - SELECT - DISTINCT - (u.username) username, - 1 origin_type, - %(worker)s origin, - r.id id, - u.id target, - r.weight weight - FROM crowdsourcing_taskworker tw - INNER JOIN crowdsourcing_task t ON tw.task_id=t.id - INNER JOIN crowdsourcing_project p ON t.project_id=p.id - INNER JOIN auth_user u ON p.owner_id=u.id - LEFT OUTER JOIN crowdsourcing_rating r ON u.id=r.target_id - WHERE tw.status IN (3, 4, 5) AND tw.worker_id=%(worker)s; - ''', params={'worker': request.user.id} - ) - serializer = RatingSerializer(data, many=True, context={'request': request}) - response_data = serializer.data - return Response(data=response_data, status=status.HTTP_200_OK) diff --git a/csp/urls.py b/csp/urls.py index d751ffa0b..ce3315ec6 100644 --- a/csp/urls.py +++ b/csp/urls.py @@ -6,16 +6,15 @@ from crowdsourcing import views from crowdsourcing.viewsets.file import FileViewSet -from crowdsourcing.viewsets.message import ConversationViewSet, MessageViewSet, RedisMessageViewSet, \ - ConversationRecipientViewSet +from crowdsourcing.viewsets.message import RedisMessageViewSet from crowdsourcing.viewsets.payment import ChargeViewSet, TransferViewSet from crowdsourcing.viewsets.project import * from crowdsourcing.viewsets.qualification import QualificationViewSet, RequesterACGViewSet, WorkerACEViewSet, \ QualificationItemViewSet -from crowdsourcing.viewsets.rating import WorkerRequesterRatingViewset, RatingViewset +from crowdsourcing.viewsets.rating import RatingViewSet from crowdsourcing.viewsets.task import TaskViewSet, TaskWorkerResultViewSet, TaskWorkerViewSet, \ ExternalSubmit, ReturnFeedbackViewSet -from crowdsourcing.viewsets.template import TemplateViewSet, TemplateItemViewSet, TemplateItemPropertiesViewSet +from crowdsourcing.viewsets.template import TemplateViewSet, TemplateItemViewSet from crowdsourcing.viewsets.user import UserViewSet, UserProfileViewSet, UserPreferencesViewSet, CountryViewSet, \ CityViewSet from mturk import views as mturk_views @@ -36,8 +35,7 @@ router.register(r'profile', UserProfileViewSet) router.register(r'user', UserViewSet) router.register(r'preferences', UserPreferencesViewSet) -router.register(r'worker-requester-rating', WorkerRequesterRatingViewset) -router.register(r'rating', RatingViewset) +router.register(r'ratings', RatingViewSet) router.register(r'country', CountryViewSet) router.register(r'city', CityViewSet) diff --git a/static/js/crowdsource.routes.js b/static/js/crowdsource.routes.js index 3eaeb6b42..20d8ff02a 100644 --- a/static/js/crowdsource.routes.js +++ b/static/js/crowdsource.routes.js @@ -314,6 +314,12 @@ templateUrl: '/static/templates/docs/payments.html' }; + var docsRatings = { + controller: 'DocsController', + controllerAs: 'docs', + templateUrl: '/static/templates/docs/ratings.html' + }; + var docsOAuth2 = { controller: 'DocsController', controllerAs: 'docs', @@ -479,6 +485,13 @@ }, authenticate: false }) + .state('docs.ratings', { + url: '/ratings', + views: { + 'content': docsRatings + }, + authenticate: false + }) .state('docs.oauth2', { url: '/oauth2-authentication', views: { diff --git a/static/js/rating/services/rating.service.js b/static/js/rating/services/rating.service.js index 0048833fb..404496755 100644 --- a/static/js/rating/services/rating.service.js +++ b/static/js/rating/services/rating.service.js @@ -34,12 +34,6 @@ return RatingService; - /** - * @name getWorkerRatings - * @desc Get worker ratings. - * @returns {Promise} - * @memberOf crowdsource.rating.services.RatingService - */ function getWorkerRatings() { var settings = { url: '/api/rating/workers_reviews/', @@ -67,7 +61,7 @@ function submitRating(weight, entry, task) { var settings = { - url: '/api/worker-requester-rating/', + url: '/api/ratings/', method: 'POST', data: { weight: weight, @@ -81,7 +75,7 @@ function updateProjectRating(weight, entry, project) { var settings = { - url: '/api/worker-requester-rating/by-project/', + url: '/api/ratings/by-project/', method: 'POST', data: { weight: weight, @@ -95,7 +89,7 @@ function updateRating(weight, entry) { var settings = { - url: '/api/worker-requester-rating/' + entry.id + '/', + url: '/api/ratings/' + entry.id + '/', method: 'PUT', data: { weight: weight @@ -106,7 +100,7 @@ function listByTarget(target, origin_type) { var settings = { - url: '/api/worker-requester-rating/list-by-target/?target=' + target + '&origin_type=' + origin_type, + url: '/api/ratings/list-by-target/?target=' + target + '&origin_type=' + origin_type, method: 'GET' }; return HttpService.doRequest(settings); diff --git a/static/templates/docs/navigation.html b/static/templates/docs/navigation.html index 909c50ef2..0d9aa101c 100644 --- a/static/templates/docs/navigation.html +++ b/static/templates/docs/navigation.html @@ -9,7 +9,7 @@ Assignments Templates Template Items - Ratings + Ratings Qualifications/Filters Payments diff --git a/static/templates/docs/ratings.html b/static/templates/docs/ratings.html new file mode 100644 index 000000000..35b51ff1c --- /dev/null +++ b/static/templates/docs/ratings.html @@ -0,0 +1,70 @@ +
+
+
+

Ratings

+
Handles the user Boomerang ratings.
+

Resource definition

+
+ {{ '{' }}
+
+ "id": integer,
+ "origin_type": string,
+ "weight": float,
+ "created_at": string,
+ "updated_at": string +
+ {{ '}' }} +
+
 
+

Rating: create

+
Create a new rating, or update the existing one if all data matches.
+

Request

+
POST /v1/ratings/ +
+

Request Data

+
+ {{ '{' }}
+
+ "weight": float,
+ "origin_type": string,
+ "target": string
+
+ {{ '}' }} +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Field NameData TypeDescription
weightfloatThe rating value to be associated to this target user, range from 1.0 (lowest) to 3.0 (highest).
origin_typestringThe account type of the rater, possible values are "worker" and "requester".
targetstringDaemo handle of the worker.
+
+

Response

+
{{ '{' }}"id": integer{{ '}' }} +
+
 
+ +
+
+
+
From 76dee5ae0990156440c59214741d683c36a5ca4a Mon Sep 17 00:00:00 2001 From: Durim Morina Date: Mon, 8 Jan 2018 17:47:25 -0800 Subject: [PATCH 3/3] added qualifications docs and refactoring --- crowdsourcing/serializers/qualification.py | 5 +- crowdsourcing/viewsets/qualification.py | 24 ++- static/js/crowdsource.routes.js | 27 +++ .../project/controllers/project.controller.js | 2 +- static/js/project/services/project.service.js | 2 +- static/templates/docs/navigation.html | 3 +- .../templates/docs/qualification-items.html | 181 ++++++++++++++++++ static/templates/docs/qualifications.html | 118 ++++++++++++ static/templates/docs/templates.html | 2 +- 9 files changed, 350 insertions(+), 14 deletions(-) create mode 100644 static/templates/docs/qualification-items.html create mode 100644 static/templates/docs/qualifications.html diff --git a/crowdsourcing/serializers/qualification.py b/crowdsourcing/serializers/qualification.py index 2c95f355c..91e524e19 100644 --- a/crowdsourcing/serializers/qualification.py +++ b/crowdsourcing/serializers/qualification.py @@ -1,16 +1,17 @@ from rest_framework import serializers from crowdsourcing import constants -from crowdsourcing.serializers.dynamic import DynamicFieldsModelSerializer from crowdsourcing.models import Qualification, QualificationItem, WorkerAccessControlEntry, \ RequesterAccessControlGroup +from crowdsourcing.serializers.dynamic import DynamicFieldsModelSerializer from crowdsourcing.tasks import update_worker_cache class QualificationSerializer(DynamicFieldsModelSerializer): class Meta: model = Qualification - fields = ('id', 'name', 'description') + fields = ('id', 'name', 'created_at', 'updated_at') + read_only_fields = ('created_at', 'updated_at') def create(self, owner, *args, **kwargs): return Qualification.objects.create(owner=owner, **self.validated_data) diff --git a/crowdsourcing/viewsets/qualification.py b/crowdsourcing/viewsets/qualification.py index e162b85d1..8d0d1e04f 100644 --- a/crowdsourcing/viewsets/qualification.py +++ b/crowdsourcing/viewsets/qualification.py @@ -1,19 +1,20 @@ from django.db import transaction -from rest_framework import status, viewsets -from rest_framework.decorators import list_route +from rest_framework import serializers +from rest_framework import status, viewsets, mixins +from rest_framework.decorators import list_route, detail_route from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response -from rest_framework import serializers -from crowdsourcing import constants -from crowdsourcing.tasks import update_worker_cache +from crowdsourcing import constants from crowdsourcing.models import Qualification, QualificationItem, \ WorkerAccessControlEntry, RequesterAccessControlGroup from crowdsourcing.serializers.qualification import QualificationSerializer, QualificationItemSerializer, \ WorkerACESerializer, RequesterACGSerializer +from crowdsourcing.tasks import update_worker_cache -class QualificationViewSet(viewsets.ModelViewSet): +class QualificationViewSet(mixins.CreateModelMixin, mixins.ListModelMixin, mixins.RetrieveModelMixin, + viewsets.GenericViewSet): queryset = Qualification.objects.all() serializer_class = QualificationSerializer permission_classes = [IsAuthenticated] @@ -31,7 +32,14 @@ def create(self, request, *args, **kwargs): def list(self, request, *args, **kwargs): queryset = self.queryset.filter(owner=request.user) serializer = self.serializer_class(instance=queryset, many=True) - return Response(data=serializer.data, status=status.HTTP_200_OK) + return Response( + data={"results": serializer.data, "count": len(serializer.data), "previous": None, "next": None}, + status=status.HTTP_200_OK) + + @detail_route(methods=['get']) + def items(self, request, *args, **kwargs): + qualification_items = self.get_object().items.all() + return Response(self.item_serializer_class(instance=qualification_items, many=True).data) class QualificationItemViewSet(viewsets.ModelViewSet): @@ -57,7 +65,7 @@ def update(self, request, *args, **kwargs): raise serializers.ValidationError(detail=serializer.errors) def list(self, request, *args, **kwargs): - queryset = self.queryset.filter(qualification_id=request.query_params.get('qualification', -1)) + queryset = self.queryset.filter(qualification_id=request.query_params.get('qualification_id', -1)) serializer = self.serializer_class(instance=queryset, many=True) return Response(serializer.data, status=status.HTTP_200_OK) diff --git a/static/js/crowdsource.routes.js b/static/js/crowdsource.routes.js index 20d8ff02a..d1d5f2199 100644 --- a/static/js/crowdsource.routes.js +++ b/static/js/crowdsource.routes.js @@ -320,6 +320,18 @@ templateUrl: '/static/templates/docs/ratings.html' }; + var docsQualifications = { + controller: 'DocsController', + controllerAs: 'docs', + templateUrl: '/static/templates/docs/qualifications.html' + }; + + var docsQualificationItems = { + controller: 'DocsController', + controllerAs: 'docs', + templateUrl: '/static/templates/docs/qualification-items.html' + }; + var docsOAuth2 = { controller: 'DocsController', controllerAs: 'docs', @@ -492,6 +504,21 @@ }, authenticate: false }) + + .state('docs.qualifications', { + url: '/qualifications', + views: { + 'content': docsQualifications + }, + authenticate: false + }) + .state('docs.qualification_items', { + url: '/qualification-items', + views: { + 'content': docsQualificationItems + }, + authenticate: false + }) .state('docs.oauth2', { url: '/oauth2-authentication', views: { diff --git a/static/js/project/controllers/project.controller.js b/static/js/project/controllers/project.controller.js index c40d8c6fd..2442016ca 100644 --- a/static/js/project/controllers/project.controller.js +++ b/static/js/project/controllers/project.controller.js @@ -590,7 +590,7 @@ var file = files[i]; Upload.upload({ - url: '/api/file/', + url: '/api/files/', //fields: {'username': $scope.username}, file: file }).progress(function (evt) { diff --git a/static/js/project/services/project.service.js b/static/js/project/services/project.service.js index c20b4fcc9..499cc53ef 100644 --- a/static/js/project/services/project.service.js +++ b/static/js/project/services/project.service.js @@ -294,7 +294,7 @@ function getQualificationItems(qualification_id) { var settings = { - url: '/api/qualification-items/?qualification=' + qualification_id, + url: '/api/qualification-items/?qualification_id=' + qualification_id, method: 'GET' }; return HttpService.doRequest(settings); diff --git a/static/templates/docs/navigation.html b/static/templates/docs/navigation.html index 0d9aa101c..73713beb3 100644 --- a/static/templates/docs/navigation.html +++ b/static/templates/docs/navigation.html @@ -10,7 +10,8 @@ Templates Template Items Ratings - Qualifications/Filters + Qualifications + Qualification Items Payments diff --git a/static/templates/docs/qualification-items.html b/static/templates/docs/qualification-items.html new file mode 100644 index 000000000..503e5ea54 --- /dev/null +++ b/static/templates/docs/qualification-items.html @@ -0,0 +1,181 @@ +
+
+
+

Qualification Items

+
Qualification item definitions which will be used to filter users at runtime.
+

Resource definition

+
+ {{ '{' }}
+
+ "id": integer,
+ "scope": string,
+ "qualification": integer,
+ "expression": +
+ { +
+ "attribute": string,
+ "operator": string,
+ "value": string
+
+ + } +
+
+ {{ '}' }} +
+
 
+

Qualification Items: list

+
Lists the items by qualification ID.
+

Request

+
GET /v1/qualification-items/?qualification_id={QUALIFICATION_ID}
+

Response

+
+ {{ '{' }}
+
+ "count": integer,
+ "next": string,
+ "previous": string,
+ "results": [
+
Qualification Item Resource
+ ] +
+ {{ '}' }} +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Field NameData TypeDescription
countintegerThe number of qualifications that exist in this qualification.
nextstringURL to fetch next page.
previousstringURL to fetch previous page.
results [ ]listThe list qualification items.
+
+
 
+

Qualification Items: retrieve

+
Retrieve a qualification item by ID.
+

Request

+
GET /v1/qualification-items/qualificationItemId/ +
+

Response

+
+ This method will return a Qualification Item Resource. +
+
 
+

Qualification Items: create

+
Create a new qualification item.
+

Request

+
POST /v1/qualification-items/ +
+

Request Data

+
+ {{ '{' }}
+
+ "scope": string,
+ "qualification": integer,
+ "expression": +
+ { +
+ "attribute": string,
+ "operator": string,
+ "value": string
+
+ + } +
+ +
+ {{ '}' }} +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Field NameData TypeDescription
scopestringScope of this qualification, possible values are "task" and "project".
qualificationintegerId of the qualification this item is being added to. +
expressionJSON object +
expression.attributestringA predefined value for the item attribute, possible values are "assignment_id", "worker_group". +
expression.operatorstringThe operator which is used to evaluate the attribute and value, possible values "in", "not_in", + "contains". +
expression.valuestringValue of the item, varies depending on what the attribute is, it can be a worker group id + or a column in the spreadsheet which contains the assignment ids comma-separated. +
+
+

Response

+
{{ '{' }}"id": integer{{ '}' }} +
+
 
+

Qualification Items: destroy

+
Delete a qualification item by ID.
+

Request

+
DELETE /v1/qualification-items/qualificationItemId/
+

Response

+
The response for this request will be empty.
+
+
+
+
diff --git a/static/templates/docs/qualifications.html b/static/templates/docs/qualifications.html new file mode 100644 index 000000000..d2134b7a4 --- /dev/null +++ b/static/templates/docs/qualifications.html @@ -0,0 +1,118 @@ +
+
+
+

Qualifications

+
Filters that can be applied to projects.
+

Resource definition

+
+ {{ '{' }}
+
+ "id": integer,
+ "name": string,
+ "created_at": string,
+ "updated_at": string +
+ {{ '}' }} +
+
 
+

Templates: list

+
Lists the qualifications that you own.
+

Request

+
GET /v1/qualifications/
+

Response

+
+ {{ '{' }}
+
+ "count": integer,
+ "next": string,
+ "previous": string,
+ "results": [
+
Qualification Resource
+ ] +
+ {{ '}' }} +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Field NameData TypeDescription
countintegerThe number of qualifications that this user owns.
nextstringURL to fetch next page.
previousstringURL to fetch previous page.
results [ ]listThe list of the qualifications.
+
+
 
+

Qualifications: create

+
Create a new qualification.
+

Request

+
POST /v1/qualifications/ +
+

Request Data

+
+ {{ '{' }}
+
+ "name": string
+
+ {{ '}' }} +
+
+ + + + + + + + + + + + + + + +
Field NameData TypeDescription
namestringA name for this qualification.
+
+

Response

+
{{ '{' }}"id": integer{{ '}' }} +
+
 
+ +
+
+
+
diff --git a/static/templates/docs/templates.html b/static/templates/docs/templates.html index a47de188b..81f231c4a 100644 --- a/static/templates/docs/templates.html +++ b/static/templates/docs/templates.html @@ -86,7 +86,7 @@

Request Data

{{ '{' }}
- "name": json object,
+ "name": string,
"items": [],