Fixing tags actions with epics

remotes/origin/issue/4795/notification_even_they_are_disabled
Alejandro Alonso 2016-09-21 13:21:14 +02:00
parent f8a1c8f4a3
commit 9a06a8df94
5 changed files with 253 additions and 37 deletions

View File

@ -24,7 +24,7 @@ def tag_exist_for_project_elements(project, tag):
def create_tags(project, new_tags_colors): def create_tags(project, new_tags_colors):
project.tags_colors += [[k, v] for k,v in new_tags_colors.items()] project.tags_colors += [[k, v] for k, v in new_tags_colors.items()]
project.save(update_fields=["tags_colors"]) project.save(update_fields=["tags_colors"])
@ -33,14 +33,42 @@ def create_tag(project, tag, color):
project.save(update_fields=["tags_colors"]) project.save(update_fields=["tags_colors"])
def edit_tag(project, from_tag, to_tag=None, color=None): def edit_tag(project, from_tag, to_tag, color):
tags_colors = dict(project.tags_colors) print("edit_tag", project, from_tag, to_tag, color)
sql = """
UPDATE userstories_userstory
SET tags = array_distinct(array_replace(tags, '{from_tag}', '{to_tag}'))
WHERE project_id = {project_id};
if color is not None: UPDATE tasks_task
tags_colors = dict(project.tags_colors) SET tags = array_distinct(array_replace(tags, '{from_tag}', '{to_tag}'))
tags_colors[from_tag] = color WHERE project_id = {project_id};
if to_tag is not None: UPDATE issues_issue
SET tags = array_distinct(array_replace(tags, '{from_tag}', '{to_tag}'))
WHERE project_id = {project_id};
UPDATE epics_epic
SET tags = array_distinct(array_replace(tags, '{from_tag}', '{to_tag}'))
WHERE project_id = {project_id};
"""
sql = sql.format(project_id=project.id, from_tag=from_tag, to_tag=to_tag)
cursor = connection.cursor()
cursor.execute(sql)
tags_colors = dict(project.tags_colors)
tags_colors.pop(from_tag)
tags_colors[to_tag] = color
project.tags_colors = list(tags_colors.items())
project.save(update_fields=["tags_colors"])
def rename_tag(project, from_tag, to_tag, **kwargs):
# Kwargs can have a color parameter
update_color = "color" in kwargs
if update_color:
color = kwargs.get("color")
else:
color = dict(project.tags_colors)[from_tag] color = dict(project.tags_colors)[from_tag]
sql = """ sql = """
UPDATE userstories_userstory UPDATE userstories_userstory
@ -54,30 +82,8 @@ def edit_tag(project, from_tag, to_tag=None, color=None):
UPDATE issues_issue UPDATE issues_issue
SET tags = array_distinct(array_replace(tags, '{from_tag}', '{to_tag}')) SET tags = array_distinct(array_replace(tags, '{from_tag}', '{to_tag}'))
WHERE project_id = {project_id}; WHERE project_id = {project_id};
"""
sql = sql.format(project_id=project.id, from_tag=from_tag, to_tag=to_tag)
cursor = connection.cursor()
cursor.execute(sql)
tags_colors[to_tag] = tags_colors.pop(from_tag) UPDATE epics_epic
project.tags_colors = list(tags_colors.items())
project.save(update_fields=["tags_colors"])
def rename_tag(project, from_tag, to_tag, color=None):
color = color or dict(project.tags_colors)[from_tag]
sql = """
UPDATE userstories_userstory
SET tags = array_distinct(array_replace(tags, '{from_tag}', '{to_tag}'))
WHERE project_id = {project_id};
UPDATE tasks_task
SET tags = array_distinct(array_replace(tags, '{from_tag}', '{to_tag}'))
WHERE project_id = {project_id};
UPDATE issues_issue
SET tags = array_distinct(array_replace(tags, '{from_tag}', '{to_tag}')) SET tags = array_distinct(array_replace(tags, '{from_tag}', '{to_tag}'))
WHERE project_id = {project_id}; WHERE project_id = {project_id};
""" """
@ -105,6 +111,10 @@ def delete_tag(project, tag):
UPDATE issues_issue UPDATE issues_issue
SET tags = array_remove(tags, '{tag}') SET tags = array_remove(tags, '{tag}')
WHERE project_id = {project_id}; WHERE project_id = {project_id};
UPDATE epics_epic
SET tags = array_remove(tags, '{tag}')
WHERE project_id = {project_id};
""" """
sql = sql.format(project_id=project.id, tag=tag) sql = sql.format(project_id=project.id, tag=tag)
cursor = connection.cursor() cursor = connection.cursor()
@ -119,4 +129,4 @@ def delete_tag(project, tag):
def mix_tags(project, from_tags, to_tag): def mix_tags(project, from_tags, to_tag):
color = dict(project.tags_colors)[to_tag] color = dict(project.tags_colors)[to_tag]
for from_tag in from_tags: for from_tag in from_tags:
rename_tag(project, from_tag, to_tag, color) rename_tag(project, from_tag, to_tag, color=color)

View File

@ -82,6 +82,15 @@ class EditTagTagValidator(ProjectTagValidator):
return attrs return attrs
def validate(self, data):
if "to_tag" not in data:
data["to_tag"] = data.get("from_tag")
if "color" not in data:
data["color"] = dict(self.project.tags_colors).get(data.get("from_tag"))
return data
class DeleteTagValidator(ProjectTagValidator): class DeleteTagValidator(ProjectTagValidator):
tag = serializers.CharField() tag = serializers.CharField()

View File

@ -670,6 +670,26 @@ def create_userstory(**kwargs):
return UserStoryFactory(**defaults) return UserStoryFactory(**defaults)
def create_epic(**kwargs):
"Create an epic along with its dependencies"
owner = kwargs.pop("owner", None)
if not owner:
owner = UserFactory.create()
project = kwargs.pop("project", None)
if project is None:
project = ProjectFactory.create(owner=owner)
defaults = {
"project": project,
"owner": owner,
}
defaults.update(kwargs)
return EpicFactory(**defaults)
def create_project(**kwargs): def create_project(**kwargs):
"Create a project along with its dependencies" "Create a project along with its dependencies"
defaults = {} defaults = {}

View File

@ -0,0 +1,161 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2014-2016 Andrey Antukh <niwi@niwi.nz>
# Copyright (C) 2014-2016 Jesús Espino <jespinog@gmail.com>
# Copyright (C) 2014-2016 David Barragán <bameda@dbarragan.com>
# Copyright (C) 2014-2016 Alejandro Alonso <alejandro.alonso@kaleidos.net>
# Copyright (C) 2014-2016 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/>.
from unittest import mock
from collections import OrderedDict
from django.core.urlresolvers import reverse
from taiga.base.utils import json
from .. import factories as f
import pytest
pytestmark = pytest.mark.django_db
def test_api_epic_add_new_tags_with_error(client):
project = f.ProjectFactory.create()
epic = f.create_epic(project=project, status__project=project)
f.MembershipFactory.create(project=project, user=epic.owner, is_admin=True)
url = reverse("epics-detail", kwargs={"pk": epic.pk})
data = {
"tags": [],
"version": epic.version
}
client.login(epic.owner)
data["tags"] = [1]
response = client.json.patch(url, json.dumps(data))
assert response.status_code == 400, response.data
assert "tags" in response.data
data["tags"] = [["back"]]
response = client.json.patch(url, json.dumps(data))
assert response.status_code == 400, response.data
assert "tags" in response.data
data["tags"] = [["back", "#cccc"]]
response = client.json.patch(url, json.dumps(data))
assert response.status_code == 400, response.data
assert "tags" in response.data
data["tags"] = [[1, "#ccc"]]
response = client.json.patch(url, json.dumps(data))
assert response.status_code == 400, response.data
assert "tags" in response.data
def test_api_epic_add_new_tags_without_colors(client):
project = f.ProjectFactory.create()
epic = f.create_epic(project=project, status__project=project)
f.MembershipFactory.create(project=project, user=epic.owner, is_admin=True)
url = reverse("epics-detail", kwargs={"pk": epic.pk})
data = {
"tags": [
["back", None],
["front", None],
["ux", None]
],
"version": epic.version
}
client.login(epic.owner)
response = client.json.patch(url, json.dumps(data))
assert response.status_code == 200, response.data
tags_colors = OrderedDict(project.tags_colors)
assert not tags_colors.keys()
project.refresh_from_db()
tags_colors = OrderedDict(project.tags_colors)
assert "back" in tags_colors and "front" in tags_colors and "ux" in tags_colors
def test_api_epic_add_new_tags_with_colors(client):
project = f.ProjectFactory.create()
epic = f.create_epic(project=project, status__project=project)
f.MembershipFactory.create(project=project, user=epic.owner, is_admin=True)
url = reverse("epics-detail", kwargs={"pk": epic.pk})
data = {
"tags": [
["back", "#fff8e7"],
["front", None],
["ux", "#fabada"]
],
"version": epic.version
}
client.login(epic.owner)
response = client.json.patch(url, json.dumps(data))
assert response.status_code == 200, response.data
tags_colors = OrderedDict(project.tags_colors)
assert not tags_colors.keys()
project.refresh_from_db()
tags_colors = OrderedDict(project.tags_colors)
assert "back" in tags_colors and "front" in tags_colors and "ux" in tags_colors
assert tags_colors["back"] == "#fff8e7"
assert tags_colors["ux"] == "#fabada"
def test_api_create_new_epic_with_tags(client):
project = f.ProjectFactory.create(tags_colors=[["front", "#aaaaaa"], ["ux", "#fabada"]])
status = f.EpicStatusFactory.create(project=project)
project.default_epic_status = status
project.save()
f.MembershipFactory.create(project=project, user=project.owner, is_admin=True)
url = reverse("epics-list")
data = {
"subject": "Test user story",
"project": project.id,
"tags": [
["back", "#fff8e7"],
["front", None],
["ux", "#fabada"]
]
}
client.login(project.owner)
response = client.json.post(url, json.dumps(data))
assert response.status_code == 201, response.data
epic_tags_colors = OrderedDict(response.data["tags"])
assert epic_tags_colors["back"] == "#fff8e7"
assert epic_tags_colors["front"] == "#aaaaaa"
assert epic_tags_colors["ux"] == "#fabada"
tags_colors = OrderedDict(project.tags_colors)
project.refresh_from_db()
tags_colors = OrderedDict(project.tags_colors)
assert tags_colors["back"] == "#fff8e7"
assert tags_colors["ux"] == "#fabada"
assert tags_colors["front"] == "#aaaaaa"

View File

@ -31,6 +31,7 @@ from taiga.projects.models import Project
from taiga.projects.userstories.models import UserStory from taiga.projects.userstories.models import UserStory
from taiga.projects.tasks.models import Task from taiga.projects.tasks.models import Task
from taiga.projects.issues.models import Issue from taiga.projects.issues.models import Issue
from taiga.projects.epics.models import Epic
from taiga.projects.choices import BLOCKED_BY_DELETING from taiga.projects.choices import BLOCKED_BY_DELETING
from .. import factories as f from .. import factories as f
@ -1918,6 +1919,7 @@ def test_edit_tag_only_name(client, settings):
user_story = f.UserStoryFactory.create(project=project, tags=["tag"]) user_story = f.UserStoryFactory.create(project=project, tags=["tag"])
task = f.TaskFactory.create(project=project, tags=["tag"]) task = f.TaskFactory.create(project=project, tags=["tag"])
issue = f.IssueFactory.create(project=project, tags=["tag"]) issue = f.IssueFactory.create(project=project, tags=["tag"])
epic = f.EpicFactory.create(project=project, tags=["tag"])
role = f.RoleFactory.create(project=project, permissions=["view_project"]) role = f.RoleFactory.create(project=project, permissions=["view_project"])
membership = f.MembershipFactory.create(project=project, user=user, role=role, is_admin=True) membership = f.MembershipFactory.create(project=project, user=user, role=role, is_admin=True)
@ -1940,6 +1942,8 @@ def test_edit_tag_only_name(client, settings):
assert task.tags == ["renamed_tag"] assert task.tags == ["renamed_tag"]
issue = Issue.objects.get(id=issue.pk) issue = Issue.objects.get(id=issue.pk)
assert issue.tags == ["renamed_tag"] assert issue.tags == ["renamed_tag"]
epic = Epic.objects.get(id=epic.pk)
assert epic.tags == ["renamed_tag"]
def test_edit_tag_only_color(client, settings): def test_edit_tag_only_color(client, settings):
@ -1948,6 +1952,7 @@ def test_edit_tag_only_color(client, settings):
user_story = f.UserStoryFactory.create(project=project, tags=["tag"]) user_story = f.UserStoryFactory.create(project=project, tags=["tag"])
task = f.TaskFactory.create(project=project, tags=["tag"]) task = f.TaskFactory.create(project=project, tags=["tag"])
issue = f.IssueFactory.create(project=project, tags=["tag"]) issue = f.IssueFactory.create(project=project, tags=["tag"])
epic = f.EpicFactory.create(project=project, tags=["tag"])
role = f.RoleFactory.create(project=project, permissions=["view_project"]) role = f.RoleFactory.create(project=project, permissions=["view_project"])
membership = f.MembershipFactory.create(project=project, user=user, role=role, is_admin=True) membership = f.MembershipFactory.create(project=project, user=user, role=role, is_admin=True)
@ -1969,6 +1974,8 @@ def test_edit_tag_only_color(client, settings):
assert task.tags == ["tag"] assert task.tags == ["tag"]
issue = Issue.objects.get(id=issue.pk) issue = Issue.objects.get(id=issue.pk)
assert issue.tags == ["tag"] assert issue.tags == ["tag"]
epic = Epic.objects.get(id=epic.pk)
assert epic.tags == ["tag"]
def test_edit_tag(client, settings): def test_edit_tag(client, settings):
@ -1977,6 +1984,7 @@ def test_edit_tag(client, settings):
user_story = f.UserStoryFactory.create(project=project, tags=["tag"]) user_story = f.UserStoryFactory.create(project=project, tags=["tag"])
task = f.TaskFactory.create(project=project, tags=["tag"]) task = f.TaskFactory.create(project=project, tags=["tag"])
issue = f.IssueFactory.create(project=project, tags=["tag"]) issue = f.IssueFactory.create(project=project, tags=["tag"])
epic = f.EpicFactory.create(project=project, tags=["tag"])
role = f.RoleFactory.create(project=project, permissions=["view_project"]) role = f.RoleFactory.create(project=project, permissions=["view_project"])
membership = f.MembershipFactory.create(project=project, user=user, role=role, is_admin=True) membership = f.MembershipFactory.create(project=project, user=user, role=role, is_admin=True)
@ -1999,6 +2007,8 @@ def test_edit_tag(client, settings):
assert task.tags == ["renamed_tag"] assert task.tags == ["renamed_tag"]
issue = Issue.objects.get(id=issue.pk) issue = Issue.objects.get(id=issue.pk)
assert issue.tags == ["renamed_tag"] assert issue.tags == ["renamed_tag"]
epic = Epic.objects.get(id=epic.pk)
assert epic.tags == ["renamed_tag"]
def test_delete_tag(client, settings): def test_delete_tag(client, settings):
@ -2007,6 +2017,7 @@ def test_delete_tag(client, settings):
user_story = f.UserStoryFactory.create(project=project, tags=["tag"]) user_story = f.UserStoryFactory.create(project=project, tags=["tag"])
task = f.TaskFactory.create(project=project, tags=["tag"]) task = f.TaskFactory.create(project=project, tags=["tag"])
issue = f.IssueFactory.create(project=project, tags=["tag"]) issue = f.IssueFactory.create(project=project, tags=["tag"])
epic = f.EpicFactory.create(project=project, tags=["tag"])
role = f.RoleFactory.create(project=project, permissions=["view_project"]) role = f.RoleFactory.create(project=project, permissions=["view_project"])
membership = f.MembershipFactory.create(project=project, user=user, role=role, is_admin=True) membership = f.MembershipFactory.create(project=project, user=user, role=role, is_admin=True)
@ -2027,6 +2038,8 @@ def test_delete_tag(client, settings):
assert task.tags == [] assert task.tags == []
issue = Issue.objects.get(id=issue.pk) issue = Issue.objects.get(id=issue.pk)
assert issue.tags == [] assert issue.tags == []
epic = Epic.objects.get(id=epic.pk)
assert epic.tags == []
def test_mix_tags(client, settings): def test_mix_tags(client, settings):
@ -2035,6 +2048,7 @@ def test_mix_tags(client, settings):
user_story = f.UserStoryFactory.create(project=project, tags=["tag1", "tag3"]) user_story = f.UserStoryFactory.create(project=project, tags=["tag1", "tag3"])
task = f.TaskFactory.create(project=project, tags=["tag2", "tag3"]) task = f.TaskFactory.create(project=project, tags=["tag2", "tag3"])
issue = f.IssueFactory.create(project=project, tags=["tag1", "tag2", "tag3"]) issue = f.IssueFactory.create(project=project, tags=["tag1", "tag2", "tag3"])
epic = f.EpicFactory.create(project=project, tags=["tag1", "tag2", "tag3"])
role = f.RoleFactory.create(project=project, permissions=["view_project"]) role = f.RoleFactory.create(project=project, permissions=["view_project"])
membership = f.MembershipFactory.create(project=project, user=user, role=role, is_admin=True) membership = f.MembershipFactory.create(project=project, user=user, role=role, is_admin=True)
@ -2056,6 +2070,8 @@ def test_mix_tags(client, settings):
assert set(task.tags) == set(["tag2", "tag3"]) assert set(task.tags) == set(["tag2", "tag3"])
issue = Issue.objects.get(id=issue.pk) issue = Issue.objects.get(id=issue.pk)
assert set(issue.tags) == set(["tag2", "tag3"]) assert set(issue.tags) == set(["tag2", "tag3"])
epic = Epic.objects.get(id=epic.pk)
assert set(epic.tags) == set(["tag2", "tag3"])
def test_color_tags_project_fired_on_element_create(): def test_color_tags_project_fired_on_element_create():