From fd12f849697402ecf23797acd9fd1d084ff505cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Barrag=C3=A1n=20Merino?= Date: Thu, 26 Nov 2015 18:47:25 +0100 Subject: [PATCH] Task #3538: Add tribe_gig PickledObjectField attribute to UserStory model --- CHANGELOG.md | 1 + taiga/base/fields.py | 13 +++++++ taiga/projects/api.py | 34 +++++++++---------- taiga/projects/history/freeze_impl.py | 1 + .../emails/includes/fields_diff-html.jinja | 3 +- .../emails/includes/fields_diff-text.jinja | 3 +- .../migrations/0011_userstory_tribe_gig.py | 20 +++++++++++ taiga/projects/userstories/models.py | 5 +++ taiga/projects/userstories/serializers.py | 5 ++- tests/integration/test_userstories.py | 21 ++++++++++++ 10 files changed, 86 insertions(+), 20 deletions(-) create mode 100644 taiga/projects/userstories/migrations/0011_userstory_tribe_gig.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 6df31f60..a16bdd9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - Improve login and forgot password: allow username or email case-insensitive if the query only match with one user. - Improve the django admin panel, now it is more usable and all the selector fields works properly. +- [API] Add tribe_gig field to user stories (improve integration between Taiga and Taiga Tribe). - [API] Performance improvements for project stats. - Lots of small and not so small bugfixes. diff --git a/taiga/base/fields.py b/taiga/base/fields.py index 0c5d96aa..28c04a11 100644 --- a/taiga/base/fields.py +++ b/taiga/base/fields.py @@ -84,6 +84,19 @@ class PgArrayField(serializers.WritableField): return data +class PickledObjectField(serializers.WritableField): + """ + PickledObjectField objects serializer. + """ + widget = widgets.Textarea + + def to_native(self, obj): + return obj + + def from_native(self, data): + return data + + class TagsField(serializers.WritableField): """ Pickle objects serializer. diff --git a/taiga/projects/api.py b/taiga/projects/api.py index ba49b1a1..fa473d50 100644 --- a/taiga/projects/api.py +++ b/taiga/projects/api.py @@ -76,6 +76,23 @@ class ProjectViewSet(LikedResourceMixin, HistoryResourceMixin, ModelCrudViewSet) return qs + def get_serializer_class(self): + if self.action == "list": + return self.list_serializer_class + elif self.action == "create": + return self.serializer_class + + if self.action == "by_slug": + slug = self.request.QUERY_PARAMS.get("slug", None) + project = get_object_or_404(models.Project, slug=slug) + else: + project = self.get_object() + + if permissions_service.is_project_owner(self.request.user, project): + return self.admin_serializer_class + + return self.serializer_class + @detail_route(methods=["POST"]) def watch(self, request, pk=None): project = self.get_object() @@ -105,23 +122,6 @@ class ProjectViewSet(LikedResourceMixin, HistoryResourceMixin, ModelCrudViewSet) services.update_projects_order_in_bulk(data, "user_order", request.user) return response.NoContent(data=None) - def get_serializer_class(self): - if self.action == "list": - return self.list_serializer_class - elif self.action == "create": - return self.serializer_class - - if self.action == "by_slug": - slug = self.request.QUERY_PARAMS.get("slug", None) - project = get_object_or_404(models.Project, slug=slug) - else: - project = self.get_object() - - if permissions_service.is_project_owner(self.request.user, project): - return self.admin_serializer_class - - return self.serializer_class - @list_route(methods=["GET"]) def by_slug(self, request): slug = request.QUERY_PARAMS.get("slug", None) diff --git a/taiga/projects/history/freeze_impl.py b/taiga/projects/history/freeze_impl.py index 6e327b52..6a551304 100644 --- a/taiga/projects/history/freeze_impl.py +++ b/taiga/projects/history/freeze_impl.py @@ -286,6 +286,7 @@ def userstory_freezer(us) -> dict: "blocked_note": us.blocked_note, "blocked_note_html": mdrender(us.project, us.blocked_note), "custom_attributes": extract_user_story_custom_attributes(us), + "tribe_gig": us.tribe_gig, } return snapshot diff --git a/taiga/projects/history/templates/emails/includes/fields_diff-html.jinja b/taiga/projects/history/templates/emails/includes/fields_diff-html.jinja index 4c99f755..eadca5c3 100644 --- a/taiga/projects/history/templates/emails/includes/fields_diff-html.jinja +++ b/taiga/projects/history/templates/emails/includes/fields_diff-html.jinja @@ -9,7 +9,8 @@ "kanban_order", "taskboard_order", "us_order", - "custom_attributes" + "custom_attributes", + "tribe_gig", ] %} {% for field_name, values in changed_fields.items() %} diff --git a/taiga/projects/history/templates/emails/includes/fields_diff-text.jinja b/taiga/projects/history/templates/emails/includes/fields_diff-text.jinja index 5ecbf496..ff0a1b0d 100644 --- a/taiga/projects/history/templates/emails/includes/fields_diff-text.jinja +++ b/taiga/projects/history/templates/emails/includes/fields_diff-text.jinja @@ -9,7 +9,8 @@ "us_order", "blocked_note_diff", "blocked_note_html", - "custom_attributes" + "custom_attributes", + "tribe_gig", ] %} {% for field_name, values in changed_fields.items() %} {% if field_name not in excluded_fields %} diff --git a/taiga/projects/userstories/migrations/0011_userstory_tribe_gig.py b/taiga/projects/userstories/migrations/0011_userstory_tribe_gig.py new file mode 100644 index 00000000..af85e462 --- /dev/null +++ b/taiga/projects/userstories/migrations/0011_userstory_tribe_gig.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import picklefield.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('userstories', '0010_remove_userstory_watchers'), + ] + + operations = [ + migrations.AddField( + model_name='userstory', + name='tribe_gig', + field=picklefield.fields.PickledObjectField(editable=False, null=True, default=None, verbose_name='taiga tribe gig', blank=True), + ), + ] diff --git a/taiga/projects/userstories/models.py b/taiga/projects/userstories/models.py index 2b29a275..6b49654e 100644 --- a/taiga/projects/userstories/models.py +++ b/taiga/projects/userstories/models.py @@ -21,6 +21,7 @@ from django.utils.translation import ugettext_lazy as _ from django.utils import timezone from djorm_pgarray.fields import TextArrayField +from picklefield.fields import PickledObjectField from taiga.base.tags import TaggedMixin from taiga.projects.occ import OCCModelMixin @@ -101,6 +102,10 @@ class UserStory(OCCModelMixin, WatchedModelMixin, BlockedMixin, TaggedMixin, mod related_name="generated_user_stories", verbose_name=_("generated from issue")) external_reference = TextArrayField(default=None, verbose_name=_("external reference")) + + tribe_gig = PickledObjectField(null=True, blank=True, default=None, + verbose_name="taiga tribe gig") + _importing = None class Meta: diff --git a/taiga/projects/userstories/serializers.py b/taiga/projects/userstories/serializers.py index c3f93d67..98cc2bb4 100644 --- a/taiga/projects/userstories/serializers.py +++ b/taiga/projects/userstories/serializers.py @@ -17,6 +17,7 @@ from django.apps import apps from taiga.base.api import serializers from taiga.base.fields import TagsField +from taiga.base.fields import PickledObjectField from taiga.base.fields import PgArrayField from taiga.base.neighbors import NeighborsSerializerMixin from taiga.base.utils import json @@ -45,7 +46,8 @@ class RolePointsField(serializers.WritableField): return json.loads(obj) -class UserStorySerializer(WatchersValidator, VoteResourceSerializerMixin, EditableWatchedResourceModelSerializer, serializers.ModelSerializer): +class UserStorySerializer(WatchersValidator, VoteResourceSerializerMixin, EditableWatchedResourceModelSerializer, + serializers.ModelSerializer): tags = TagsField(default=[], required=False) external_reference = PgArrayField(required=False) points = RolePointsField(source="role_points", required=False) @@ -59,6 +61,7 @@ class UserStorySerializer(WatchersValidator, VoteResourceSerializerMixin, Editab status_extra_info = BasicUserStoryStatusSerializer(source="status", required=False, read_only=True) assigned_to_extra_info = UserBasicInfoSerializer(source="assigned_to", required=False, read_only=True) owner_extra_info = UserBasicInfoSerializer(source="owner", required=False, read_only=True) + tribe_gig = PickledObjectField(required=False) class Meta: model = models.UserStory diff --git a/tests/integration/test_userstories.py b/tests/integration/test_userstories.py index 4ddaece0..8502c4ca 100644 --- a/tests/integration/test_userstories.py +++ b/tests/integration/test_userstories.py @@ -514,3 +514,24 @@ def test_update_userstory_remove_watchers(client): assert response.data["watchers"] == [] watcher_ids = list(us.get_watchers().values_list("id", flat=True)) assert watcher_ids == [] + + +def test_update_userstory_update_tribe_gig(client): + project = f.ProjectFactory.create() + us = f.UserStoryFactory.create(project=project, status__project=project, milestone__project=project) + f.MembershipFactory.create(project=us.project, user=us.owner, is_owner=True) + + url = reverse("userstories-detail", kwargs={"pk": us.pk}) + data = { + "tribe_gig": { + "id": 2, + "title": "This is a gig test title" + }, + "version":1 + } + + client.login(user=us.owner) + response = client.json.patch(url, json.dumps(data)) + + assert response.status_code == 200 + assert response.data["tribe_gig"] == data["tribe_gig"]