Implemented issues filters data api rest endpoint.

remotes/origin/enhancement/email-actions
Andrey Antukh 2013-11-08 15:35:31 +01:00
parent 649df99977
commit f31b2fafa9
5 changed files with 168 additions and 23 deletions

View File

@ -0,0 +1,138 @@
# -*- coding: utf-8 -*-
from contextlib import closing
from django.db import connection
def _get_issues_tags(project):
extra_sql = ("select unnest(unpickle(tags)) as tagname, count(unnest(unpickle(tags))) "
"from issues_issue where project_id = %s "
"group by unnest(unpickle(tags)) "
"order by tagname asc")
with closing(connection.cursor()) as cursor:
cursor.execute(extra_sql, [project.id])
rows = cursor.fetchall()
return dict(rows)
def _get_issues_statuses(project):
extra_sql = ("select status_id, count(status_id) from issues_issue "
"where project_id = %s group by status_id;")
extra_sql = """
select id, (select count(*) from issues_issue
where project_id = m.project_id and status_id = m.id)
from projects_issuestatus as m
where project_id = %s;
"""
with closing(connection.cursor()) as cursor:
cursor.execute(extra_sql, [project.id])
rows = cursor.fetchall()
return dict(rows)
def _get_issues_priorities(project):
extra_sql = """
select id, (select count(*) from issues_issue
where project_id = m.project_id and priority_id = m.id)
from projects_priority as m
where project_id = %s;
"""
with closing(connection.cursor()) as cursor:
cursor.execute(extra_sql, [project.id])
rows = cursor.fetchall()
return dict(rows)
def _get_issues_types(project):
extra_sql = """
select id, (select count(*) from issues_issue
where project_id = m.project_id and type_id = m.id)
from projects_issuetype as m
where project_id = %s;
"""
with closing(connection.cursor()) as cursor:
cursor.execute(extra_sql, [project.id])
rows = cursor.fetchall()
return dict(rows)
def _get_issues_severities(project):
extra_sql = """
select id, (select count(*) from issues_issue
where project_id = m.project_id and severity_id = m.id)
from projects_severity as m
where project_id = %s;
"""
with closing(connection.cursor()) as cursor:
cursor.execute(extra_sql, [project.id])
rows = cursor.fetchall()
return dict(rows)
def _get_issues_assigned_to(project):
extra_sql = """
select user_id, (select count(*) from issues_issue
where project_id = pm.project_id and assigned_to_id = pm.user_id)
from projects_membership as pm
where project_id = %s;
"""
with closing(connection.cursor()) as cursor:
cursor.execute(extra_sql, [project.id])
rows = cursor.fetchall()
return dict(rows)
def _get_issues_owners(project):
extra_sql = """
select user_id, (select count(*) from issues_issue
where project_id = pm.project_id and owner_id = pm.user_id)
from projects_membership as pm
where project_id = %s;
"""
with closing(connection.cursor()) as cursor:
cursor.execute(extra_sql, [project.id])
rows = cursor.fetchall()
return dict(rows)
def _get_issues_created_by(project):
extra_sql = """
select user_id, (select count(*) from issues_issue
where project_id = pm.project_id and owner_id = pm.user_id)
from projects_membership as pm
where project_id = %s;
"""
with closing(connection.cursor()) as cursor:
cursor.execute(extra_sql, [project.id])
rows = cursor.fetchall()
return dict(rows)
def get_issues_filters_data(project):
data = {
"owners": _get_issues_owners(project),
"tags": _get_issues_tags(project),
"statuses": _get_issues_statuses(project),
"priorities": _get_issues_priorities(project),
"assigned_to": _get_issues_assigned_to(project),
"created_by": _get_issues_created_by(project),
"types": _get_issues_types(project),
"severities": _get_issues_severities(project),
}
return data

View File

@ -1,7 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.db.models import Q, Count from django.db.models import Q
from django.shortcuts import get_object_or_404
from rest_framework.permissions import IsAuthenticated from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response from rest_framework.response import Response
@ -14,7 +13,9 @@ from greenmine.base.notifications.api import NotificationSenderMixin
from . import serializers from . import serializers
from . import models from . import models
from . import permissions from . import permissions
from .aggregates import stats from .aggregates import stats
from .aggregates import filters as filters_aggr
class ProjectViewSet(ModelCrudViewSet): class ProjectViewSet(ModelCrudViewSet):
@ -33,6 +34,11 @@ class ProjectViewSet(ModelCrudViewSet):
project = self.get_object() project = self.get_object()
return Response(stats.get_stats_for_project_issues(project)) return Response(stats.get_stats_for_project_issues(project))
@detail_route(methods=['get'])
def issue_filters_data(self, request, pk=None):
project = self.get_object()
return Response(filters_aggr.get_issues_filters_data(project))
def get_queryset(self): def get_queryset(self):
qs = super(ProjectViewSet, self).get_queryset() qs = super(ProjectViewSet, self).get_queryset()
qs = qs.filter(Q(owner=self.request.user) | qs = qs.filter(Q(owner=self.request.user) |

View File

@ -1,8 +1,12 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import reversion
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from rest_framework.permissions import IsAuthenticated from rest_framework.permissions import IsAuthenticated
from rest_framework.decorators import list_route
from rest_framework.response import Response
from rest_framework import status
from greenmine.base import filters from greenmine.base import filters
from greenmine.base import exceptions as exc from greenmine.base import exceptions as exc
@ -16,8 +20,6 @@ from . import models
from . import permissions from . import permissions
from . import serializers from . import serializers
import reversion
class IssueAttachmentViewSet(ModelCrudViewSet): class IssueAttachmentViewSet(ModelCrudViewSet):
model = Attachment model = Attachment
@ -90,3 +92,4 @@ class IssueViewSet(NotificationSenderMixin, ModelCrudViewSet):
# Update the comment in the last version # Update the comment in the last version
reversion.set_comment(self.request.DATA["comment"]) reversion.set_comment(self.request.DATA["comment"])
super().post_save(obj, created) super().post_save(obj, created)

View File

@ -161,10 +161,6 @@ class Project(models.Model):
role_model = get_model("users", "Role") role_model = get_model("users", "Role")
return role_model.objects.all() return role_model.objects.all()
# TODO: do not remove this
# return role_model.objects.filter(id__in=list(self.memberships.values_list(
# "role", flat=True)))
def get_users(self): def get_users(self):
user_model = get_user_model() user_model = get_user_model()
return user_model.objects.filter( return user_model.objects.filter(

View File

@ -1,3 +1,5 @@
CREATE INDEX issues_unpickle_tags_index ON issues_issue USING btree (unpickle(tags));
CREATE OR REPLACE FUNCTION unpickle (data text) CREATE OR REPLACE FUNCTION unpickle (data text)
RETURNS text[] RETURNS text[]
AS $$ AS $$
@ -7,18 +9,18 @@ AS $$
return pickle.loads(base64.b64decode(data)) return pickle.loads(base64.b64decode(data))
$$ LANGUAGE plpythonu; $$ LANGUAGE plpythonu;
CREATE OR REPLACE FUNCTION array_uniq_join (data text[], data2 text[]) -- CREATE OR REPLACE FUNCTION array_uniq_join (data text[], data2 text[])
RETURNS text[] -- RETURNS text[]
AS $$ -- AS $$
tmp = set(data) -- tmp = set(data)
tmp.update(data2) -- tmp.update(data2)
return tuple(tmp) -- return tuple(tmp)
$$ LANGUAGE plpythonu; -- $$ LANGUAGE plpythonu;
--
DROP AGGREGATE array_uniq_concat (text[]); -- DROP AGGREGATE array_uniq_concat (text[]);
CREATE AGGREGATE array_uniq_concat (text[]) -- CREATE AGGREGATE array_uniq_concat (text[])
( -- (
sfunc = array_uniq_join, -- sfunc = array_uniq_join,
stype = text[], -- stype = text[],
initcond = '{}' -- initcond = '{}'
); -- );