Refactoring likes, votes, watchers and favourites names
parent
37c9a2fe6e
commit
da8024141b
|
@ -34,8 +34,8 @@ from taiga.projects.history.mixins import HistoryResourceMixin
|
||||||
from taiga.projects.notifications.mixins import WatchedResourceMixin, WatchersViewSetMixin
|
from taiga.projects.notifications.mixins import WatchedResourceMixin, WatchersViewSetMixin
|
||||||
from taiga.projects.notifications.choices import NotifyLevel
|
from taiga.projects.notifications.choices import NotifyLevel
|
||||||
from taiga.projects.notifications.utils import (
|
from taiga.projects.notifications.utils import (
|
||||||
attach_project_watchers_attrs_to_queryset,
|
attach_project_total_watchers_attrs_to_queryset,
|
||||||
attach_project_is_watched_to_queryset,
|
attach_project_is_watcher_to_queryset,
|
||||||
attach_notify_level_to_project_queryset)
|
attach_notify_level_to_project_queryset)
|
||||||
|
|
||||||
from taiga.projects.mixins.ordering import BulkUpdateOrderMixin
|
from taiga.projects.mixins.ordering import BulkUpdateOrderMixin
|
||||||
|
@ -69,9 +69,9 @@ class ProjectViewSet(LikedResourceMixin, HistoryResourceMixin, ModelCrudViewSet)
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
qs = super().get_queryset()
|
qs = super().get_queryset()
|
||||||
qs = self.attach_votes_attrs_to_queryset(qs)
|
qs = self.attach_votes_attrs_to_queryset(qs)
|
||||||
qs = attach_project_watchers_attrs_to_queryset(qs)
|
qs = attach_project_total_watchers_attrs_to_queryset(qs)
|
||||||
if self.request.user.is_authenticated():
|
if self.request.user.is_authenticated():
|
||||||
qs = attach_project_is_watched_to_queryset(qs, self.request.user)
|
qs = attach_project_is_watcher_to_queryset(qs, self.request.user)
|
||||||
qs = attach_notify_level_to_project_queryset(qs, self.request.user)
|
qs = attach_notify_level_to_project_queryset(qs, self.request.user)
|
||||||
|
|
||||||
return qs
|
return qs
|
||||||
|
|
|
@ -76,7 +76,7 @@ class IssueViewSet(OCCResourceMixin, VotedResourceMixin, HistoryResourceMixin, W
|
||||||
"owner",
|
"owner",
|
||||||
"assigned_to",
|
"assigned_to",
|
||||||
"subject",
|
"subject",
|
||||||
"votes_count")
|
"total_voters")
|
||||||
|
|
||||||
def get_serializer_class(self, *args, **kwargs):
|
def get_serializer_class(self, *args, **kwargs):
|
||||||
if self.action in ["retrieve", "by_ref"]:
|
if self.action in ["retrieve", "by_ref"]:
|
||||||
|
|
|
@ -23,15 +23,15 @@ from taiga.mdrender.service import render as mdrender
|
||||||
from taiga.projects.validators import ProjectExistsValidator
|
from taiga.projects.validators import ProjectExistsValidator
|
||||||
from taiga.projects.notifications.validators import WatchersValidator
|
from taiga.projects.notifications.validators import WatchersValidator
|
||||||
from taiga.projects.serializers import BasicIssueStatusSerializer
|
from taiga.projects.serializers import BasicIssueStatusSerializer
|
||||||
from taiga.projects.notifications.mixins import WatchedResourceModelSerializer
|
from taiga.projects.notifications.mixins import EditableWatchedResourceModelSerializer
|
||||||
from taiga.projects.votes.mixins.serializers import VotedResourceSerializerMixin
|
from taiga.projects.votes.mixins.serializers import VoteResourceSerializerMixin
|
||||||
|
|
||||||
from taiga.users.serializers import UserBasicInfoSerializer
|
from taiga.users.serializers import UserBasicInfoSerializer
|
||||||
|
|
||||||
from . import models
|
from . import models
|
||||||
|
|
||||||
|
|
||||||
class IssueSerializer(WatchersValidator, VotedResourceSerializerMixin, WatchedResourceModelSerializer, serializers.ModelSerializer):
|
class IssueSerializer(WatchersValidator, VoteResourceSerializerMixin, EditableWatchedResourceModelSerializer, serializers.ModelSerializer):
|
||||||
tags = TagsField(required=False)
|
tags = TagsField(required=False)
|
||||||
external_reference = PgArrayField(required=False)
|
external_reference = PgArrayField(required=False)
|
||||||
is_closed = serializers.Field(source="is_closed")
|
is_closed = serializers.Field(source="is_closed")
|
||||||
|
|
|
@ -29,7 +29,10 @@ from taiga.base.api import serializers
|
||||||
from taiga.base.api.utils import get_object_or_404
|
from taiga.base.api.utils import get_object_or_404
|
||||||
from taiga.base.fields import WatchersField
|
from taiga.base.fields import WatchersField
|
||||||
from taiga.projects.notifications import services
|
from taiga.projects.notifications import services
|
||||||
from taiga.projects.notifications.utils import attach_watchers_to_queryset, attach_is_watched_to_queryset
|
from taiga.projects.notifications.utils import (attach_watchers_to_queryset,
|
||||||
|
attach_is_watcher_to_queryset,
|
||||||
|
attach_total_watchers_to_queryset)
|
||||||
|
|
||||||
from taiga.users.models import User
|
from taiga.users.models import User
|
||||||
from . import models
|
from . import models
|
||||||
from . serializers import WatcherSerializer
|
from . serializers import WatcherSerializer
|
||||||
|
@ -50,8 +53,9 @@ class WatchedResourceMixin:
|
||||||
|
|
||||||
def attach_watchers_attrs_to_queryset(self, queryset):
|
def attach_watchers_attrs_to_queryset(self, queryset):
|
||||||
qs = attach_watchers_to_queryset(queryset)
|
qs = attach_watchers_to_queryset(queryset)
|
||||||
|
qs = attach_total_watchers_to_queryset(queryset)
|
||||||
if self.request.user.is_authenticated():
|
if self.request.user.is_authenticated():
|
||||||
qs = attach_is_watched_to_queryset(qs, self.request.user)
|
qs = attach_is_watcher_to_queryset(qs, self.request.user)
|
||||||
|
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
|
@ -178,12 +182,20 @@ class WatchedModelMixin(object):
|
||||||
|
|
||||||
|
|
||||||
class WatchedResourceModelSerializer(serializers.ModelSerializer):
|
class WatchedResourceModelSerializer(serializers.ModelSerializer):
|
||||||
is_watched = serializers.SerializerMethodField("get_is_watched")
|
is_watcher = serializers.SerializerMethodField("get_is_watcher")
|
||||||
watchers = WatchersField(required=False)
|
total_watchers = serializers.SerializerMethodField("get_total_watchers")
|
||||||
|
|
||||||
def get_is_watched(self, obj):
|
def get_is_watcher(self, obj):
|
||||||
# The "is_watched" attribute is attached in the get_queryset of the viewset.
|
# The "is_watcher" attribute is attached in the get_queryset of the viewset.
|
||||||
return getattr(obj, "is_watched", False) or False
|
return getattr(obj, "is_watcher", False) or False
|
||||||
|
|
||||||
|
def get_total_watchers(self, obj):
|
||||||
|
# The "total_watchers" attribute is attached in the get_queryset of the viewset.
|
||||||
|
return getattr(obj, "total_watchers", 0) or 0
|
||||||
|
|
||||||
|
|
||||||
|
class EditableWatchedResourceModelSerializer(WatchedResourceModelSerializer):
|
||||||
|
watchers = WatchersField(required=False)
|
||||||
|
|
||||||
def restore_object(self, attrs, instance=None):
|
def restore_object(self, attrs, instance=None):
|
||||||
#watchers is not a field from the model but can be attached in the get_queryset of the viewset.
|
#watchers is not a field from the model but can be attached in the get_queryset of the viewset.
|
||||||
|
@ -223,7 +235,7 @@ class WatchedResourceModelSerializer(serializers.ModelSerializer):
|
||||||
return super(WatchedResourceModelSerializer, self).to_native(obj)
|
return super(WatchedResourceModelSerializer, self).to_native(obj)
|
||||||
|
|
||||||
def save(self, **kwargs):
|
def save(self, **kwargs):
|
||||||
obj = super(WatchedResourceModelSerializer, self).save(**kwargs)
|
obj = super(EditableWatchedResourceModelSerializer, self).save(**kwargs)
|
||||||
self.fields["watchers"] = WatchersField(required=False)
|
self.fields["watchers"] = WatchersField(required=False)
|
||||||
obj.watchers = [user.id for user in obj.get_watchers()]
|
obj.watchers = [user.id for user in obj.get_watchers()]
|
||||||
return obj
|
return obj
|
||||||
|
|
|
@ -40,8 +40,8 @@ def attach_watchers_to_queryset(queryset, as_field="watchers"):
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
|
|
||||||
def attach_is_watched_to_queryset(queryset, user, as_field="is_watched"):
|
def attach_is_watcher_to_queryset(queryset, user, as_field="is_watcher"):
|
||||||
"""Attach is_watched boolean to each object of the queryset.
|
"""Attach is_watcher boolean to each object of the queryset.
|
||||||
|
|
||||||
:param user: A users.User object model
|
:param user: A users.User object model
|
||||||
:param queryset: A Django queryset object.
|
:param queryset: A Django queryset object.
|
||||||
|
@ -64,8 +64,28 @@ def attach_is_watched_to_queryset(queryset, user, as_field="is_watched"):
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
|
|
||||||
def attach_project_is_watched_to_queryset(queryset, user, as_field="is_watched"):
|
def attach_total_watchers_to_queryset(queryset, as_field="total_watchers"):
|
||||||
"""Attach is_watched boolean to each object of the projects queryset.
|
"""Attach total_watchers boolean to each object of the queryset.
|
||||||
|
|
||||||
|
:param user: A users.User object model
|
||||||
|
:param queryset: A Django queryset object.
|
||||||
|
:param as_field: Attach the boolean as an attribute with this name.
|
||||||
|
|
||||||
|
:return: Queryset object with the additional `as_field` field.
|
||||||
|
"""
|
||||||
|
model = queryset.model
|
||||||
|
type = apps.get_model("contenttypes", "ContentType").objects.get_for_model(model)
|
||||||
|
sql = ("""SELECT count(*)
|
||||||
|
FROM notifications_watched
|
||||||
|
WHERE notifications_watched.content_type_id = {type_id}
|
||||||
|
AND notifications_watched.object_id = {tbl}.id""")
|
||||||
|
sql = sql.format(type_id=type.id, tbl=model._meta.db_table)
|
||||||
|
qs = queryset.extra(select={as_field: sql})
|
||||||
|
return qs
|
||||||
|
|
||||||
|
|
||||||
|
def attach_project_is_watcher_to_queryset(queryset, user, as_field="is_watcher"):
|
||||||
|
"""Attach is_watcher boolean to each object of the projects queryset.
|
||||||
|
|
||||||
:param user: A users.User object model
|
:param user: A users.User object model
|
||||||
:param queryset: A Django projects queryset object.
|
:param queryset: A Django projects queryset object.
|
||||||
|
@ -89,7 +109,7 @@ def attach_project_is_watched_to_queryset(queryset, user, as_field="is_watched")
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
|
|
||||||
def attach_project_watchers_attrs_to_queryset(queryset, as_field="watchers"):
|
def attach_project_total_watchers_attrs_to_queryset(queryset, as_field="total_watchers"):
|
||||||
"""Attach watching user ids to each project of the queryset.
|
"""Attach watching user ids to each project of the queryset.
|
||||||
|
|
||||||
:param queryset: A Django projects queryset object.
|
:param queryset: A Django projects queryset object.
|
||||||
|
@ -100,10 +120,10 @@ def attach_project_watchers_attrs_to_queryset(queryset, as_field="watchers"):
|
||||||
model = queryset.model
|
model = queryset.model
|
||||||
type = apps.get_model("contenttypes", "ContentType").objects.get_for_model(model)
|
type = apps.get_model("contenttypes", "ContentType").objects.get_for_model(model)
|
||||||
|
|
||||||
sql = ("""SELECT array(SELECT user_id
|
sql = ("""SELECT count(user_id)
|
||||||
FROM notifications_notifypolicy
|
FROM notifications_notifypolicy
|
||||||
WHERE notifications_notifypolicy.project_id = {tbl}.id
|
WHERE notifications_notifypolicy.project_id = {tbl}.id
|
||||||
AND notifications_notifypolicy.notify_level != {ignore_notify_level})""")
|
AND notifications_notifypolicy.notify_level != {ignore_notify_level}""")
|
||||||
sql = sql.format(tbl=model._meta.db_table, ignore_notify_level=NotifyLevel.ignore)
|
sql = sql.format(tbl=model._meta.db_table, ignore_notify_level=NotifyLevel.ignore)
|
||||||
qs = queryset.extra(select={as_field: sql})
|
qs = queryset.extra(select={as_field: sql})
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,6 @@ from taiga.base.fields import PgArrayField
|
||||||
from taiga.base.fields import TagsField
|
from taiga.base.fields import TagsField
|
||||||
from taiga.base.fields import TagsColorsField
|
from taiga.base.fields import TagsColorsField
|
||||||
|
|
||||||
from taiga.projects.notifications.validators import WatchersValidator
|
|
||||||
|
|
||||||
from taiga.users.services import get_photo_or_gravatar_url
|
from taiga.users.services import get_photo_or_gravatar_url
|
||||||
from taiga.users.serializers import UserSerializer
|
from taiga.users.serializers import UserSerializer
|
||||||
from taiga.users.serializers import UserBasicInfoSerializer
|
from taiga.users.serializers import UserBasicInfoSerializer
|
||||||
|
@ -40,12 +38,12 @@ from taiga.projects.notifications import models as notify_models
|
||||||
|
|
||||||
from . import models
|
from . import models
|
||||||
from . import services
|
from . import services
|
||||||
|
from .notifications.mixins import WatchedResourceModelSerializer
|
||||||
from .validators import ProjectExistsValidator
|
from .validators import ProjectExistsValidator
|
||||||
from .custom_attributes.serializers import UserStoryCustomAttributeSerializer
|
from .custom_attributes.serializers import UserStoryCustomAttributeSerializer
|
||||||
from .custom_attributes.serializers import TaskCustomAttributeSerializer
|
from .custom_attributes.serializers import TaskCustomAttributeSerializer
|
||||||
from .custom_attributes.serializers import IssueCustomAttributeSerializer
|
from .custom_attributes.serializers import IssueCustomAttributeSerializer
|
||||||
from .notifications.mixins import WatchedResourceModelSerializer
|
from .votes.mixins.serializers import FanResourceSerializerMixin
|
||||||
from .votes.mixins.serializers import LikedResourceSerializerMixin
|
|
||||||
|
|
||||||
######################################################
|
######################################################
|
||||||
## Custom values for selectors
|
## Custom values for selectors
|
||||||
|
@ -310,7 +308,7 @@ class ProjectMemberSerializer(serializers.ModelSerializer):
|
||||||
## Projects
|
## Projects
|
||||||
######################################################
|
######################################################
|
||||||
|
|
||||||
class ProjectSerializer(WatchersValidator, LikedResourceSerializerMixin, WatchedResourceModelSerializer, serializers.ModelSerializer):
|
class ProjectSerializer(FanResourceSerializerMixin, WatchedResourceModelSerializer, serializers.ModelSerializer):
|
||||||
tags = TagsField(default=[], required=False)
|
tags = TagsField(default=[], required=False)
|
||||||
anon_permissions = PgArrayField(required=False)
|
anon_permissions = PgArrayField(required=False)
|
||||||
public_permissions = PgArrayField(required=False)
|
public_permissions = PgArrayField(required=False)
|
||||||
|
|
|
@ -27,15 +27,15 @@ from taiga.projects.milestones.validators import SprintExistsValidator
|
||||||
from taiga.projects.tasks.validators import TaskExistsValidator
|
from taiga.projects.tasks.validators import TaskExistsValidator
|
||||||
from taiga.projects.notifications.validators import WatchersValidator
|
from taiga.projects.notifications.validators import WatchersValidator
|
||||||
from taiga.projects.serializers import BasicTaskStatusSerializerSerializer
|
from taiga.projects.serializers import BasicTaskStatusSerializerSerializer
|
||||||
from taiga.projects.notifications.mixins import WatchedResourceModelSerializer
|
from taiga.projects.notifications.mixins import EditableWatchedResourceModelSerializer
|
||||||
from taiga.projects.votes.mixins.serializers import VotedResourceSerializerMixin
|
from taiga.projects.votes.mixins.serializers import VoteResourceSerializerMixin
|
||||||
|
|
||||||
from taiga.users.serializers import UserBasicInfoSerializer
|
from taiga.users.serializers import UserBasicInfoSerializer
|
||||||
|
|
||||||
from . import models
|
from . import models
|
||||||
|
|
||||||
|
|
||||||
class TaskSerializer(WatchersValidator, VotedResourceSerializerMixin, WatchedResourceModelSerializer, serializers.ModelSerializer):
|
class TaskSerializer(WatchersValidator, VoteResourceSerializerMixin, EditableWatchedResourceModelSerializer, serializers.ModelSerializer):
|
||||||
tags = TagsField(required=False, default=[])
|
tags = TagsField(required=False, default=[])
|
||||||
external_reference = PgArrayField(required=False)
|
external_reference = PgArrayField(required=False)
|
||||||
comment = serializers.SerializerMethodField("get_comment")
|
comment = serializers.SerializerMethodField("get_comment")
|
||||||
|
|
|
@ -70,7 +70,7 @@ class UserStoryViewSet(OCCResourceMixin, VotedResourceMixin, HistoryResourceMixi
|
||||||
order_by_fields = ["backlog_order",
|
order_by_fields = ["backlog_order",
|
||||||
"sprint_order",
|
"sprint_order",
|
||||||
"kanban_order",
|
"kanban_order",
|
||||||
"votes_count"]
|
"total_voters"]
|
||||||
|
|
||||||
# Specific filter used for filtering neighbor user stories
|
# Specific filter used for filtering neighbor user stories
|
||||||
_neighbor_tags_filter = filters.TagsFilter('neighbor_tags')
|
_neighbor_tags_filter = filters.TagsFilter('neighbor_tags')
|
||||||
|
|
|
@ -27,8 +27,8 @@ from taiga.projects.validators import UserStoryStatusExistsValidator
|
||||||
from taiga.projects.userstories.validators import UserStoryExistsValidator
|
from taiga.projects.userstories.validators import UserStoryExistsValidator
|
||||||
from taiga.projects.notifications.validators import WatchersValidator
|
from taiga.projects.notifications.validators import WatchersValidator
|
||||||
from taiga.projects.serializers import BasicUserStoryStatusSerializer
|
from taiga.projects.serializers import BasicUserStoryStatusSerializer
|
||||||
from taiga.projects.notifications.mixins import WatchedResourceModelSerializer
|
from taiga.projects.notifications.mixins import EditableWatchedResourceModelSerializer
|
||||||
from taiga.projects.votes.mixins.serializers import VotedResourceSerializerMixin
|
from taiga.projects.votes.mixins.serializers import VoteResourceSerializerMixin
|
||||||
|
|
||||||
from taiga.users.serializers import UserBasicInfoSerializer
|
from taiga.users.serializers import UserBasicInfoSerializer
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ class RolePointsField(serializers.WritableField):
|
||||||
return json.loads(obj)
|
return json.loads(obj)
|
||||||
|
|
||||||
|
|
||||||
class UserStorySerializer(WatchersValidator, VotedResourceSerializerMixin, WatchedResourceModelSerializer, serializers.ModelSerializer):
|
class UserStorySerializer(WatchersValidator, VoteResourceSerializerMixin, EditableWatchedResourceModelSerializer, serializers.ModelSerializer):
|
||||||
tags = TagsField(default=[], required=False)
|
tags = TagsField(default=[], required=False)
|
||||||
external_reference = PgArrayField(required=False)
|
external_reference = PgArrayField(required=False)
|
||||||
points = RolePointsField(source="role_points", required=False)
|
points = RolePointsField(source="role_points", required=False)
|
||||||
|
|
|
@ -17,21 +17,27 @@
|
||||||
from taiga.base.api import serializers
|
from taiga.base.api import serializers
|
||||||
|
|
||||||
|
|
||||||
class BaseVotedResourceSerializer(serializers.ModelSerializer):
|
class FanResourceSerializerMixin(serializers.ModelSerializer):
|
||||||
def get_votes_counter(self, obj):
|
is_fan = serializers.SerializerMethodField("get_is_fan")
|
||||||
# The "votes_count" attribute is attached in the get_queryset of the viewset.
|
total_fans = serializers.SerializerMethodField("get_total_fans")
|
||||||
return getattr(obj, "votes_count", 0) or 0
|
|
||||||
|
|
||||||
def get_is_voted(self, obj):
|
def get_is_fan(self, obj):
|
||||||
# The "is_voted" attribute is attached in the get_queryset of the viewset.
|
# The "is_voted" attribute is attached in the get_queryset of the viewset.
|
||||||
return getattr(obj, "is_voted", False) or False
|
return getattr(obj, "is_voter", False) or False
|
||||||
|
|
||||||
|
def get_total_fans(self, obj):
|
||||||
|
# The "total_likes" attribute is attached in the get_queryset of the viewset.
|
||||||
|
return getattr(obj, "total_voters", 0) or 0
|
||||||
|
|
||||||
|
|
||||||
class LikedResourceSerializerMixin(BaseVotedResourceSerializer):
|
class VoteResourceSerializerMixin(serializers.ModelSerializer):
|
||||||
likes = serializers.SerializerMethodField("get_votes_counter")
|
is_voter = serializers.SerializerMethodField("get_is_voter")
|
||||||
is_liked = serializers.SerializerMethodField("get_is_voted")
|
total_voters = serializers.SerializerMethodField("get_total_voters")
|
||||||
|
|
||||||
|
def get_is_voter(self, obj):
|
||||||
|
# The "is_voted" attribute is attached in the get_queryset of the viewset.
|
||||||
|
return getattr(obj, "is_voter", False) or False
|
||||||
|
|
||||||
class VotedResourceSerializerMixin(BaseVotedResourceSerializer):
|
def get_total_voters(self, obj):
|
||||||
votes = serializers.SerializerMethodField("get_votes_counter")
|
# The "total_likes" attribute is attached in the get_queryset of the viewset.
|
||||||
is_voted = serializers.SerializerMethodField("get_is_voted")
|
return getattr(obj, "total_voters", 0) or 0
|
||||||
|
|
|
@ -23,7 +23,7 @@ from taiga.base.decorators import detail_route
|
||||||
|
|
||||||
from taiga.projects.votes import serializers
|
from taiga.projects.votes import serializers
|
||||||
from taiga.projects.votes import services
|
from taiga.projects.votes import services
|
||||||
from taiga.projects.votes.utils import attach_votes_count_to_queryset, attach_is_vote_to_queryset
|
from taiga.projects.votes.utils import attach_total_voters_to_queryset, attach_is_voter_to_queryset
|
||||||
|
|
||||||
|
|
||||||
class BaseVotedResource:
|
class BaseVotedResource:
|
||||||
|
@ -33,10 +33,10 @@ class BaseVotedResource:
|
||||||
# return self.attach_votes_attrs_to_queryset(qs)
|
# return self.attach_votes_attrs_to_queryset(qs)
|
||||||
|
|
||||||
def attach_votes_attrs_to_queryset(self, queryset):
|
def attach_votes_attrs_to_queryset(self, queryset):
|
||||||
qs = attach_votes_count_to_queryset(queryset)
|
qs = attach_total_voters_to_queryset(queryset)
|
||||||
|
|
||||||
if self.request.user.is_authenticated():
|
if self.request.user.is_authenticated():
|
||||||
qs = attach_is_vote_to_queryset(self.request.user, qs)
|
qs = attach_is_voter_to_queryset(self.request.user, qs)
|
||||||
|
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,6 @@ def add_vote(obj, user):
|
||||||
obj_type = apps.get_model("contenttypes", "ContentType").objects.get_for_model(obj)
|
obj_type = apps.get_model("contenttypes", "ContentType").objects.get_for_model(obj)
|
||||||
with atomic():
|
with atomic():
|
||||||
vote, created = Vote.objects.get_or_create(content_type=obj_type, object_id=obj.id, user=user)
|
vote, created = Vote.objects.get_or_create(content_type=obj_type, object_id=obj.id, user=user)
|
||||||
|
|
||||||
if not created:
|
if not created:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
|
|
||||||
|
|
||||||
def attach_votes_count_to_queryset(queryset, as_field="votes_count"):
|
def attach_total_voters_to_queryset(queryset, as_field="total_voters"):
|
||||||
"""Attach votes count to each object of the queryset.
|
"""Attach votes count to each object of the queryset.
|
||||||
|
|
||||||
Because of laziness of vote objects creation, this makes much simpler and more efficient to
|
Because of laziness of vote objects creation, this makes much simpler and more efficient to
|
||||||
|
@ -34,8 +34,8 @@ def attach_votes_count_to_queryset(queryset, as_field="votes_count"):
|
||||||
"""
|
"""
|
||||||
model = queryset.model
|
model = queryset.model
|
||||||
type = apps.get_model("contenttypes", "ContentType").objects.get_for_model(model)
|
type = apps.get_model("contenttypes", "ContentType").objects.get_for_model(model)
|
||||||
sql = """SELECT coalesce(SUM(votes_count), 0) FROM (
|
sql = """SELECT coalesce(SUM(total_voters), 0) FROM (
|
||||||
SELECT coalesce(votes_votes.count, 0) votes_count
|
SELECT coalesce(votes_votes.count, 0) total_voters
|
||||||
FROM votes_votes
|
FROM votes_votes
|
||||||
WHERE votes_votes.content_type_id = {type_id}
|
WHERE votes_votes.content_type_id = {type_id}
|
||||||
AND votes_votes.object_id = {tbl}.id
|
AND votes_votes.object_id = {tbl}.id
|
||||||
|
@ -46,7 +46,7 @@ def attach_votes_count_to_queryset(queryset, as_field="votes_count"):
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
|
|
||||||
def attach_is_vote_to_queryset(user, queryset, as_field="is_voted"):
|
def attach_is_voter_to_queryset(user, queryset, as_field="is_voter"):
|
||||||
"""Attach is_vote boolean to each object of the queryset.
|
"""Attach is_vote boolean to each object of the queryset.
|
||||||
|
|
||||||
Because of laziness of vote objects creation, this makes much simpler and more efficient to
|
Because of laziness of vote objects creation, this makes much simpler and more efficient to
|
||||||
|
|
|
@ -113,32 +113,62 @@ class UsersViewSet(ModelCrudViewSet):
|
||||||
self.check_permissions(request, "stats", user)
|
self.check_permissions(request, "stats", user)
|
||||||
return response.Ok(services.get_stats_for_user(user, request.user))
|
return response.Ok(services.get_stats_for_user(user, request.user))
|
||||||
|
|
||||||
|
|
||||||
|
def _serialize_liked_content(self, elem, **kwargs):
|
||||||
|
if elem.get("type") == "project":
|
||||||
|
serializer = serializers.FanSerializer
|
||||||
|
else:
|
||||||
|
serializer = serializers.VotedSerializer
|
||||||
|
|
||||||
|
return serializer(elem, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
@detail_route(methods=["GET"])
|
@detail_route(methods=["GET"])
|
||||||
def favourites(self, request, *args, **kwargs):
|
def watched(self, request, *args, **kwargs):
|
||||||
for_user = get_object_or_404(models.User, **kwargs)
|
for_user = get_object_or_404(models.User, **kwargs)
|
||||||
from_user = request.user
|
from_user = request.user
|
||||||
self.check_permissions(request, 'favourites', for_user)
|
self.check_permissions(request, 'watched', for_user)
|
||||||
filters = {
|
filters = {
|
||||||
"type": request.GET.get("type", None),
|
"type": request.GET.get("type", None),
|
||||||
"action": request.GET.get("action", None),
|
|
||||||
"q": request.GET.get("q", None),
|
"q": request.GET.get("q", None),
|
||||||
}
|
}
|
||||||
|
|
||||||
self.object_list = services.get_favourites_list(for_user, from_user, **filters)
|
self.object_list = services.get_watched_list(for_user, from_user, **filters)
|
||||||
page = self.paginate_queryset(self.object_list)
|
page = self.paginate_queryset(self.object_list)
|
||||||
|
elements = page.object_list if page is not None else self.object_list
|
||||||
|
|
||||||
extra_args = {
|
extra_args = {
|
||||||
"many": True,
|
|
||||||
"user_votes": services.get_voted_content_for_user(request.user),
|
"user_votes": services.get_voted_content_for_user(request.user),
|
||||||
"user_watching": services.get_watched_content_for_user(request.user),
|
"user_watching": services.get_watched_content_for_user(request.user),
|
||||||
}
|
}
|
||||||
|
|
||||||
if page is not None:
|
response_data = [self._serialize_liked_content(elem, **extra_args).data for elem in elements]
|
||||||
serializer = serializers.FavouriteSerializer(page.object_list, **extra_args)
|
return response.Ok(response_data)
|
||||||
else:
|
|
||||||
serializer = serializers.FavouriteSerializer(self.object_list, **extra_args)
|
|
||||||
|
@detail_route(methods=["GET"])
|
||||||
|
def liked(self, request, *args, **kwargs):
|
||||||
|
for_user = get_object_or_404(models.User, **kwargs)
|
||||||
|
from_user = request.user
|
||||||
|
self.check_permissions(request, 'liked', for_user)
|
||||||
|
filters = {
|
||||||
|
"type": request.GET.get("type", None),
|
||||||
|
"q": request.GET.get("q", None),
|
||||||
|
}
|
||||||
|
|
||||||
|
self.object_list = services.get_voted_list(for_user, from_user, **filters)
|
||||||
|
page = self.paginate_queryset(self.object_list)
|
||||||
|
elements = page.object_list if page is not None else self.object_list
|
||||||
|
|
||||||
|
extra_args = {
|
||||||
|
"user_votes": services.get_voted_content_for_user(request.user),
|
||||||
|
"user_watching": services.get_watched_content_for_user(request.user),
|
||||||
|
}
|
||||||
|
|
||||||
|
response_data = [self._serialize_liked_content(elem, **extra_args).data for elem in elements]
|
||||||
|
|
||||||
|
return response.Ok(response_data)
|
||||||
|
|
||||||
return response.Ok(serializer.data)
|
|
||||||
|
|
||||||
@list_route(methods=["POST"])
|
@list_route(methods=["POST"])
|
||||||
def password_recovery(self, request, pk=None):
|
def password_recovery(self, request, pk=None):
|
||||||
|
|
|
@ -46,7 +46,8 @@ class UserPermission(TaigaResourcePermission):
|
||||||
remove_avatar_perms = IsAuthenticated()
|
remove_avatar_perms = IsAuthenticated()
|
||||||
change_email_perms = AllowAny()
|
change_email_perms = AllowAny()
|
||||||
contacts_perms = AllowAny()
|
contacts_perms = AllowAny()
|
||||||
favourites_perms = AllowAny()
|
liked_perms = AllowAny()
|
||||||
|
watched_perms = AllowAny()
|
||||||
|
|
||||||
|
|
||||||
class RolesPermission(TaigaResourcePermission):
|
class RolesPermission(TaigaResourcePermission):
|
||||||
|
|
|
@ -155,13 +155,12 @@ class ProjectRoleSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
######################################################
|
######################################################
|
||||||
## Favourite
|
## Like
|
||||||
######################################################
|
######################################################
|
||||||
|
|
||||||
|
|
||||||
class FavouriteSerializer(serializers.Serializer):
|
class LikeSerializer(serializers.Serializer):
|
||||||
type = serializers.CharField()
|
type = serializers.CharField()
|
||||||
action = serializers.CharField()
|
|
||||||
id = serializers.IntegerField()
|
id = serializers.IntegerField()
|
||||||
ref = serializers.IntegerField()
|
ref = serializers.IntegerField()
|
||||||
slug = serializers.CharField()
|
slug = serializers.CharField()
|
||||||
|
@ -175,11 +174,8 @@ class FavouriteSerializer(serializers.Serializer):
|
||||||
created_date = serializers.DateTimeField()
|
created_date = serializers.DateTimeField()
|
||||||
is_private = serializers.SerializerMethodField("get_is_private")
|
is_private = serializers.SerializerMethodField("get_is_private")
|
||||||
|
|
||||||
is_voted = serializers.SerializerMethodField("get_is_voted")
|
is_watcher = serializers.SerializerMethodField("get_is_watcher")
|
||||||
is_watched = serializers.SerializerMethodField("get_is_watched")
|
|
||||||
|
|
||||||
total_watchers = serializers.IntegerField()
|
total_watchers = serializers.IntegerField()
|
||||||
total_votes = serializers.IntegerField()
|
|
||||||
|
|
||||||
project = serializers.SerializerMethodField("get_project")
|
project = serializers.SerializerMethodField("get_project")
|
||||||
project_name = serializers.SerializerMethodField("get_project_name")
|
project_name = serializers.SerializerMethodField("get_project_name")
|
||||||
|
@ -196,7 +192,7 @@ class FavouriteSerializer(serializers.Serializer):
|
||||||
self.user_watching = kwargs.pop("user_watching", {})
|
self.user_watching = kwargs.pop("user_watching", {})
|
||||||
|
|
||||||
# Instantiate the superclass normally
|
# Instantiate the superclass normally
|
||||||
super(FavouriteSerializer, self).__init__(*args, **kwargs)
|
super(LikeSerializer, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
def _none_if_project(self, obj, property):
|
def _none_if_project(self, obj, property):
|
||||||
type = obj.get("type", "")
|
type = obj.get("type", "")
|
||||||
|
@ -230,10 +226,7 @@ class FavouriteSerializer(serializers.Serializer):
|
||||||
def get_project_is_private(self, obj):
|
def get_project_is_private(self, obj):
|
||||||
return self._none_if_project(obj, "project_is_private")
|
return self._none_if_project(obj, "project_is_private")
|
||||||
|
|
||||||
def get_is_voted(self, obj):
|
def get_is_watcher(self, obj):
|
||||||
return obj["id"] in self.user_votes.get(obj["type"], [])
|
|
||||||
|
|
||||||
def get_is_watched(self, obj):
|
|
||||||
return obj["id"] in self.user_watching.get(obj["type"], [])
|
return obj["id"] in self.user_watching.get(obj["type"], [])
|
||||||
|
|
||||||
def get_photo(self, obj):
|
def get_photo(self, obj):
|
||||||
|
@ -248,3 +241,19 @@ class FavouriteSerializer(serializers.Serializer):
|
||||||
def get_tags_color(self, obj):
|
def get_tags_color(self, obj):
|
||||||
tags = obj.get("tags", [])
|
tags = obj.get("tags", [])
|
||||||
return [{"name": tc[0], "color": tc[1]} for tc in obj.get("tags_colors", []) if tc[0] in tags]
|
return [{"name": tc[0], "color": tc[1]} for tc in obj.get("tags_colors", []) if tc[0] in tags]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class FanSerializer(LikeSerializer):
|
||||||
|
is_fan = serializers.SerializerMethodField("get_is_fan")
|
||||||
|
total_fans = serializers.IntegerField(source="total_voters")
|
||||||
|
|
||||||
|
def get_is_fan(self, obj):
|
||||||
|
return obj["id"] in self.user_votes.get(obj["type"], [])
|
||||||
|
|
||||||
|
class VotedSerializer(LikeSerializer):
|
||||||
|
is_voter = serializers.SerializerMethodField("get_is_voter")
|
||||||
|
total_voters = serializers.IntegerField()
|
||||||
|
|
||||||
|
def get_is_voter(self, obj):
|
||||||
|
return obj["id"] in self.user_votes.get(obj["type"], [])
|
||||||
|
|
|
@ -188,12 +188,12 @@ def get_watched_content_for_user(user):
|
||||||
return user_watches
|
return user_watches
|
||||||
|
|
||||||
|
|
||||||
def _build_favourites_sql_for_projects(for_user):
|
def _build_watched_sql_for_projects(for_user):
|
||||||
sql = """
|
sql = """
|
||||||
SELECT projects_project.id AS id, null AS ref, 'project' AS type, 'watch' AS action,
|
SELECT projects_project.id AS id, null AS ref, 'project' AS type,
|
||||||
tags, notifications_notifypolicy.project_id AS object_id, projects_project.id AS project,
|
tags, notifications_notifypolicy.project_id AS object_id, projects_project.id AS project,
|
||||||
slug AS slug, projects_project.name AS name, null AS subject,
|
slug AS slug, projects_project.name AS name, null AS subject,
|
||||||
notifications_notifypolicy.created_at as created_date, coalesce(watchers, 0) as total_watchers, coalesce(votes_votes.count, 0) total_votes, null AS assigned_to,
|
notifications_notifypolicy.created_at as created_date, coalesce(watchers, 0) as total_watchers, coalesce(votes_votes.count, 0) total_voters, null AS assigned_to,
|
||||||
null as status, null as status_color
|
null as status, null as status_color
|
||||||
FROM notifications_notifypolicy
|
FROM notifications_notifypolicy
|
||||||
INNER JOIN projects_project
|
INNER JOIN projects_project
|
||||||
|
@ -207,11 +207,20 @@ def _build_favourites_sql_for_projects(for_user):
|
||||||
LEFT JOIN votes_votes
|
LEFT JOIN votes_votes
|
||||||
ON (projects_project.id = votes_votes.object_id AND {project_content_type_id} = votes_votes.content_type_id)
|
ON (projects_project.id = votes_votes.object_id AND {project_content_type_id} = votes_votes.content_type_id)
|
||||||
WHERE notifications_notifypolicy.user_id = {for_user_id}
|
WHERE notifications_notifypolicy.user_id = {for_user_id}
|
||||||
UNION
|
"""
|
||||||
SELECT projects_project.id AS id, null AS ref, 'project' AS type, 'vote' AS action,
|
sql = sql.format(
|
||||||
|
for_user_id=for_user.id,
|
||||||
|
ignore_notify_level=NotifyLevel.ignore,
|
||||||
|
project_content_type_id=ContentType.objects.get(app_label="projects", model="project").id)
|
||||||
|
return sql
|
||||||
|
|
||||||
|
|
||||||
|
def _build_voted_sql_for_projects(for_user):
|
||||||
|
sql = """
|
||||||
|
SELECT projects_project.id AS id, null AS ref, 'project' AS type,
|
||||||
tags, votes_vote.object_id AS object_id, projects_project.id AS project,
|
tags, votes_vote.object_id AS object_id, projects_project.id AS project,
|
||||||
slug AS slug, projects_project.name AS name, null AS subject,
|
slug AS slug, projects_project.name AS name, null AS subject,
|
||||||
votes_vote.created_date, coalesce(watchers, 0) as total_watchers, coalesce(votes_votes.count, 0) total_votes, null AS assigned_to,
|
votes_vote.created_date, coalesce(watchers, 0) as total_watchers, coalesce(votes_votes.count, 0) total_voters, null AS assigned_to,
|
||||||
null as status, null as status_color
|
null as status, null as status_color
|
||||||
FROM votes_vote
|
FROM votes_vote
|
||||||
INNER JOIN projects_project
|
INNER JOIN projects_project
|
||||||
|
@ -233,65 +242,43 @@ def _build_favourites_sql_for_projects(for_user):
|
||||||
return sql
|
return sql
|
||||||
|
|
||||||
|
|
||||||
|
def _build_sql_for_type(for_user, type, table_name, action_table, ref_column="ref",
|
||||||
def _build_favourites_sql_for_type(for_user, type, table_name, ref_column="ref",
|
|
||||||
project_column="project_id", assigned_to_column="assigned_to_id",
|
project_column="project_id", assigned_to_column="assigned_to_id",
|
||||||
slug_column="slug", subject_column="subject"):
|
slug_column="slug", subject_column="subject"):
|
||||||
sql = """
|
sql = """
|
||||||
SELECT {table_name}.id AS id, {ref_column} AS ref, '{type}' AS type, 'watch' AS action,
|
SELECT {table_name}.id AS id, {ref_column} AS ref, '{type}' AS type,
|
||||||
tags, notifications_watched.object_id AS object_id, {table_name}.{project_column} AS project,
|
tags, {action_table}.object_id AS object_id, {table_name}.{project_column} AS project,
|
||||||
{slug_column} AS slug, null AS name, {subject_column} AS subject,
|
{slug_column} AS slug, null AS name, {subject_column} AS subject,
|
||||||
notifications_watched.created_date, coalesce(watchers, 0) as total_watchers, coalesce(votes_votes.count, 0) total_votes, {assigned_to_column} AS assigned_to,
|
{action_table}.created_date, coalesce(watchers, 0) as total_watchers, coalesce(votes_votes.count, 0) total_voters, {assigned_to_column} AS assigned_to,
|
||||||
projects_{type}status.name as status, projects_{type}status.color as status_color
|
projects_{type}status.name as status, projects_{type}status.color as status_color
|
||||||
FROM notifications_watched
|
FROM {action_table}
|
||||||
INNER JOIN django_content_type
|
INNER JOIN django_content_type
|
||||||
ON (notifications_watched.content_type_id = django_content_type.id AND django_content_type.model = '{type}')
|
ON ({action_table}.content_type_id = django_content_type.id AND django_content_type.model = '{type}')
|
||||||
INNER JOIN {table_name}
|
INNER JOIN {table_name}
|
||||||
ON ({table_name}.id = notifications_watched.object_id)
|
ON ({table_name}.id = {action_table}.object_id)
|
||||||
INNER JOIN projects_{type}status
|
INNER JOIN projects_{type}status
|
||||||
ON (projects_{type}status.id = {table_name}.status_id)
|
ON (projects_{type}status.id = {table_name}.status_id)
|
||||||
LEFT JOIN (SELECT object_id, content_type_id, count(*) watchers FROM notifications_watched GROUP BY object_id, content_type_id) type_watchers
|
LEFT JOIN (SELECT object_id, content_type_id, count(*) watchers FROM notifications_watched GROUP BY object_id, content_type_id) type_watchers
|
||||||
ON {table_name}.id = type_watchers.object_id AND django_content_type.id = type_watchers.content_type_id
|
ON {table_name}.id = type_watchers.object_id AND django_content_type.id = type_watchers.content_type_id
|
||||||
LEFT JOIN votes_votes
|
LEFT JOIN votes_votes
|
||||||
ON ({table_name}.id = votes_votes.object_id AND django_content_type.id = votes_votes.content_type_id)
|
ON ({table_name}.id = votes_votes.object_id AND django_content_type.id = votes_votes.content_type_id)
|
||||||
WHERE notifications_watched.user_id = {for_user_id}
|
WHERE {action_table}.user_id = {for_user_id}
|
||||||
UNION
|
|
||||||
SELECT {table_name}.id AS id, {ref_column} AS ref, '{type}' AS type, 'vote' AS action,
|
|
||||||
tags, votes_vote.object_id AS object_id, {table_name}.{project_column} AS project,
|
|
||||||
{slug_column} AS slug, null AS name, {subject_column} AS subject,
|
|
||||||
votes_vote.created_date, coalesce(watchers, 0) as total_watchers, votes_votes.count total_votes, {assigned_to_column} AS assigned_to,
|
|
||||||
projects_{type}status.name as status, projects_{type}status.color as status_color
|
|
||||||
FROM votes_vote
|
|
||||||
INNER JOIN django_content_type
|
|
||||||
ON (votes_vote.content_type_id = django_content_type.id AND django_content_type.model = '{type}')
|
|
||||||
INNER JOIN {table_name}
|
|
||||||
ON ({table_name}.id = votes_vote.object_id)
|
|
||||||
INNER JOIN projects_{type}status
|
|
||||||
ON (projects_{type}status.id = {table_name}.status_id)
|
|
||||||
LEFT JOIN (SELECT object_id, content_type_id, count(*) watchers FROM notifications_watched GROUP BY object_id, content_type_id) type_watchers
|
|
||||||
ON {table_name}.id = type_watchers.object_id AND django_content_type.id = type_watchers.content_type_id
|
|
||||||
LEFT JOIN votes_votes
|
|
||||||
ON ({table_name}.id = votes_votes.object_id AND django_content_type.id = votes_votes.content_type_id)
|
|
||||||
WHERE votes_vote.user_id = {for_user_id}
|
|
||||||
"""
|
"""
|
||||||
sql = sql.format(for_user_id=for_user.id, type=type, table_name=table_name,
|
sql = sql.format(for_user_id=for_user.id, type=type, table_name=table_name,
|
||||||
ref_column = ref_column, project_column=project_column,
|
action_table=action_table, ref_column = ref_column,
|
||||||
assigned_to_column=assigned_to_column, slug_column=slug_column,
|
project_column=project_column, assigned_to_column=assigned_to_column,
|
||||||
subject_column=subject_column)
|
slug_column=slug_column, subject_column=subject_column)
|
||||||
|
|
||||||
return sql
|
return sql
|
||||||
|
|
||||||
|
|
||||||
def get_favourites_list(for_user, from_user, type=None, action=None, q=None):
|
def _get_favourites_list(for_user, from_user, action_table, project_sql_builder, type=None, q=None):
|
||||||
filters_sql = ""
|
filters_sql = ""
|
||||||
and_needed = False
|
and_needed = False
|
||||||
|
|
||||||
if type:
|
if type:
|
||||||
filters_sql += " AND type = '{type}' ".format(type=type)
|
filters_sql += " AND type = '{type}' ".format(type=type)
|
||||||
|
|
||||||
if action:
|
|
||||||
filters_sql += " AND action = '{action}' ".format(action=action)
|
|
||||||
|
|
||||||
if q:
|
if q:
|
||||||
filters_sql += """ AND (
|
filters_sql += """ AND (
|
||||||
to_tsvector('english_nostop', coalesce(subject,'') || ' ' ||coalesce(entities.name,'') || ' ' ||coalesce(to_char(ref, '999'),'')) @@ to_tsquery('english_nostop', '{q}')
|
to_tsvector('english_nostop', coalesce(subject,'') || ' ' ||coalesce(entities.name,'') || ' ' ||coalesce(to_char(ref, '999'),'')) @@ to_tsquery('english_nostop', '{q}')
|
||||||
|
@ -361,10 +348,10 @@ def get_favourites_list(for_user, from_user, type=None, action=None, q=None):
|
||||||
for_user_id=for_user.id,
|
for_user_id=for_user.id,
|
||||||
from_user_id=from_user_id,
|
from_user_id=from_user_id,
|
||||||
filters_sql=filters_sql,
|
filters_sql=filters_sql,
|
||||||
userstories_sql=_build_favourites_sql_for_type(for_user, "userstory", "userstories_userstory", slug_column="null"),
|
userstories_sql=_build_sql_for_type(for_user, "userstory", "userstories_userstory", action_table, slug_column="null"),
|
||||||
tasks_sql=_build_favourites_sql_for_type(for_user, "task", "tasks_task", slug_column="null"),
|
tasks_sql=_build_sql_for_type(for_user, "task", "tasks_task", action_table, slug_column="null"),
|
||||||
issues_sql=_build_favourites_sql_for_type(for_user, "issue", "issues_issue", slug_column="null"),
|
issues_sql=_build_sql_for_type(for_user, "issue", "issues_issue", action_table, slug_column="null"),
|
||||||
projects_sql=_build_favourites_sql_for_projects(for_user))
|
projects_sql=project_sql_builder(for_user))
|
||||||
|
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
cursor.execute(sql)
|
cursor.execute(sql)
|
||||||
|
@ -374,3 +361,11 @@ def get_favourites_list(for_user, from_user, type=None, action=None, q=None):
|
||||||
dict(zip([col[0] for col in desc], row))
|
dict(zip([col[0] for col in desc], row))
|
||||||
for row in cursor.fetchall()
|
for row in cursor.fetchall()
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def get_watched_list(for_user, from_user, type=None, q=None):
|
||||||
|
return _get_favourites_list(for_user, from_user, "notifications_watched", _build_watched_sql_for_projects, type=type, q=q)
|
||||||
|
|
||||||
|
|
||||||
|
def get_voted_list(for_user, from_user, type=None, q=None):
|
||||||
|
return _get_favourites_list(for_user, from_user, "votes_vote", _build_voted_sql_for_projects, type=type, q=q)
|
||||||
|
|
|
@ -25,7 +25,7 @@ from taiga.projects.issues import models as issue_models
|
||||||
from taiga.projects.milestones import models as milestone_models
|
from taiga.projects.milestones import models as milestone_models
|
||||||
from taiga.projects.wiki import models as wiki_models
|
from taiga.projects.wiki import models as wiki_models
|
||||||
from taiga.projects.history import models as history_models
|
from taiga.projects.history import models as history_models
|
||||||
from taiga.projects.notifications.mixins import WatchedResourceModelSerializer
|
from taiga.projects.notifications.mixins import EditableWatchedResourceModelSerializer
|
||||||
|
|
||||||
from .models import Webhook, WebhookLog
|
from .models import Webhook, WebhookLog
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ class PointSerializer(serializers.Serializer):
|
||||||
return obj.value
|
return obj.value
|
||||||
|
|
||||||
|
|
||||||
class UserStorySerializer(CustomAttributesValuesWebhookSerializerMixin, WatchedResourceModelSerializer,
|
class UserStorySerializer(CustomAttributesValuesWebhookSerializerMixin, EditableWatchedResourceModelSerializer,
|
||||||
serializers.ModelSerializer):
|
serializers.ModelSerializer):
|
||||||
tags = TagsField(default=[], required=False)
|
tags = TagsField(default=[], required=False)
|
||||||
external_reference = PgArrayField(required=False)
|
external_reference = PgArrayField(required=False)
|
||||||
|
@ -121,7 +121,7 @@ class UserStorySerializer(CustomAttributesValuesWebhookSerializerMixin, WatchedR
|
||||||
return project.userstorycustomattributes.all()
|
return project.userstorycustomattributes.all()
|
||||||
|
|
||||||
|
|
||||||
class TaskSerializer(CustomAttributesValuesWebhookSerializerMixin, WatchedResourceModelSerializer,
|
class TaskSerializer(CustomAttributesValuesWebhookSerializerMixin, EditableWatchedResourceModelSerializer,
|
||||||
serializers.ModelSerializer):
|
serializers.ModelSerializer):
|
||||||
tags = TagsField(default=[], required=False)
|
tags = TagsField(default=[], required=False)
|
||||||
owner = UserSerializer()
|
owner = UserSerializer()
|
||||||
|
@ -135,7 +135,7 @@ class TaskSerializer(CustomAttributesValuesWebhookSerializerMixin, WatchedResour
|
||||||
return project.taskcustomattributes.all()
|
return project.taskcustomattributes.all()
|
||||||
|
|
||||||
|
|
||||||
class IssueSerializer(CustomAttributesValuesWebhookSerializerMixin, WatchedResourceModelSerializer,
|
class IssueSerializer(CustomAttributesValuesWebhookSerializerMixin, EditableWatchedResourceModelSerializer,
|
||||||
serializers.ModelSerializer):
|
serializers.ModelSerializer):
|
||||||
tags = TagsField(default=[], required=False)
|
tags = TagsField(default=[], required=False)
|
||||||
owner = UserSerializer()
|
owner = UserSerializer()
|
||||||
|
|
|
@ -289,8 +289,20 @@ def test_user_action_change_email(client, data):
|
||||||
assert results == [204, 204, 204]
|
assert results == [204, 204, 204]
|
||||||
|
|
||||||
|
|
||||||
def test_user_list_votes(client, data):
|
def test_user_list_watched(client, data):
|
||||||
url = reverse('users-favourites', kwargs={"pk": data.registered_user.pk})
|
url = reverse('users-watched', kwargs={"pk": data.registered_user.pk})
|
||||||
|
users = [
|
||||||
|
None,
|
||||||
|
data.registered_user,
|
||||||
|
data.other_user,
|
||||||
|
data.superuser,
|
||||||
|
]
|
||||||
|
results = helper_test_http_method(client, 'get', url, None, users)
|
||||||
|
assert results == [200, 200, 200, 200]
|
||||||
|
|
||||||
|
|
||||||
|
def test_user_list_liked(client, data):
|
||||||
|
url = reverse('users-liked', kwargs={"pk": data.registered_user.pk})
|
||||||
users = [
|
users = [
|
||||||
None,
|
None,
|
||||||
data.registered_user,
|
data.registered_user,
|
||||||
|
|
|
@ -1,123 +0,0 @@
|
||||||
# Copyright (C) 2015 Andrey Antukh <niwi@niwi.be>
|
|
||||||
# Copyright (C) 2015 Jesús Espino <jespinog@gmail.com>
|
|
||||||
# Copyright (C) 2015 David Barragán <bameda@dbarragan.com>
|
|
||||||
# Copyright (C) 2015 Anler Hernández <hello@anler.me>
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Affero General Public License as
|
|
||||||
# published by the Free Software Foundation, either version 3 of the
|
|
||||||
# License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
from django.core.urlresolvers import reverse
|
|
||||||
|
|
||||||
from .. import factories as f
|
|
||||||
|
|
||||||
pytestmark = pytest.mark.django_db
|
|
||||||
|
|
||||||
|
|
||||||
def test_like_project(client):
|
|
||||||
user = f.UserFactory.create()
|
|
||||||
project = f.create_project(owner=user)
|
|
||||||
f.MembershipFactory.create(project=project, user=user, is_owner=True)
|
|
||||||
url = reverse("projects-like", args=(project.id,))
|
|
||||||
|
|
||||||
client.login(user)
|
|
||||||
response = client.post(url)
|
|
||||||
|
|
||||||
assert response.status_code == 200
|
|
||||||
|
|
||||||
|
|
||||||
def test_unlike_project(client):
|
|
||||||
user = f.UserFactory.create()
|
|
||||||
project = f.create_project(owner=user)
|
|
||||||
f.MembershipFactory.create(project=project, user=user, is_owner=True)
|
|
||||||
url = reverse("projects-unlike", args=(project.id,))
|
|
||||||
|
|
||||||
client.login(user)
|
|
||||||
response = client.post(url)
|
|
||||||
|
|
||||||
assert response.status_code == 200
|
|
||||||
|
|
||||||
|
|
||||||
def test_list_project_fans(client):
|
|
||||||
user = f.UserFactory.create()
|
|
||||||
project = f.create_project(owner=user)
|
|
||||||
f.MembershipFactory.create(project=project, user=user, is_owner=True)
|
|
||||||
f.VoteFactory.create(content_object=project, user=user)
|
|
||||||
url = reverse("project-fans-list", args=(project.id,))
|
|
||||||
|
|
||||||
client.login(user)
|
|
||||||
response = client.get(url)
|
|
||||||
|
|
||||||
assert response.status_code == 200
|
|
||||||
assert response.data[0]['id'] == user.id
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_project_fan(client):
|
|
||||||
user = f.UserFactory.create()
|
|
||||||
project = f.create_project(owner=user)
|
|
||||||
f.MembershipFactory.create(project=project, user=user, is_owner=True)
|
|
||||||
vote = f.VoteFactory.create(content_object=project, user=user)
|
|
||||||
url = reverse("project-fans-detail", args=(project.id, vote.user.id))
|
|
||||||
|
|
||||||
client.login(user)
|
|
||||||
response = client.get(url)
|
|
||||||
|
|
||||||
assert response.status_code == 200
|
|
||||||
assert response.data['id'] == vote.user.id
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_project_likes(client):
|
|
||||||
user = f.UserFactory.create()
|
|
||||||
project = f.create_project(owner=user)
|
|
||||||
f.MembershipFactory.create(project=project, user=user, is_owner=True)
|
|
||||||
url = reverse("projects-detail", args=(project.id,))
|
|
||||||
|
|
||||||
f.VotesFactory.create(content_object=project, count=5)
|
|
||||||
|
|
||||||
client.login(user)
|
|
||||||
response = client.get(url)
|
|
||||||
|
|
||||||
assert response.status_code == 200
|
|
||||||
assert response.data['likes'] == 5
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_project_is_liked(client):
|
|
||||||
user = f.UserFactory.create()
|
|
||||||
project = f.create_project(owner=user)
|
|
||||||
f.MembershipFactory.create(project=project, user=user, is_owner=True)
|
|
||||||
f.VotesFactory.create(content_object=project)
|
|
||||||
url_detail = reverse("projects-detail", args=(project.id,))
|
|
||||||
url_like = reverse("projects-like", args=(project.id,))
|
|
||||||
url_unlike = reverse("projects-unlike", args=(project.id,))
|
|
||||||
|
|
||||||
client.login(user)
|
|
||||||
|
|
||||||
response = client.get(url_detail)
|
|
||||||
assert response.status_code == 200
|
|
||||||
assert response.data['likes'] == 0
|
|
||||||
assert response.data['is_liked'] == False
|
|
||||||
|
|
||||||
response = client.post(url_like)
|
|
||||||
assert response.status_code == 200
|
|
||||||
|
|
||||||
response = client.get(url_detail)
|
|
||||||
assert response.status_code == 200
|
|
||||||
assert response.data['likes'] == 1
|
|
||||||
assert response.data['is_liked'] == True
|
|
||||||
|
|
||||||
response = client.post(url_unlike)
|
|
||||||
assert response.status_code == 200
|
|
||||||
|
|
||||||
response = client.get(url_detail)
|
|
||||||
assert response.status_code == 200
|
|
||||||
assert response.data['likes'] == 0
|
|
||||||
assert response.data['is_liked'] == False
|
|
|
@ -9,10 +9,10 @@ from .. import factories as f
|
||||||
|
|
||||||
from taiga.base.utils import json
|
from taiga.base.utils import json
|
||||||
from taiga.users import models
|
from taiga.users import models
|
||||||
from taiga.users.serializers import FavouriteSerializer
|
from taiga.users.serializers import FanSerializer, VotedSerializer
|
||||||
from taiga.auth.tokens import get_token_for_user
|
from taiga.auth.tokens import get_token_for_user
|
||||||
from taiga.permissions.permissions import MEMBERS_PERMISSIONS, ANON_PERMISSIONS, USER_PERMISSIONS
|
from taiga.permissions.permissions import MEMBERS_PERMISSIONS, ANON_PERMISSIONS, USER_PERMISSIONS
|
||||||
from taiga.users.services import get_favourites_list
|
from taiga.users.services import get_watched_list, get_voted_list
|
||||||
|
|
||||||
from easy_thumbnails.files import generate_all_aliases, get_thumbnailer
|
from easy_thumbnails.files import generate_all_aliases, get_thumbnailer
|
||||||
|
|
||||||
|
@ -348,7 +348,7 @@ def test_mail_permissions(client):
|
||||||
assert "email" in response.data
|
assert "email" in response.data
|
||||||
|
|
||||||
|
|
||||||
def test_get_favourites_list():
|
def test_get_watched_list():
|
||||||
fav_user = f.UserFactory()
|
fav_user = f.UserFactory()
|
||||||
viewer_user = f.UserFactory()
|
viewer_user = f.UserFactory()
|
||||||
|
|
||||||
|
@ -356,58 +356,117 @@ def test_get_favourites_list():
|
||||||
role = f.RoleFactory(project=project, permissions=["view_project", "view_us", "view_tasks", "view_issues"])
|
role = f.RoleFactory(project=project, permissions=["view_project", "view_us", "view_tasks", "view_issues"])
|
||||||
membership = f.MembershipFactory(project=project, role=role, user=fav_user)
|
membership = f.MembershipFactory(project=project, role=role, user=fav_user)
|
||||||
project.add_watcher(fav_user)
|
project.add_watcher(fav_user)
|
||||||
|
|
||||||
|
user_story = f.UserStoryFactory(project=project, subject="Testing user story")
|
||||||
|
user_story.add_watcher(fav_user)
|
||||||
|
|
||||||
|
task = f.TaskFactory(project=project, subject="Testing task")
|
||||||
|
task.add_watcher(fav_user)
|
||||||
|
|
||||||
|
issue = f.IssueFactory(project=project, subject="Testing issue")
|
||||||
|
issue.add_watcher(fav_user)
|
||||||
|
|
||||||
|
assert len(get_watched_list(fav_user, viewer_user)) == 4
|
||||||
|
assert len(get_watched_list(fav_user, viewer_user, type="project")) == 1
|
||||||
|
assert len(get_watched_list(fav_user, viewer_user, type="userstory")) == 1
|
||||||
|
assert len(get_watched_list(fav_user, viewer_user, type="task")) == 1
|
||||||
|
assert len(get_watched_list(fav_user, viewer_user, type="issue")) == 1
|
||||||
|
assert len(get_watched_list(fav_user, viewer_user, type="unknown")) == 0
|
||||||
|
|
||||||
|
assert len(get_watched_list(fav_user, viewer_user, q="issue")) == 1
|
||||||
|
assert len(get_watched_list(fav_user, viewer_user, q="unexisting text")) == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_voted_list():
|
||||||
|
fav_user = f.UserFactory()
|
||||||
|
viewer_user = f.UserFactory()
|
||||||
|
|
||||||
|
project = f.ProjectFactory(is_private=False, name="Testing project")
|
||||||
|
role = f.RoleFactory(project=project, permissions=["view_project", "view_us", "view_tasks", "view_issues"])
|
||||||
|
membership = f.MembershipFactory(project=project, role=role, user=fav_user)
|
||||||
content_type = ContentType.objects.get_for_model(project)
|
content_type = ContentType.objects.get_for_model(project)
|
||||||
f.VoteFactory(content_type=content_type, object_id=project.id, user=fav_user)
|
f.VoteFactory(content_type=content_type, object_id=project.id, user=fav_user)
|
||||||
f.VotesFactory(content_type=content_type, object_id=project.id, count=1)
|
f.VotesFactory(content_type=content_type, object_id=project.id, count=1)
|
||||||
|
|
||||||
user_story = f.UserStoryFactory(project=project, subject="Testing user story")
|
user_story = f.UserStoryFactory(project=project, subject="Testing user story")
|
||||||
user_story.add_watcher(fav_user)
|
|
||||||
content_type = ContentType.objects.get_for_model(user_story)
|
content_type = ContentType.objects.get_for_model(user_story)
|
||||||
f.VoteFactory(content_type=content_type, object_id=user_story.id, user=fav_user)
|
f.VoteFactory(content_type=content_type, object_id=user_story.id, user=fav_user)
|
||||||
f.VotesFactory(content_type=content_type, object_id=user_story.id, count=1)
|
f.VotesFactory(content_type=content_type, object_id=user_story.id, count=1)
|
||||||
|
|
||||||
task = f.TaskFactory(project=project, subject="Testing task")
|
task = f.TaskFactory(project=project, subject="Testing task")
|
||||||
task.add_watcher(fav_user)
|
|
||||||
content_type = ContentType.objects.get_for_model(task)
|
content_type = ContentType.objects.get_for_model(task)
|
||||||
f.VoteFactory(content_type=content_type, object_id=task.id, user=fav_user)
|
f.VoteFactory(content_type=content_type, object_id=task.id, user=fav_user)
|
||||||
f.VotesFactory(content_type=content_type, object_id=task.id, count=1)
|
f.VotesFactory(content_type=content_type, object_id=task.id, count=1)
|
||||||
|
|
||||||
issue = f.IssueFactory(project=project, subject="Testing issue")
|
issue = f.IssueFactory(project=project, subject="Testing issue")
|
||||||
issue.add_watcher(fav_user)
|
|
||||||
content_type = ContentType.objects.get_for_model(issue)
|
content_type = ContentType.objects.get_for_model(issue)
|
||||||
f.VoteFactory(content_type=content_type, object_id=issue.id, user=fav_user)
|
f.VoteFactory(content_type=content_type, object_id=issue.id, user=fav_user)
|
||||||
f.VotesFactory(content_type=content_type, object_id=issue.id, count=1)
|
f.VotesFactory(content_type=content_type, object_id=issue.id, count=1)
|
||||||
|
|
||||||
assert len(get_favourites_list(fav_user, viewer_user)) == 8
|
assert len(get_voted_list(fav_user, viewer_user)) == 4
|
||||||
assert len(get_favourites_list(fav_user, viewer_user, type="project")) == 2
|
assert len(get_voted_list(fav_user, viewer_user, type="project")) == 1
|
||||||
assert len(get_favourites_list(fav_user, viewer_user, type="userstory")) == 2
|
assert len(get_voted_list(fav_user, viewer_user, type="userstory")) == 1
|
||||||
assert len(get_favourites_list(fav_user, viewer_user, type="task")) == 2
|
assert len(get_voted_list(fav_user, viewer_user, type="task")) == 1
|
||||||
assert len(get_favourites_list(fav_user, viewer_user, type="issue")) == 2
|
assert len(get_voted_list(fav_user, viewer_user, type="issue")) == 1
|
||||||
assert len(get_favourites_list(fav_user, viewer_user, type="unknown")) == 0
|
assert len(get_voted_list(fav_user, viewer_user, type="unknown")) == 0
|
||||||
|
|
||||||
assert len(get_favourites_list(fav_user, viewer_user, action="watch")) == 4
|
assert len(get_voted_list(fav_user, viewer_user, q="issue")) == 1
|
||||||
assert len(get_favourites_list(fav_user, viewer_user, action="vote")) == 4
|
assert len(get_voted_list(fav_user, viewer_user, q="unexisting text")) == 0
|
||||||
|
|
||||||
assert len(get_favourites_list(fav_user, viewer_user, q="issue")) == 2
|
|
||||||
assert len(get_favourites_list(fav_user, viewer_user, q="unexisting text")) == 0
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_favourites_list_valid_info_for_project():
|
def test_get_watched_list_valid_info_for_project():
|
||||||
|
fav_user = f.UserFactory()
|
||||||
|
viewer_user = f.UserFactory()
|
||||||
|
|
||||||
|
project = f.ProjectFactory(is_private=False, name="Testing project", tags=['test', 'tag'])
|
||||||
|
role = f.RoleFactory(project=project, permissions=["view_project", "view_us", "view_tasks", "view_issues"])
|
||||||
|
project.add_watcher(fav_user)
|
||||||
|
|
||||||
|
raw_project_watch_info = get_watched_list(fav_user, viewer_user)[0]
|
||||||
|
project_watch_info = FanSerializer(raw_project_watch_info).data
|
||||||
|
|
||||||
|
assert project_watch_info["type"] == "project"
|
||||||
|
assert project_watch_info["id"] == project.id
|
||||||
|
assert project_watch_info["ref"] == None
|
||||||
|
assert project_watch_info["slug"] == project.slug
|
||||||
|
assert project_watch_info["name"] == project.name
|
||||||
|
assert project_watch_info["subject"] == None
|
||||||
|
assert project_watch_info["description"] == project.description
|
||||||
|
assert project_watch_info["assigned_to"] == None
|
||||||
|
assert project_watch_info["status"] == None
|
||||||
|
assert project_watch_info["status_color"] == None
|
||||||
|
|
||||||
|
tags_colors = {tc["name"]:tc["color"] for tc in project_watch_info["tags_colors"]}
|
||||||
|
assert "test" in tags_colors
|
||||||
|
assert "tag" in tags_colors
|
||||||
|
|
||||||
|
assert project_watch_info["is_private"] == project.is_private
|
||||||
|
assert project_watch_info["is_fan"] == False
|
||||||
|
assert project_watch_info["is_watcher"] == False
|
||||||
|
assert project_watch_info["total_watchers"] == 1
|
||||||
|
assert project_watch_info["total_fans"] == 0
|
||||||
|
assert project_watch_info["project"] == None
|
||||||
|
assert project_watch_info["project_name"] == None
|
||||||
|
assert project_watch_info["project_slug"] == None
|
||||||
|
assert project_watch_info["project_is_private"] == None
|
||||||
|
assert project_watch_info["assigned_to_username"] == None
|
||||||
|
assert project_watch_info["assigned_to_full_name"] == None
|
||||||
|
assert project_watch_info["assigned_to_photo"] == None
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_voted_list_valid_info_for_project():
|
||||||
fav_user = f.UserFactory()
|
fav_user = f.UserFactory()
|
||||||
viewer_user = f.UserFactory()
|
viewer_user = f.UserFactory()
|
||||||
watcher_user = f.UserFactory()
|
|
||||||
|
|
||||||
project = f.ProjectFactory(is_private=False, name="Testing project", tags=['test', 'tag'])
|
project = f.ProjectFactory(is_private=False, name="Testing project", tags=['test', 'tag'])
|
||||||
project.add_watcher(watcher_user)
|
|
||||||
content_type = ContentType.objects.get_for_model(project)
|
content_type = ContentType.objects.get_for_model(project)
|
||||||
vote = f.VoteFactory(content_type=content_type, object_id=project.id, user=fav_user)
|
vote = f.VoteFactory(content_type=content_type, object_id=project.id, user=fav_user)
|
||||||
f.VotesFactory(content_type=content_type, object_id=project.id, count=1)
|
f.VotesFactory(content_type=content_type, object_id=project.id, count=1)
|
||||||
|
|
||||||
raw_project_vote_info = get_favourites_list(fav_user, viewer_user)[0]
|
raw_project_vote_info = get_voted_list(fav_user, viewer_user)[0]
|
||||||
project_vote_info = FavouriteSerializer(raw_project_vote_info).data
|
project_vote_info = FanSerializer(raw_project_vote_info).data
|
||||||
|
|
||||||
assert project_vote_info["type"] == "project"
|
assert project_vote_info["type"] == "project"
|
||||||
assert project_vote_info["action"] == "vote"
|
|
||||||
assert project_vote_info["id"] == project.id
|
assert project_vote_info["id"] == project.id
|
||||||
assert project_vote_info["ref"] == None
|
assert project_vote_info["ref"] == None
|
||||||
assert project_vote_info["slug"] == project.slug
|
assert project_vote_info["slug"] == project.slug
|
||||||
|
@ -423,10 +482,14 @@ def test_get_favourites_list_valid_info_for_project():
|
||||||
assert "tag" in tags_colors
|
assert "tag" in tags_colors
|
||||||
|
|
||||||
assert project_vote_info["is_private"] == project.is_private
|
assert project_vote_info["is_private"] == project.is_private
|
||||||
assert project_vote_info["is_voted"] == False
|
|
||||||
assert project_vote_info["is_watched"] == False
|
import pprint
|
||||||
assert project_vote_info["total_watchers"] == 1
|
pprint.pprint(project_vote_info)
|
||||||
assert project_vote_info["total_votes"] == 1
|
|
||||||
|
assert project_vote_info["is_fan"] == False
|
||||||
|
assert project_vote_info["is_watcher"] == False
|
||||||
|
assert project_vote_info["total_watchers"] == 0
|
||||||
|
assert project_vote_info["total_fans"] == 1
|
||||||
assert project_vote_info["project"] == None
|
assert project_vote_info["project"] == None
|
||||||
assert project_vote_info["project_name"] == None
|
assert project_vote_info["project_name"] == None
|
||||||
assert project_vote_info["project_slug"] == None
|
assert project_vote_info["project_slug"] == None
|
||||||
|
@ -436,10 +499,61 @@ def test_get_favourites_list_valid_info_for_project():
|
||||||
assert project_vote_info["assigned_to_photo"] == None
|
assert project_vote_info["assigned_to_photo"] == None
|
||||||
|
|
||||||
|
|
||||||
def test_get_favourites_list_valid_info_for_not_project_types():
|
def test_get_watched_list_valid_info_for_not_project_types():
|
||||||
|
fav_user = f.UserFactory()
|
||||||
|
viewer_user = f.UserFactory()
|
||||||
|
assigned_to_user = f.UserFactory()
|
||||||
|
|
||||||
|
project = f.ProjectFactory(is_private=False, name="Testing project")
|
||||||
|
|
||||||
|
factories = {
|
||||||
|
"userstory": f.UserStoryFactory,
|
||||||
|
"task": f.TaskFactory,
|
||||||
|
"issue": f.IssueFactory
|
||||||
|
}
|
||||||
|
|
||||||
|
for object_type in factories:
|
||||||
|
instance = factories[object_type](project=project,
|
||||||
|
subject="Testing",
|
||||||
|
tags=["test1", "test2"],
|
||||||
|
assigned_to=assigned_to_user)
|
||||||
|
|
||||||
|
instance.add_watcher(fav_user)
|
||||||
|
raw_instance_watch_info = get_watched_list(fav_user, viewer_user, type=object_type)[0]
|
||||||
|
instance_watch_info = VotedSerializer(raw_instance_watch_info).data
|
||||||
|
|
||||||
|
assert instance_watch_info["type"] == object_type
|
||||||
|
assert instance_watch_info["id"] == instance.id
|
||||||
|
assert instance_watch_info["ref"] == instance.ref
|
||||||
|
assert instance_watch_info["slug"] == None
|
||||||
|
assert instance_watch_info["name"] == None
|
||||||
|
assert instance_watch_info["subject"] == instance.subject
|
||||||
|
assert instance_watch_info["description"] == None
|
||||||
|
assert instance_watch_info["assigned_to"] == instance.assigned_to.id
|
||||||
|
assert instance_watch_info["status"] == instance.status.name
|
||||||
|
assert instance_watch_info["status_color"] == instance.status.color
|
||||||
|
|
||||||
|
tags_colors = {tc["name"]:tc["color"] for tc in instance_watch_info["tags_colors"]}
|
||||||
|
assert "test1" in tags_colors
|
||||||
|
assert "test2" in tags_colors
|
||||||
|
|
||||||
|
assert instance_watch_info["is_private"] == None
|
||||||
|
assert instance_watch_info["is_voter"] == False
|
||||||
|
assert instance_watch_info["is_watcher"] == False
|
||||||
|
assert instance_watch_info["total_watchers"] == 1
|
||||||
|
assert instance_watch_info["total_voters"] == 0
|
||||||
|
assert instance_watch_info["project"] == instance.project.id
|
||||||
|
assert instance_watch_info["project_name"] == instance.project.name
|
||||||
|
assert instance_watch_info["project_slug"] == instance.project.slug
|
||||||
|
assert instance_watch_info["project_is_private"] == instance.project.is_private
|
||||||
|
assert instance_watch_info["assigned_to_username"] == instance.assigned_to.username
|
||||||
|
assert instance_watch_info["assigned_to_full_name"] == instance.assigned_to.full_name
|
||||||
|
assert instance_watch_info["assigned_to_photo"] != ""
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_voted_list_valid_info_for_not_project_types():
|
||||||
fav_user = f.UserFactory()
|
fav_user = f.UserFactory()
|
||||||
viewer_user = f.UserFactory()
|
viewer_user = f.UserFactory()
|
||||||
watcher_user = f.UserFactory()
|
|
||||||
assigned_to_user = f.UserFactory()
|
assigned_to_user = f.UserFactory()
|
||||||
|
|
||||||
project = f.ProjectFactory(is_private=False, name="Testing project")
|
project = f.ProjectFactory(is_private=False, name="Testing project")
|
||||||
|
@ -456,16 +570,14 @@ def test_get_favourites_list_valid_info_for_not_project_types():
|
||||||
tags=["test1", "test2"],
|
tags=["test1", "test2"],
|
||||||
assigned_to=assigned_to_user)
|
assigned_to=assigned_to_user)
|
||||||
|
|
||||||
instance.add_watcher(watcher_user)
|
|
||||||
content_type = ContentType.objects.get_for_model(instance)
|
content_type = ContentType.objects.get_for_model(instance)
|
||||||
vote = f.VoteFactory(content_type=content_type, object_id=instance.id, user=fav_user)
|
vote = f.VoteFactory(content_type=content_type, object_id=instance.id, user=fav_user)
|
||||||
f.VotesFactory(content_type=content_type, object_id=instance.id, count=3)
|
f.VotesFactory(content_type=content_type, object_id=instance.id, count=3)
|
||||||
|
|
||||||
raw_instance_vote_info = get_favourites_list(fav_user, viewer_user, type=object_type)[0]
|
raw_instance_vote_info = get_voted_list(fav_user, viewer_user, type=object_type)[0]
|
||||||
instance_vote_info = FavouriteSerializer(raw_instance_vote_info).data
|
instance_vote_info = VotedSerializer(raw_instance_vote_info).data
|
||||||
|
|
||||||
assert instance_vote_info["type"] == object_type
|
assert instance_vote_info["type"] == object_type
|
||||||
assert instance_vote_info["action"] == "vote"
|
|
||||||
assert instance_vote_info["id"] == instance.id
|
assert instance_vote_info["id"] == instance.id
|
||||||
assert instance_vote_info["ref"] == instance.ref
|
assert instance_vote_info["ref"] == instance.ref
|
||||||
assert instance_vote_info["slug"] == None
|
assert instance_vote_info["slug"] == None
|
||||||
|
@ -481,10 +593,10 @@ def test_get_favourites_list_valid_info_for_not_project_types():
|
||||||
assert "test2" in tags_colors
|
assert "test2" in tags_colors
|
||||||
|
|
||||||
assert instance_vote_info["is_private"] == None
|
assert instance_vote_info["is_private"] == None
|
||||||
assert instance_vote_info["is_voted"] == False
|
assert instance_vote_info["is_voter"] == False
|
||||||
assert instance_vote_info["is_watched"] == False
|
assert instance_vote_info["is_watcher"] == False
|
||||||
assert instance_vote_info["total_watchers"] == 1
|
assert instance_vote_info["total_watchers"] == 0
|
||||||
assert instance_vote_info["total_votes"] == 3
|
assert instance_vote_info["total_voters"] == 3
|
||||||
assert instance_vote_info["project"] == instance.project.id
|
assert instance_vote_info["project"] == instance.project.id
|
||||||
assert instance_vote_info["project_name"] == instance.project.name
|
assert instance_vote_info["project_name"] == instance.project.name
|
||||||
assert instance_vote_info["project_slug"] == instance.project.slug
|
assert instance_vote_info["project_slug"] == instance.project.slug
|
||||||
|
@ -494,7 +606,41 @@ def test_get_favourites_list_valid_info_for_not_project_types():
|
||||||
assert instance_vote_info["assigned_to_photo"] != ""
|
assert instance_vote_info["assigned_to_photo"] != ""
|
||||||
|
|
||||||
|
|
||||||
def test_get_favourites_list_permissions():
|
def test_get_watched_list_permissions():
|
||||||
|
fav_user = f.UserFactory()
|
||||||
|
viewer_unpriviliged_user = f.UserFactory()
|
||||||
|
viewer_priviliged_user = f.UserFactory()
|
||||||
|
|
||||||
|
project = f.ProjectFactory(is_private=True, name="Testing project")
|
||||||
|
project.add_watcher(fav_user)
|
||||||
|
role = f.RoleFactory(project=project, permissions=["view_project", "view_us", "view_tasks", "view_issues"])
|
||||||
|
membership = f.MembershipFactory(project=project, role=role, user=viewer_priviliged_user)
|
||||||
|
|
||||||
|
user_story = f.UserStoryFactory(project=project, subject="Testing user story")
|
||||||
|
user_story.add_watcher(fav_user)
|
||||||
|
|
||||||
|
task = f.TaskFactory(project=project, subject="Testing task")
|
||||||
|
task.add_watcher(fav_user)
|
||||||
|
|
||||||
|
issue = f.IssueFactory(project=project, subject="Testing issue")
|
||||||
|
issue.add_watcher(fav_user)
|
||||||
|
|
||||||
|
#If the project is private a viewer user without any permission shouldn' see
|
||||||
|
# any vote
|
||||||
|
assert len(get_watched_list(fav_user, viewer_unpriviliged_user)) == 0
|
||||||
|
|
||||||
|
#If the project is private but the viewer user has permissions the votes should
|
||||||
|
# be accesible
|
||||||
|
assert len(get_watched_list(fav_user, viewer_priviliged_user)) == 4
|
||||||
|
|
||||||
|
#If the project is private but has the required anon permissions the votes should
|
||||||
|
# be accesible by any user too
|
||||||
|
project.anon_permissions = ["view_project", "view_us", "view_tasks", "view_issues"]
|
||||||
|
project.save()
|
||||||
|
assert len(get_watched_list(fav_user, viewer_unpriviliged_user)) == 4
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_voted_list_permissions():
|
||||||
fav_user = f.UserFactory()
|
fav_user = f.UserFactory()
|
||||||
viewer_unpriviliged_user = f.UserFactory()
|
viewer_unpriviliged_user = f.UserFactory()
|
||||||
viewer_priviliged_user = f.UserFactory()
|
viewer_priviliged_user = f.UserFactory()
|
||||||
|
@ -523,14 +669,14 @@ def test_get_favourites_list_permissions():
|
||||||
|
|
||||||
#If the project is private a viewer user without any permission shouldn' see
|
#If the project is private a viewer user without any permission shouldn' see
|
||||||
# any vote
|
# any vote
|
||||||
assert len(get_favourites_list(fav_user, viewer_unpriviliged_user)) == 0
|
assert len(get_voted_list(fav_user, viewer_unpriviliged_user)) == 0
|
||||||
|
|
||||||
#If the project is private but the viewer user has permissions the votes should
|
#If the project is private but the viewer user has permissions the votes should
|
||||||
# be accesible
|
# be accesible
|
||||||
assert len(get_favourites_list(fav_user, viewer_priviliged_user)) == 4
|
assert len(get_voted_list(fav_user, viewer_priviliged_user)) == 4
|
||||||
|
|
||||||
#If the project is private but has the required anon permissions the votes should
|
#If the project is private but has the required anon permissions the votes should
|
||||||
# be accesible by any user too
|
# be accesible by any user too
|
||||||
project.anon_permissions = ["view_project", "view_us", "view_tasks", "view_issues"]
|
project.anon_permissions = ["view_project", "view_us", "view_tasks", "view_issues"]
|
||||||
project.save()
|
project.save()
|
||||||
assert len(get_favourites_list(fav_user, viewer_unpriviliged_user)) == 4
|
assert len(get_voted_list(fav_user, viewer_unpriviliged_user)) == 4
|
||||||
|
|
|
@ -85,7 +85,7 @@ def test_get_issue_votes(client):
|
||||||
response = client.get(url)
|
response = client.get(url)
|
||||||
|
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['votes'] == 5
|
assert response.data['total_voters'] == 5
|
||||||
|
|
||||||
|
|
||||||
def test_get_issue_is_voted(client):
|
def test_get_issue_is_voted(client):
|
||||||
|
@ -101,21 +101,21 @@ def test_get_issue_is_voted(client):
|
||||||
|
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['votes'] == 0
|
assert response.data['total_voters'] == 0
|
||||||
assert response.data['is_voted'] == False
|
assert response.data['is_voter'] == False
|
||||||
|
|
||||||
response = client.post(url_upvote)
|
response = client.post(url_upvote)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['votes'] == 1
|
assert response.data['total_voters'] == 1
|
||||||
assert response.data['is_voted'] == True
|
assert response.data['is_voter'] == True
|
||||||
|
|
||||||
response = client.post(url_downvote)
|
response = client.post(url_downvote)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['votes'] == 0
|
assert response.data['total_voters'] == 0
|
||||||
assert response.data['is_voted'] == False
|
assert response.data['is_voter'] == False
|
||||||
|
|
|
@ -87,7 +87,7 @@ def test_get_task_votes(client):
|
||||||
response = client.get(url)
|
response = client.get(url)
|
||||||
|
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['votes'] == 5
|
assert response.data['total_voters'] == 5
|
||||||
|
|
||||||
|
|
||||||
def test_get_task_is_voted(client):
|
def test_get_task_is_voted(client):
|
||||||
|
@ -103,21 +103,21 @@ def test_get_task_is_voted(client):
|
||||||
|
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['votes'] == 0
|
assert response.data['total_voters'] == 0
|
||||||
assert response.data['is_voted'] == False
|
assert response.data['is_voter'] == False
|
||||||
|
|
||||||
response = client.post(url_upvote)
|
response = client.post(url_upvote)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['votes'] == 1
|
assert response.data['total_voters'] == 1
|
||||||
assert response.data['is_voted'] == True
|
assert response.data['is_voter'] == True
|
||||||
|
|
||||||
response = client.post(url_downvote)
|
response = client.post(url_downvote)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['votes'] == 0
|
assert response.data['total_voters'] == 0
|
||||||
assert response.data['is_voted'] == False
|
assert response.data['is_voter'] == False
|
||||||
|
|
|
@ -86,7 +86,7 @@ def test_get_user_story_votes(client):
|
||||||
response = client.get(url)
|
response = client.get(url)
|
||||||
|
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['votes'] == 5
|
assert response.data['total_voters'] == 5
|
||||||
|
|
||||||
|
|
||||||
def test_get_user_story_is_voted(client):
|
def test_get_user_story_is_voted(client):
|
||||||
|
@ -102,21 +102,21 @@ def test_get_user_story_is_voted(client):
|
||||||
|
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['votes'] == 0
|
assert response.data['total_voters'] == 0
|
||||||
assert response.data['is_voted'] == False
|
assert response.data['is_voter'] == False
|
||||||
|
|
||||||
response = client.post(url_upvote)
|
response = client.post(url_upvote)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['votes'] == 1
|
assert response.data['total_voters'] == 1
|
||||||
assert response.data['is_voted'] == True
|
assert response.data['is_voter'] == True
|
||||||
|
|
||||||
response = client.post(url_downvote)
|
response = client.post(url_downvote)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['votes'] == 0
|
assert response.data['total_voters'] == 0
|
||||||
assert response.data['is_voted'] == False
|
assert response.data['is_voter'] == False
|
||||||
|
|
|
@ -89,9 +89,10 @@ def test_get_issue_watchers(client):
|
||||||
|
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['watchers'] == [user.id]
|
assert response.data['watchers'] == [user.id]
|
||||||
|
assert response.data['total_watchers'] == 1
|
||||||
|
|
||||||
|
|
||||||
def test_get_issue_is_watched(client):
|
def test_get_issue_is_watcher(client):
|
||||||
user = f.UserFactory.create()
|
user = f.UserFactory.create()
|
||||||
issue = f.IssueFactory(owner=user)
|
issue = f.IssueFactory(owner=user)
|
||||||
f.MembershipFactory.create(project=issue.project, user=user, is_owner=True)
|
f.MembershipFactory.create(project=issue.project, user=user, is_owner=True)
|
||||||
|
@ -104,7 +105,7 @@ def test_get_issue_is_watched(client):
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['watchers'] == []
|
assert response.data['watchers'] == []
|
||||||
assert response.data['is_watched'] == False
|
assert response.data['is_watcher'] == False
|
||||||
|
|
||||||
response = client.post(url_watch)
|
response = client.post(url_watch)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
@ -112,7 +113,7 @@ def test_get_issue_is_watched(client):
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['watchers'] == [user.id]
|
assert response.data['watchers'] == [user.id]
|
||||||
assert response.data['is_watched'] == True
|
assert response.data['is_watcher'] == True
|
||||||
|
|
||||||
response = client.post(url_unwatch)
|
response = client.post(url_unwatch)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
@ -120,4 +121,4 @@ def test_get_issue_is_watched(client):
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['watchers'] == []
|
assert response.data['watchers'] == []
|
||||||
assert response.data['is_watched'] == False
|
assert response.data['is_watcher'] == False
|
||||||
|
|
|
@ -88,10 +88,10 @@ def test_get_milestone_watchers(client):
|
||||||
response = client.get(url)
|
response = client.get(url)
|
||||||
|
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['watchers'] == [user.id]
|
assert response.data['total_watchers'] == 1
|
||||||
|
|
||||||
|
|
||||||
def test_get_milestone_is_watched(client):
|
def test_get_milestone_is_watcher(client):
|
||||||
user = f.UserFactory.create()
|
user = f.UserFactory.create()
|
||||||
milestone = f.MilestoneFactory(owner=user)
|
milestone = f.MilestoneFactory(owner=user)
|
||||||
f.MembershipFactory.create(project=milestone.project, user=user, is_owner=True)
|
f.MembershipFactory.create(project=milestone.project, user=user, is_owner=True)
|
||||||
|
@ -103,21 +103,21 @@ def test_get_milestone_is_watched(client):
|
||||||
|
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['watchers'] == []
|
assert response.data['total_watchers'] == 0
|
||||||
assert response.data['is_watched'] == False
|
assert response.data['is_watcher'] == False
|
||||||
|
|
||||||
response = client.post(url_watch)
|
response = client.post(url_watch)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['watchers'] == [user.id]
|
assert response.data['total_watchers'] == 1
|
||||||
assert response.data['is_watched'] == True
|
assert response.data['is_watcher'] == True
|
||||||
|
|
||||||
response = client.post(url_unwatch)
|
response = client.post(url_unwatch)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['watchers'] == []
|
assert response.data['total_watchers'] == 0
|
||||||
assert response.data['is_watched'] == False
|
assert response.data['is_watcher'] == False
|
||||||
|
|
|
@ -121,10 +121,10 @@ def test_get_project_watchers(client):
|
||||||
response = client.get(url)
|
response = client.get(url)
|
||||||
|
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['watchers'] == [user.id]
|
assert response.data['total_watchers'] == 1
|
||||||
|
|
||||||
|
|
||||||
def test_get_project_is_watched(client):
|
def test_get_project_is_watcher(client):
|
||||||
user = f.UserFactory.create()
|
user = f.UserFactory.create()
|
||||||
project = f.ProjectFactory.create(is_private=False,
|
project = f.ProjectFactory.create(is_private=False,
|
||||||
anon_permissions=list(map(lambda x: x[0], ANON_PERMISSIONS)),
|
anon_permissions=list(map(lambda x: x[0], ANON_PERMISSIONS)),
|
||||||
|
@ -139,21 +139,22 @@ def test_get_project_is_watched(client):
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
|
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['watchers'] == []
|
assert response.data['total_watchers'] == 0
|
||||||
assert response.data['is_watched'] == False
|
|
||||||
|
assert response.data['is_watcher'] == False
|
||||||
|
|
||||||
response = client.post(url_watch)
|
response = client.post(url_watch)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['watchers'] == [user.id]
|
assert response.data['total_watchers'] == 1
|
||||||
assert response.data['is_watched'] == True
|
assert response.data['is_watcher'] == True
|
||||||
|
|
||||||
response = client.post(url_unwatch)
|
response = client.post(url_unwatch)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['watchers'] == []
|
assert response.data['total_watchers'] == 0
|
||||||
assert response.data['is_watched'] == False
|
assert response.data['is_watcher'] == False
|
||||||
|
|
|
@ -89,9 +89,10 @@ def test_get_task_watchers(client):
|
||||||
|
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['watchers'] == [user.id]
|
assert response.data['watchers'] == [user.id]
|
||||||
|
assert response.data['total_watchers'] == 1
|
||||||
|
|
||||||
|
|
||||||
def test_get_task_is_watched(client):
|
def test_get_task_is_watcher(client):
|
||||||
user = f.UserFactory.create()
|
user = f.UserFactory.create()
|
||||||
task = f.TaskFactory(owner=user)
|
task = f.TaskFactory(owner=user)
|
||||||
f.MembershipFactory.create(project=task.project, user=user, is_owner=True)
|
f.MembershipFactory.create(project=task.project, user=user, is_owner=True)
|
||||||
|
@ -104,7 +105,7 @@ def test_get_task_is_watched(client):
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['watchers'] == []
|
assert response.data['watchers'] == []
|
||||||
assert response.data['is_watched'] == False
|
assert response.data['is_watcher'] == False
|
||||||
|
|
||||||
response = client.post(url_watch)
|
response = client.post(url_watch)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
@ -112,7 +113,7 @@ def test_get_task_is_watched(client):
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['watchers'] == [user.id]
|
assert response.data['watchers'] == [user.id]
|
||||||
assert response.data['is_watched'] == True
|
assert response.data['is_watcher'] == True
|
||||||
|
|
||||||
response = client.post(url_unwatch)
|
response = client.post(url_unwatch)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
@ -120,4 +121,4 @@ def test_get_task_is_watched(client):
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['watchers'] == []
|
assert response.data['watchers'] == []
|
||||||
assert response.data['is_watched'] == False
|
assert response.data['is_watcher'] == False
|
||||||
|
|
|
@ -89,9 +89,10 @@ def test_get_user_story_watchers(client):
|
||||||
|
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['watchers'] == [user.id]
|
assert response.data['watchers'] == [user.id]
|
||||||
|
assert response.data['total_watchers'] == 1
|
||||||
|
|
||||||
|
|
||||||
def test_get_user_story_is_watched(client):
|
def test_get_user_story_is_watcher(client):
|
||||||
user = f.UserFactory.create()
|
user = f.UserFactory.create()
|
||||||
user_story = f.UserStoryFactory(owner=user)
|
user_story = f.UserStoryFactory(owner=user)
|
||||||
f.MembershipFactory.create(project=user_story.project, user=user, is_owner=True)
|
f.MembershipFactory.create(project=user_story.project, user=user, is_owner=True)
|
||||||
|
@ -104,7 +105,7 @@ def test_get_user_story_is_watched(client):
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['watchers'] == []
|
assert response.data['watchers'] == []
|
||||||
assert response.data['is_watched'] == False
|
assert response.data['is_watcher'] == False
|
||||||
|
|
||||||
response = client.post(url_watch)
|
response = client.post(url_watch)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
@ -112,7 +113,7 @@ def test_get_user_story_is_watched(client):
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['watchers'] == [user.id]
|
assert response.data['watchers'] == [user.id]
|
||||||
assert response.data['is_watched'] == True
|
assert response.data['is_watcher'] == True
|
||||||
|
|
||||||
response = client.post(url_unwatch)
|
response = client.post(url_unwatch)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
@ -120,4 +121,4 @@ def test_get_user_story_is_watched(client):
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['watchers'] == []
|
assert response.data['watchers'] == []
|
||||||
assert response.data['is_watched'] == False
|
assert response.data['is_watcher'] == False
|
||||||
|
|
|
@ -88,10 +88,10 @@ def test_get_wikipage_watchers(client):
|
||||||
response = client.get(url)
|
response = client.get(url)
|
||||||
|
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['watchers'] == [user.id]
|
assert response.data['total_watchers'] == 1
|
||||||
|
|
||||||
|
|
||||||
def test_get_wikipage_is_watched(client):
|
def test_get_wikipage_is_watcher(client):
|
||||||
user = f.UserFactory.create()
|
user = f.UserFactory.create()
|
||||||
wikipage = f.WikiPageFactory(owner=user)
|
wikipage = f.WikiPageFactory(owner=user)
|
||||||
f.MembershipFactory.create(project=wikipage.project, user=user, is_owner=True)
|
f.MembershipFactory.create(project=wikipage.project, user=user, is_owner=True)
|
||||||
|
@ -103,21 +103,21 @@ def test_get_wikipage_is_watched(client):
|
||||||
|
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['watchers'] == []
|
assert response.data['total_watchers'] == 0
|
||||||
assert response.data['is_watched'] == False
|
assert response.data['is_watcher'] == False
|
||||||
|
|
||||||
response = client.post(url_watch)
|
response = client.post(url_watch)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['watchers'] == [user.id]
|
assert response.data['total_watchers'] == 1
|
||||||
assert response.data['is_watched'] == True
|
assert response.data['is_watcher'] == True
|
||||||
|
|
||||||
response = client.post(url_unwatch)
|
response = client.post(url_unwatch)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
||||||
response = client.get(url_detail)
|
response = client.get(url_detail)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.data['watchers'] == []
|
assert response.data['total_watchers'] == 0
|
||||||
assert response.data['is_watched'] == False
|
assert response.data['is_watcher'] == False
|
||||||
|
|
Loading…
Reference in New Issue