API calls to create, rename, edit color, delete and mix tags
parent
7134d04262
commit
3e555de7c4
|
@ -405,6 +405,67 @@ class ProjectViewSet(LikedResourceMixin, HistoryResourceMixin,
|
|||
services.reject_project_transfer(project, request.user, token, reason)
|
||||
return response.Ok()
|
||||
|
||||
@detail_route(methods=["POST"])
|
||||
def create_tag(self, request, pk=None):
|
||||
project = self.get_object()
|
||||
self.check_permissions(request, "create_tag", project)
|
||||
self._raise_if_blocked(project)
|
||||
serializer = serializers.CreateTagSerializer(data=request.DATA, project=project)
|
||||
if not serializer.is_valid():
|
||||
return response.BadRequest(serializer.errors)
|
||||
|
||||
data = serializer.data
|
||||
services.create_tag(project, data.get("tag"), data.get("color"))
|
||||
return response.Ok()
|
||||
|
||||
|
||||
@detail_route(methods=["POST"])
|
||||
def edit_tag(self, request, pk=None):
|
||||
project = self.get_object()
|
||||
self.check_permissions(request, "edit_tag", project)
|
||||
self._raise_if_blocked(project)
|
||||
serializer = serializers.EditTagTagSerializer(data=request.DATA, project=project)
|
||||
if not serializer.is_valid():
|
||||
return response.BadRequest(serializer.errors)
|
||||
|
||||
data = serializer.data
|
||||
services.edit_tag(project, data.get("from_tag"),
|
||||
to_tag=data.get("to_tag", None),
|
||||
color=data.get("color", None))
|
||||
|
||||
return response.Ok()
|
||||
|
||||
|
||||
@detail_route(methods=["POST"])
|
||||
def delete_tag(self, request, pk=None):
|
||||
project = self.get_object()
|
||||
self.check_permissions(request, "delete_tag", project)
|
||||
self._raise_if_blocked(project)
|
||||
serializer = serializers.DeleteTagSerializer(data=request.DATA, project=project)
|
||||
if not serializer.is_valid():
|
||||
return response.BadRequest(serializer.errors)
|
||||
|
||||
data = serializer.data
|
||||
services.delete_tag(project, data.get("tag"))
|
||||
return response.Ok()
|
||||
|
||||
@detail_route(methods=["POST"])
|
||||
def mix_tags(self, request, pk=None):
|
||||
project = self.get_object()
|
||||
self.check_permissions(request, "mix_tags", project)
|
||||
self._raise_if_blocked(project)
|
||||
serializer = serializers.MixTagsSerializer(data=request.DATA, project=project)
|
||||
if not serializer.is_valid():
|
||||
return response.BadRequest(serializer.errors)
|
||||
|
||||
data = serializer.data
|
||||
services.mix_tags(project, data.get("from_tags"), data.get("to_tag"))
|
||||
return response.Ok()
|
||||
|
||||
def _raise_if_blocked(self, project):
|
||||
if self.is_blocked(project):
|
||||
raise exc.Blocked(_("Blocked element"))
|
||||
|
||||
def _set_base_permissions(self, obj):
|
||||
update_permissions = False
|
||||
if not obj.id:
|
||||
|
|
|
@ -78,6 +78,10 @@ class ProjectPermission(TaigaResourcePermission):
|
|||
transfer_start_perms = IsObjectOwner()
|
||||
transfer_reject_perms = IsAuthenticated() & HasProjectPerm('view_project')
|
||||
transfer_accept_perms = IsAuthenticated() & HasProjectPerm('view_project')
|
||||
create_tag_perms = IsProjectAdmin()
|
||||
edit_tag_perms = IsProjectAdmin()
|
||||
delete_tag_perms = IsProjectAdmin()
|
||||
mix_tags_perms = IsProjectAdmin()
|
||||
|
||||
|
||||
class ProjectFansPermission(TaigaResourcePermission):
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
# 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 re
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.db.models import Q
|
||||
|
@ -256,7 +257,7 @@ class ProjectSerializer(FanResourceSerializerMixin, WatchedResourceModelSerializ
|
|||
i_am_member = serializers.SerializerMethodField("get_i_am_member")
|
||||
|
||||
tags = TagsField(default=[], required=False)
|
||||
tags_colors = TagsColorsField(required=False)
|
||||
tags_colors = TagsColorsField(required=False, read_only=True)
|
||||
|
||||
notify_level = serializers.SerializerMethodField("get_notify_level")
|
||||
total_closed_milestones = serializers.SerializerMethodField("get_total_closed_milestones")
|
||||
|
@ -416,3 +417,94 @@ class ProjectTemplateSerializer(serializers.ModelSerializer):
|
|||
class UpdateProjectOrderBulkSerializer(ProjectExistsValidator, serializers.Serializer):
|
||||
project_id = serializers.IntegerField()
|
||||
order = serializers.IntegerField()
|
||||
|
||||
|
||||
######################################################
|
||||
## Project tags serializers
|
||||
######################################################
|
||||
|
||||
|
||||
class ProjectTagSerializer(serializers.Serializer):
|
||||
def __init__(self, *args, **kwargs):
|
||||
# Don't pass the extra project arg
|
||||
self.project = kwargs.pop("project")
|
||||
|
||||
# Instantiate the superclass normally
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class CreateTagSerializer(ProjectTagSerializer):
|
||||
tag = serializers.CharField()
|
||||
color = serializers.CharField(required=False)
|
||||
|
||||
def validate_tag(self, attrs, source):
|
||||
tag = attrs.get(source, None)
|
||||
if services.tag_exist_for_project_elements(self.project, tag):
|
||||
raise serializers.ValidationError(_("The tag exists."))
|
||||
|
||||
return attrs
|
||||
|
||||
def validate_color(self, attrs, source):
|
||||
color = attrs.get(source, None)
|
||||
if not re.match('^\#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$', color):
|
||||
raise serializers.ValidationError(_("The color is not a valid HEX color."))
|
||||
|
||||
return attrs
|
||||
|
||||
|
||||
class EditTagTagSerializer(ProjectTagSerializer):
|
||||
from_tag = serializers.CharField()
|
||||
to_tag = serializers.CharField(required=False)
|
||||
color = serializers.CharField(required=False)
|
||||
|
||||
def validate_from_tag(self, attrs, source):
|
||||
tag = attrs.get(source, None)
|
||||
if not services.tag_exist_for_project_elements(self.project, tag):
|
||||
raise serializers.ValidationError(_("The tag doesn't exist."))
|
||||
|
||||
return attrs
|
||||
|
||||
def validate_to_tag(self, attrs, source):
|
||||
tag = attrs.get(source, None)
|
||||
if services.tag_exist_for_project_elements(self.project, tag):
|
||||
raise serializers.ValidationError(_("The tag exists yet"))
|
||||
|
||||
return attrs
|
||||
|
||||
def validate_color(self, attrs, source):
|
||||
color = attrs.get(source, None)
|
||||
if len(color) != 7 or not re.match('^\#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$', color):
|
||||
raise serializers.ValidationError(_("The color is not a valid HEX color."))
|
||||
|
||||
return attrs
|
||||
|
||||
|
||||
class DeleteTagSerializer(ProjectTagSerializer):
|
||||
tag = serializers.CharField()
|
||||
|
||||
def validate_tag(self, attrs, source):
|
||||
tag = attrs.get(source, None)
|
||||
if not services.tag_exist_for_project_elements(self.project, tag):
|
||||
raise serializers.ValidationError(_("The tag doesn't exist."))
|
||||
|
||||
return attrs
|
||||
|
||||
|
||||
class MixTagsSerializer(ProjectTagSerializer):
|
||||
from_tags = TagsField()
|
||||
to_tag = serializers.CharField()
|
||||
|
||||
def validate_from_tags(self, attrs, source):
|
||||
tags = attrs.get(source, None)
|
||||
for tag in tags:
|
||||
if not services.tag_exist_for_project_elements(self.project, tag):
|
||||
raise serializers.ValidationError(_("The tag doesn't exist."))
|
||||
|
||||
return attrs
|
||||
|
||||
def validate_to_tag(self, attrs, source):
|
||||
tag = attrs.get(source, None)
|
||||
if not services.tag_exist_for_project_elements(self.project, tag):
|
||||
raise serializers.ValidationError(_("The tag doesn't exist."))
|
||||
|
||||
return attrs
|
||||
|
|
|
@ -57,3 +57,6 @@ from .stats import get_member_stats_for_project
|
|||
|
||||
from .transfer import request_project_transfer, start_project_transfer
|
||||
from .transfer import accept_project_transfer, reject_project_transfer
|
||||
|
||||
from .tags import tag_exist_for_project_elements, create_tag
|
||||
from .tags import edit_tag, delete_tag, mix_tags
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
# -*- 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>
|
||||
# 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 django.db import connection
|
||||
|
||||
def tag_exist_for_project_elements(project, tag):
|
||||
return tag in dict(project.tags_colors).keys()
|
||||
|
||||
|
||||
def create_tag(project, tag, color):
|
||||
project.tags_colors.append([tag, color])
|
||||
project.save()
|
||||
|
||||
|
||||
def edit_tag(project, from_tag, to_tag=None, color=None):
|
||||
tags_colors = dict(project.tags_colors)
|
||||
|
||||
if color is not None:
|
||||
tags_colors = dict(project.tags_colors)
|
||||
tags_colors[from_tag] = color
|
||||
|
||||
if to_tag is not None:
|
||||
color = 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}')) 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()
|
||||
|
||||
|
||||
def rename_tag(project, from_tag, to_tag):
|
||||
color = 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}')) WHERE project_id={project_id};
|
||||
"""
|
||||
sql = sql.format(project_id=project.id, from_tag=from_tag, to_tag=to_tag, color=color)
|
||||
cursor = connection.cursor()
|
||||
cursor.execute(sql)
|
||||
|
||||
tags_colors = dict(project.tags_colors)
|
||||
tags_colors[to_tag] = tags_colors.pop(from_tag)
|
||||
project.tags_colors = list(tags_colors.items())
|
||||
project.save()
|
||||
|
||||
|
||||
def delete_tag(project, tag):
|
||||
sql = """
|
||||
UPDATE userstories_userstory SET tags = array_remove(tags, '{tag}') WHERE project_id={project_id};
|
||||
UPDATE tasks_task SET tags = array_remove(tags, '{tag}') WHERE project_id={project_id};
|
||||
UPDATE issues_issue SET tags = array_remove(tags, '{tag}') WHERE project_id={project_id};
|
||||
"""
|
||||
sql = sql.format(project_id=project.id, tag=tag)
|
||||
cursor = connection.cursor()
|
||||
cursor.execute(sql)
|
||||
|
||||
tags_colors = dict(project.tags_colors)
|
||||
del tags_colors[tag]
|
||||
project.tags_colors = list(tags_colors.items())
|
||||
project.save()
|
||||
|
||||
|
||||
def mix_tags(project, from_tags, to_tag):
|
||||
for from_tag in from_tags:
|
||||
rename_tag(project, from_tag, to_tag)
|
|
@ -27,20 +27,24 @@ def data():
|
|||
m.public_project = f.ProjectFactory(is_private=False,
|
||||
anon_permissions=['view_project'],
|
||||
public_permissions=['view_project'],
|
||||
owner=m.project_owner)
|
||||
owner=m.project_owner,
|
||||
tags_colors = [("tag1", "#123123"), ("tag2", "#456456"), ("tag3", "#111222")])
|
||||
m.private_project1 = f.ProjectFactory(is_private=True,
|
||||
anon_permissions=['view_project'],
|
||||
public_permissions=['view_project'],
|
||||
owner=m.project_owner)
|
||||
owner=m.project_owner,
|
||||
tags_colors = [("tag1", "#123123"), ("tag2", "#456456"), ("tag3", "#111222")])
|
||||
m.private_project2 = f.ProjectFactory(is_private=True,
|
||||
anon_permissions=[],
|
||||
public_permissions=[],
|
||||
owner=m.project_owner)
|
||||
owner=m.project_owner,
|
||||
tags_colors = [("tag1", "#123123"), ("tag2", "#456456"), ("tag3", "#111222")])
|
||||
m.blocked_project = f.ProjectFactory(is_private=True,
|
||||
anon_permissions=[],
|
||||
public_permissions=[],
|
||||
owner=m.project_owner,
|
||||
blocked_code=project_choices.BLOCKED_BY_STAFF)
|
||||
blocked_code=project_choices.BLOCKED_BY_STAFF,
|
||||
tags_colors = [("tag1", "#123123"), ("tag2", "#456456"), ("tag3", "#111222")])
|
||||
|
||||
m.public_membership = f.MembershipFactory(project=m.public_project,
|
||||
user=m.project_member_with_perms,
|
||||
|
@ -1911,3 +1915,127 @@ def test_project_template_patch(client, data):
|
|||
|
||||
results = helper_test_http_method(client, 'patch', url, '{"name": "Test"}', users)
|
||||
assert results == [401, 403, 200]
|
||||
|
||||
|
||||
def test_create_tag(client, data):
|
||||
users = [
|
||||
None,
|
||||
data.registered_user,
|
||||
data.project_member_without_perms,
|
||||
data.project_member_with_perms,
|
||||
data.project_owner
|
||||
]
|
||||
|
||||
post_data = json.dumps({
|
||||
"tag": "testtest",
|
||||
"color": "#123123"
|
||||
})
|
||||
|
||||
url = reverse('projects-create-tag', kwargs={"pk": data.public_project.pk})
|
||||
results = helper_test_http_method(client, 'post', url, post_data, users)
|
||||
assert results == [401, 403, 403, 403, 200]
|
||||
|
||||
url = reverse('projects-create-tag', kwargs={"pk": data.private_project1.pk})
|
||||
results = helper_test_http_method(client, 'post', url, post_data, users)
|
||||
assert results == [401, 403, 403, 403, 200]
|
||||
|
||||
url = reverse('projects-create-tag', kwargs={"pk": data.private_project2.pk})
|
||||
results = helper_test_http_method(client, 'post', url, post_data, users)
|
||||
assert results == [404, 404, 404, 403, 200]
|
||||
|
||||
url = reverse('projects-create-tag', kwargs={"pk": data.blocked_project.pk})
|
||||
results = helper_test_http_method(client, 'post', url, post_data, users)
|
||||
assert results == [404, 404, 404, 403, 451]
|
||||
|
||||
|
||||
def test_edit_tag(client, data):
|
||||
users = [
|
||||
None,
|
||||
data.registered_user,
|
||||
data.project_member_without_perms,
|
||||
data.project_member_with_perms,
|
||||
data.project_owner
|
||||
]
|
||||
|
||||
post_data = json.dumps({
|
||||
"from_tag": "tag1",
|
||||
"to_tag": "renamedtag1",
|
||||
"color": "#123123"
|
||||
})
|
||||
|
||||
url = reverse('projects-edit-tag', kwargs={"pk": data.public_project.pk})
|
||||
results = helper_test_http_method(client, 'post', url, post_data, users)
|
||||
assert results == [401, 403, 403, 403, 200]
|
||||
|
||||
url = reverse('projects-edit-tag', kwargs={"pk": data.private_project1.pk})
|
||||
results = helper_test_http_method(client, 'post', url, post_data, users)
|
||||
assert results == [401, 403, 403, 403, 200]
|
||||
|
||||
url = reverse('projects-edit-tag', kwargs={"pk": data.private_project2.pk})
|
||||
results = helper_test_http_method(client, 'post', url, post_data, users)
|
||||
assert results == [404, 404, 404, 403, 200]
|
||||
|
||||
url = reverse('projects-edit-tag', kwargs={"pk": data.blocked_project.pk})
|
||||
results = helper_test_http_method(client, 'post', url, post_data, users)
|
||||
assert results == [404, 404, 404, 403, 451]
|
||||
|
||||
|
||||
def test_delete_tag(client, data):
|
||||
users = [
|
||||
None,
|
||||
data.registered_user,
|
||||
data.project_member_without_perms,
|
||||
data.project_member_with_perms,
|
||||
data.project_owner
|
||||
]
|
||||
|
||||
post_data = json.dumps({
|
||||
"tag": "tag2",
|
||||
})
|
||||
|
||||
url = reverse('projects-delete-tag', kwargs={"pk": data.public_project.pk})
|
||||
results = helper_test_http_method(client, 'post', url, post_data, users)
|
||||
assert results == [401, 403, 403, 403, 200]
|
||||
|
||||
url = reverse('projects-delete-tag', kwargs={"pk": data.private_project1.pk})
|
||||
results = helper_test_http_method(client, 'post', url, post_data, users)
|
||||
assert results == [401, 403, 403, 403, 200]
|
||||
|
||||
url = reverse('projects-delete-tag', kwargs={"pk": data.private_project2.pk})
|
||||
results = helper_test_http_method(client, 'post', url, post_data, users)
|
||||
assert results == [404, 404, 404, 403, 200]
|
||||
|
||||
url = reverse('projects-delete-tag', kwargs={"pk": data.blocked_project.pk})
|
||||
results = helper_test_http_method(client, 'post', url, post_data, users)
|
||||
assert results == [404, 404, 404, 403, 451]
|
||||
|
||||
|
||||
def test_mix_tags(client, data):
|
||||
users = [
|
||||
None,
|
||||
data.registered_user,
|
||||
data.project_member_without_perms,
|
||||
data.project_member_with_perms,
|
||||
data.project_owner
|
||||
]
|
||||
|
||||
post_data = json.dumps({
|
||||
"from_tags": ["tag1"],
|
||||
"to_tag": "tag3"
|
||||
})
|
||||
|
||||
url = reverse('projects-mix-tags', kwargs={"pk": data.public_project.pk})
|
||||
results = helper_test_http_method(client, 'post', url, post_data, users)
|
||||
assert results == [401, 403, 403, 403, 200]
|
||||
|
||||
url = reverse('projects-mix-tags', kwargs={"pk": data.private_project1.pk})
|
||||
results = helper_test_http_method(client, 'post', url, post_data, users)
|
||||
assert results == [401, 403, 403, 403, 200]
|
||||
|
||||
url = reverse('projects-mix-tags', kwargs={"pk": data.private_project2.pk})
|
||||
results = helper_test_http_method(client, 'post', url, post_data, users)
|
||||
assert results == [404, 404, 404, 403, 200]
|
||||
|
||||
url = reverse('projects-mix-tags', kwargs={"pk": data.blocked_project.pk})
|
||||
results = helper_test_http_method(client, 'post', url, post_data, users)
|
||||
assert results == [404, 404, 404, 403, 451]
|
||||
|
|
|
@ -10,6 +10,9 @@ from taiga.projects.services import stats as stats_services
|
|||
from taiga.projects.history.services import take_snapshot
|
||||
from taiga.permissions.choices import ANON_PERMISSIONS
|
||||
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.choices import BLOCKED_BY_DELETING
|
||||
|
||||
from .. import factories as f
|
||||
|
@ -1854,6 +1857,189 @@ def test_delete_project_with_celery_disabled(client, settings):
|
|||
assert Project.objects.filter(id=project.id).count() == 0
|
||||
|
||||
|
||||
def test_create_tag(client, settings):
|
||||
user = f.UserFactory.create()
|
||||
project = f.ProjectFactory.create(owner=user)
|
||||
role = f.RoleFactory.create(project=project, permissions=["view_project"])
|
||||
membership = f.MembershipFactory.create(project=project, user=user, role=role, is_admin=True)
|
||||
url = reverse("projects-create-tag", args=(project.id,))
|
||||
client.login(user)
|
||||
data = {
|
||||
"tag": "newtag",
|
||||
"color": "#123123"
|
||||
}
|
||||
|
||||
client.login(user)
|
||||
response = client.json.post(url, json.dumps(data))
|
||||
assert response.status_code == 200
|
||||
project = Project.objects.get(id=project.pk)
|
||||
assert project.tags_colors == [["newtag", "#123123"]]
|
||||
|
||||
|
||||
def test_create_tag_without_color(client, settings):
|
||||
user = f.UserFactory.create()
|
||||
project = f.ProjectFactory.create(owner=user)
|
||||
role = f.RoleFactory.create(project=project, permissions=["view_project"])
|
||||
membership = f.MembershipFactory.create(project=project, user=user, role=role, is_admin=True)
|
||||
url = reverse("projects-create-tag", args=(project.id,))
|
||||
client.login(user)
|
||||
data = {
|
||||
"tag": "newtag",
|
||||
}
|
||||
|
||||
client.login(user)
|
||||
response = client.json.post(url, json.dumps(data))
|
||||
assert response.status_code == 200
|
||||
project = Project.objects.get(id=project.pk)
|
||||
assert project.tags_colors[0][0] == "newtag"
|
||||
|
||||
|
||||
def test_edit_tag_only_name(client, settings):
|
||||
user = f.UserFactory.create()
|
||||
project = f.ProjectFactory.create(owner=user, tags_colors=[("tag", "#123123")])
|
||||
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"])
|
||||
|
||||
role = f.RoleFactory.create(project=project, permissions=["view_project"])
|
||||
membership = f.MembershipFactory.create(project=project, user=user, role=role, is_admin=True)
|
||||
url = reverse("projects-edit-tag", args=(project.id,))
|
||||
client.login(user)
|
||||
data = {
|
||||
"from_tag": "tag",
|
||||
"to_tag": "renamed_tag"
|
||||
}
|
||||
|
||||
client.login(user)
|
||||
response = client.json.post(url, json.dumps(data))
|
||||
print(response.data)
|
||||
assert response.status_code == 200
|
||||
project = Project.objects.get(id=project.pk)
|
||||
assert project.tags_colors == [["renamed_tag", "#123123"]]
|
||||
user_story = UserStory.objects.get(id=user_story.pk)
|
||||
assert user_story.tags == ["renamed_tag"]
|
||||
task = Task.objects.get(id=task.pk)
|
||||
assert task.tags == ["renamed_tag"]
|
||||
issue = Issue.objects.get(id=issue.pk)
|
||||
assert issue.tags == ["renamed_tag"]
|
||||
|
||||
|
||||
def test_edit_tag_only_color(client, settings):
|
||||
user = f.UserFactory.create()
|
||||
project = f.ProjectFactory.create(owner=user, tags_colors=[("tag", "#123123")])
|
||||
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"])
|
||||
|
||||
role = f.RoleFactory.create(project=project, permissions=["view_project"])
|
||||
membership = f.MembershipFactory.create(project=project, user=user, role=role, is_admin=True)
|
||||
url = reverse("projects-edit-tag", args=(project.id,))
|
||||
client.login(user)
|
||||
data = {
|
||||
"from_tag": "tag",
|
||||
"color": "#AAABBB"
|
||||
}
|
||||
|
||||
client.login(user)
|
||||
response = client.json.post(url, json.dumps(data))
|
||||
assert response.status_code == 200
|
||||
project = Project.objects.get(id=project.pk)
|
||||
assert project.tags_colors == [["tag", "#AAABBB"]]
|
||||
user_story = UserStory.objects.get(id=user_story.pk)
|
||||
assert user_story.tags == ["tag"]
|
||||
task = Task.objects.get(id=task.pk)
|
||||
assert task.tags == ["tag"]
|
||||
issue = Issue.objects.get(id=issue.pk)
|
||||
assert issue.tags == ["tag"]
|
||||
|
||||
|
||||
def test_edit_tag(client, settings):
|
||||
user = f.UserFactory.create()
|
||||
project = f.ProjectFactory.create(owner=user, tags_colors=[("tag", "#123123")])
|
||||
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"])
|
||||
|
||||
role = f.RoleFactory.create(project=project, permissions=["view_project"])
|
||||
membership = f.MembershipFactory.create(project=project, user=user, role=role, is_admin=True)
|
||||
url = reverse("projects-edit-tag", args=(project.id,))
|
||||
client.login(user)
|
||||
data = {
|
||||
"from_tag": "tag",
|
||||
"to_tag": "renamed_tag",
|
||||
"color": "#AAABBB"
|
||||
}
|
||||
|
||||
client.login(user)
|
||||
response = client.json.post(url, json.dumps(data))
|
||||
assert response.status_code == 200
|
||||
project = Project.objects.get(id=project.pk)
|
||||
assert project.tags_colors == [["renamed_tag", "#AAABBB"]]
|
||||
user_story = UserStory.objects.get(id=user_story.pk)
|
||||
assert user_story.tags == ["renamed_tag"]
|
||||
task = Task.objects.get(id=task.pk)
|
||||
assert task.tags == ["renamed_tag"]
|
||||
issue = Issue.objects.get(id=issue.pk)
|
||||
assert issue.tags == ["renamed_tag"]
|
||||
|
||||
|
||||
def test_delete_tag(client, settings):
|
||||
user = f.UserFactory.create()
|
||||
project = f.ProjectFactory.create(owner=user, tags_colors=[("tag", "#123123")])
|
||||
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"])
|
||||
|
||||
role = f.RoleFactory.create(project=project, permissions=["view_project"])
|
||||
membership = f.MembershipFactory.create(project=project, user=user, role=role, is_admin=True)
|
||||
url = reverse("projects-delete-tag", args=(project.id,))
|
||||
client.login(user)
|
||||
data = {
|
||||
"tag": "tag"
|
||||
}
|
||||
|
||||
client.login(user)
|
||||
response = client.json.post(url, json.dumps(data))
|
||||
assert response.status_code == 200
|
||||
project = Project.objects.get(id=project.pk)
|
||||
assert project.tags_colors == []
|
||||
user_story = UserStory.objects.get(id=user_story.pk)
|
||||
assert user_story.tags == []
|
||||
task = Task.objects.get(id=task.pk)
|
||||
assert task.tags == []
|
||||
issue = Issue.objects.get(id=issue.pk)
|
||||
assert issue.tags == []
|
||||
|
||||
|
||||
def test_mix_tags(client, settings):
|
||||
user = f.UserFactory.create()
|
||||
project = f.ProjectFactory.create(owner=user, tags_colors=[("tag1", "#123123"), ("tag2", "#123123"), ("tag3", "#123123")])
|
||||
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"])
|
||||
|
||||
role = f.RoleFactory.create(project=project, permissions=["view_project"])
|
||||
membership = f.MembershipFactory.create(project=project, user=user, role=role, is_admin=True)
|
||||
url = reverse("projects-mix-tags", args=(project.id,))
|
||||
client.login(user)
|
||||
data = {
|
||||
"from_tags": ["tag1", "tag2"],
|
||||
"to_tag": "tag2"
|
||||
}
|
||||
|
||||
client.login(user)
|
||||
response = client.json.post(url, json.dumps(data))
|
||||
assert response.status_code == 200
|
||||
project = Project.objects.get(id=project.pk)
|
||||
assert set(["tag2", "tag3"]) == set(dict(project.tags_colors).keys())
|
||||
user_story = UserStory.objects.get(id=user_story.pk)
|
||||
assert set(user_story.tags) == set(["tag2", "tag3"])
|
||||
task = Task.objects.get(id=task.pk)
|
||||
assert set(task.tags) == set(["tag2", "tag3"])
|
||||
issue = Issue.objects.get(id=issue.pk)
|
||||
assert set(issue.tags) == set(["tag2", "tag3"])
|
||||
|
||||
|
||||
def test_color_tags_project_fired_on_element_create():
|
||||
user_story = f.UserStoryFactory.create(tags=["tag"])
|
||||
project = Project.objects.get(id=user_story.project.id)
|
||||
|
@ -1875,4 +2061,3 @@ def test_color_tags_project_fired_on_element_update_respecting_color():
|
|||
user_story.save()
|
||||
project = Project.objects.get(id=user_story.project.id)
|
||||
assert project.tags_colors == [["tag", "#123123"]]
|
||||
>>>>>>> d64d158... WIP: migrations, removing automatic color generation
|
||||
|
|
|
@ -481,7 +481,7 @@ 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'])
|
||||
project = f.ProjectFactory(is_private=False, name="Testing project")
|
||||
role = f.RoleFactory(project=project, permissions=["view_project", "view_us", "view_tasks", "view_issues"])
|
||||
project.add_watcher(fav_user)
|
||||
|
||||
|
@ -499,11 +499,6 @@ def test_get_watched_list_valid_info_for_project():
|
|||
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["logo_small_url"] == get_thumbnail_url(project.logo, settings.THN_LOGO_SMALL)
|
||||
assert project_watch_info["is_fan"] == False
|
||||
|
@ -540,7 +535,7 @@ def test_get_liked_list_valid_info():
|
|||
fan_user = f.UserFactory()
|
||||
viewer_user = f.UserFactory()
|
||||
|
||||
project = f.ProjectFactory(is_private=False, name="Testing project", tags=['test', 'tag'])
|
||||
project = f.ProjectFactory(is_private=False, name="Testing project")
|
||||
content_type = ContentType.objects.get_for_model(project)
|
||||
like = f.LikeFactory(content_type=content_type, object_id=project.id, user=fan_user)
|
||||
project.refresh_totals()
|
||||
|
@ -558,11 +553,6 @@ def test_get_liked_list_valid_info():
|
|||
assert project_like_info["assigned_to"] == None
|
||||
assert project_like_info["status"] == None
|
||||
assert project_like_info["status_color"] == None
|
||||
|
||||
tags_colors = {tc["name"]:tc["color"] for tc in project_like_info["tags_colors"]}
|
||||
assert "test" in tags_colors
|
||||
assert "tag" in tags_colors
|
||||
|
||||
assert project_like_info["is_private"] == project.is_private
|
||||
assert project_like_info["logo_small_url"] == get_thumbnail_url(project.logo, settings.THN_LOGO_SMALL)
|
||||
|
||||
|
|
Loading…
Reference in New Issue