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

@ -33,14 +33,42 @@ def create_tag(project, tag, color):
project.save(update_fields=["tags_colors"])
def edit_tag(project, from_tag, to_tag=None, color=None):
tags_colors = dict(project.tags_colors)
def edit_tag(project, from_tag, to_tag, color):
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:
tags_colors = dict(project.tags_colors)
tags_colors[from_tag] = color
UPDATE tasks_task
SET tags = array_distinct(array_replace(tags, '{from_tag}', '{to_tag}'))
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]
sql = """
UPDATE userstories_userstory
@ -54,30 +82,8 @@ def edit_tag(project, from_tag, to_tag=None, color=None):
UPDATE issues_issue
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[to_tag] = tags_colors.pop(from_tag)
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
UPDATE epics_epic
SET tags = array_distinct(array_replace(tags, '{from_tag}', '{to_tag}'))
WHERE project_id = {project_id};
"""
@ -105,6 +111,10 @@ def delete_tag(project, tag):
UPDATE issues_issue
SET tags = array_remove(tags, '{tag}')
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)
cursor = connection.cursor()
@ -119,4 +129,4 @@ def delete_tag(project, tag):
def mix_tags(project, from_tags, to_tag):
color = dict(project.tags_colors)[to_tag]
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
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):
tag = serializers.CharField()

View File

@ -670,6 +670,26 @@ def create_userstory(**kwargs):
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):
"Create a project along with its dependencies"
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.tasks.models import Task
from taiga.projects.issues.models import Issue
from taiga.projects.epics.models import Epic
from taiga.projects.choices import BLOCKED_BY_DELETING
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"])
task = f.TaskFactory.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"])
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"]
issue = Issue.objects.get(id=issue.pk)
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):
@ -1948,6 +1952,7 @@ def test_edit_tag_only_color(client, settings):
user_story = f.UserStoryFactory.create(project=project, tags=["tag"])
task = f.TaskFactory.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"])
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"]
issue = Issue.objects.get(id=issue.pk)
assert issue.tags == ["tag"]
epic = Epic.objects.get(id=epic.pk)
assert epic.tags == ["tag"]
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"])
task = f.TaskFactory.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"])
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"]
issue = Issue.objects.get(id=issue.pk)
assert issue.tags == ["renamed_tag"]
epic = Epic.objects.get(id=epic.pk)
assert epic.tags == ["renamed_tag"]
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"])
task = f.TaskFactory.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"])
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 == []
issue = Issue.objects.get(id=issue.pk)
assert issue.tags == []
epic = Epic.objects.get(id=epic.pk)
assert epic.tags == []
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"])
task = f.TaskFactory.create(project=project, tags=["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"])
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"])
issue = Issue.objects.get(id=issue.pk)
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():