From aee57d61109f172fdf9ac3d161d98e197d08dcbf Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Mon, 29 Dec 2014 15:39:51 +0100 Subject: [PATCH] Moving archived status from userstory to status --- .../fixtures/initial_project_templates.json | 4 +-- .../migrations/0008_auto_20141024_1012.py | 6 ++-- .../0014_userstorystatus_is_archived.py | 20 ++++++++++++ .../migrations/0015_auto_20141230_1212.py | 31 +++++++++++++++++++ taiga/projects/models.py | 3 ++ taiga/projects/userstories/api.py | 2 +- .../0009_remove_userstory_is_archived.py | 18 +++++++++++ taiga/projects/userstories/models.py | 2 -- tests/integration/test_userstories.py | 7 +++-- 9 files changed, 82 insertions(+), 11 deletions(-) create mode 100644 taiga/projects/migrations/0014_userstorystatus_is_archived.py create mode 100644 taiga/projects/migrations/0015_auto_20141230_1212.py create mode 100644 taiga/projects/userstories/migrations/0009_remove_userstory_is_archived.py diff --git a/taiga/projects/fixtures/initial_project_templates.json b/taiga/projects/fixtures/initial_project_templates.json index 42d8118f..fe28fe42 100644 --- a/taiga/projects/fixtures/initial_project_templates.json +++ b/taiga/projects/fixtures/initial_project_templates.json @@ -6,7 +6,7 @@ "task_statuses": "[{\"color\": \"#999999\", \"order\": 1, \"is_closed\": false, \"name\": \"New\", \"slug\": \"new\"}, {\"color\": \"#ff9900\", \"order\": 2, \"is_closed\": false, \"name\": \"In progress\", \"slug\": \"in-progress\"}, {\"color\": \"#ffcc00\", \"order\": 3, \"is_closed\": true, \"name\": \"Ready for test\", \"slug\": \"ready-for-test\"}, {\"color\": \"#669900\", \"order\": 4, \"is_closed\": true, \"name\": \"Closed\", \"slug\": \"closed\"}, {\"color\": \"#999999\", \"order\": 5, \"is_closed\": false, \"name\": \"Needs Info\", \"slug\": \"needs-info\"}]", "is_backlog_activated": true, "modified_date": "2014-07-25T10:02:46.479Z", - "us_statuses": "[{\"color\": \"#999999\", \"order\": 1, \"is_closed\": false, \"wip_limit\": null, \"name\": \"New\", \"slug\": \"new\"}, {\"color\": \"#ff8a84\", \"order\": 2, \"is_closed\": false, \"wip_limit\": null, \"name\": \"Ready\", \"slug\": \"ready\"}, {\"color\": \"#ff9900\", \"order\": 3, \"is_closed\": false, \"wip_limit\": null, \"name\": \"In progress\", \"slug\": \"in-progress\"}, {\"color\": \"#fcc000\", \"order\": 4, \"is_closed\": false, \"wip_limit\": null, \"name\": \"Ready for test\", \"slug\": \"ready-for-test\"}, {\"color\": \"#669900\", \"order\": 5, \"is_closed\": true, \"wip_limit\": null, \"name\": \"Done\", \"slug\": \"done\"}]", + "us_statuses": "[{\"color\": \"#999999\", \"order\": 1, \"is_closed\": false, \"is_archived\": false, \"wip_limit\": null, \"name\": \"New\", \"slug\": \"new\"}, {\"color\": \"#ff8a84\", \"order\": 2, \"is_closed\": false, \"is_archived\": false, \"wip_limit\": null, \"name\": \"Ready\", \"slug\": \"ready\"}, {\"color\": \"#ff9900\", \"order\": 3, \"is_closed\": false, \"is_archived\": false, \"wip_limit\": null, \"name\": \"In progress\", \"slug\": \"in-progress\"}, {\"color\": \"#fcc000\", \"order\": 4, \"is_closed\": false, \"is_archived\": false, \"wip_limit\": null, \"name\": \"Ready for test\", \"slug\": \"ready-for-test\"}, {\"color\": \"#669900\", \"order\": 5, \"is_closed\": true, \"is_archived\": false, \"wip_limit\": null, \"name\": \"Done\", \"slug\": \"done\"}, {\"color\": \"#5c3566\", \"order\": 6, \"is_closed\": true, \"is_archived\": true, \"wip_limit\": null, \"name\": \"Archived\", \"slug\": \"archived\"}]", "is_wiki_activated": true, "roles": "[{\"order\": 10, \"slug\": \"ux\", \"permissions\": [\"add_issue\", \"modify_issue\", \"delete_issue\", \"view_issues\", \"add_milestone\", \"modify_milestone\", \"delete_milestone\", \"view_milestones\", \"view_project\", \"add_task\", \"modify_task\", \"delete_task\", \"view_tasks\", \"add_us\", \"modify_us\", \"delete_us\", \"view_us\", \"add_wiki_page\", \"modify_wiki_page\", \"delete_wiki_page\", \"view_wiki_pages\", \"add_wiki_link\", \"delete_wiki_link\", \"view_wiki_links\"], \"name\": \"UX\", \"computable\": true}, {\"order\": 20, \"slug\": \"design\", \"permissions\": [\"add_issue\", \"modify_issue\", \"delete_issue\", \"view_issues\", \"add_milestone\", \"modify_milestone\", \"delete_milestone\", \"view_milestones\", \"view_project\", \"add_task\", \"modify_task\", \"delete_task\", \"view_tasks\", \"add_us\", \"modify_us\", \"delete_us\", \"view_us\", \"add_wiki_page\", \"modify_wiki_page\", \"delete_wiki_page\", \"view_wiki_pages\", \"add_wiki_link\", \"delete_wiki_link\", \"view_wiki_links\"], \"name\": \"Design\", \"computable\": true}, {\"order\": 30, \"slug\": \"front\", \"permissions\": [\"add_issue\", \"modify_issue\", \"delete_issue\", \"view_issues\", \"add_milestone\", \"modify_milestone\", \"delete_milestone\", \"view_milestones\", \"view_project\", \"add_task\", \"modify_task\", \"delete_task\", \"view_tasks\", \"add_us\", \"modify_us\", \"delete_us\", \"view_us\", \"add_wiki_page\", \"modify_wiki_page\", \"delete_wiki_page\", \"view_wiki_pages\", \"add_wiki_link\", \"delete_wiki_link\", \"view_wiki_links\"], \"name\": \"Front\", \"computable\": true}, {\"order\": 40, \"slug\": \"back\", \"permissions\": [\"add_issue\", \"modify_issue\", \"delete_issue\", \"view_issues\", \"add_milestone\", \"modify_milestone\", \"delete_milestone\", \"view_milestones\", \"view_project\", \"add_task\", \"modify_task\", \"delete_task\", \"view_tasks\", \"add_us\", \"modify_us\", \"delete_us\", \"view_us\", \"add_wiki_page\", \"modify_wiki_page\", \"delete_wiki_page\", \"view_wiki_pages\", \"add_wiki_link\", \"delete_wiki_link\", \"view_wiki_links\"], \"name\": \"Back\", \"computable\": true}, {\"order\": 50, \"slug\": \"product-owner\", \"permissions\": [\"add_issue\", \"modify_issue\", \"delete_issue\", \"view_issues\", \"add_milestone\", \"modify_milestone\", \"delete_milestone\", \"view_milestones\", \"view_project\", \"add_task\", \"modify_task\", \"delete_task\", \"view_tasks\", \"add_us\", \"modify_us\", \"delete_us\", \"view_us\", \"add_wiki_page\", \"modify_wiki_page\", \"delete_wiki_page\", \"view_wiki_pages\", \"add_wiki_link\", \"delete_wiki_link\", \"view_wiki_links\"], \"name\": \"Product Owner\", \"computable\": false}, {\"order\": 60, \"slug\": \"stakeholder\", \"permissions\": [\"add_issue\", \"modify_issue\", \"delete_issue\", \"view_issues\", \"view_milestones\", \"view_project\", \"view_tasks\", \"view_us\", \"modify_wiki_page\", \"view_wiki_pages\", \"add_wiki_link\", \"delete_wiki_link\", \"view_wiki_links\"], \"name\": \"Stakeholder\", \"computable\": false}]", "points": "[{\"value\": null, \"order\": 1, \"name\": \"?\"}, {\"value\": 0.0, \"order\": 2, \"name\": \"0\"}, {\"value\": 0.5, \"order\": 3, \"name\": \"1/2\"}, {\"value\": 1.0, \"order\": 4, \"name\": \"1\"}, {\"value\": 2.0, \"order\": 5, \"name\": \"2\"}, {\"value\": 3.0, \"order\": 6, \"name\": \"3\"}, {\"value\": 5.0, \"order\": 7, \"name\": \"5\"}, {\"value\": 8.0, \"order\": 8, \"name\": \"8\"}, {\"value\": 10.0, \"order\": 9, \"name\": \"10\"}, {\"value\": 15.0, \"order\": 10, \"name\": \"15\"}, {\"value\": 20.0, \"order\": 11, \"name\": \"20\"}, {\"value\": 40.0, \"order\": 12, \"name\": \"40\"}]", @@ -33,7 +33,7 @@ "task_statuses": "[{\"color\": \"#999999\", \"order\": 1, \"is_closed\": false, \"name\": \"New\", \"slug\": \"new\"}, {\"color\": \"#729fcf\", \"order\": 2, \"is_closed\": false, \"name\": \"In progress\", \"slug\": \"in-progress\"}, {\"color\": \"#f57900\", \"order\": 3, \"is_closed\": true, \"name\": \"Ready for test\", \"slug\": \"ready-for-test\"}, {\"color\": \"#4e9a06\", \"order\": 4, \"is_closed\": true, \"name\": \"Closed\", \"slug\": \"closed\"}, {\"color\": \"#cc0000\", \"order\": 5, \"is_closed\": false, \"name\": \"Needs Info\", \"slug\": \"needs-info\"}]", "is_backlog_activated": false, "modified_date": "2014-07-25T13:11:42.754Z", - "us_statuses": "[{\"wip_limit\": null, \"order\": 1, \"is_closed\": false, \"color\": \"#999999\", \"name\": \"New\", \"slug\": \"new\"}, {\"wip_limit\": null, \"order\": 2, \"is_closed\": false, \"color\": \"#f57900\", \"name\": \"Ready\", \"slug\": \"ready\"}, {\"wip_limit\": null, \"order\": 3, \"is_closed\": false, \"color\": \"#729fcf\", \"name\": \"In progress\", \"slug\": \"in-progress\"}, {\"wip_limit\": null, \"order\": 4, \"is_closed\": false, \"color\": \"#4e9a06\", \"name\": \"Ready for test\", \"slug\": \"ready-for-test\"}, {\"wip_limit\": null, \"order\": 5, \"is_closed\": true, \"color\": \"#cc0000\", \"name\": \"Done\", \"slug\": \"done\"}]", + "us_statuses": "[{\"wip_limit\": null, \"order\": 1, \"is_closed\": false, \"is_archived\": false, \"color\": \"#999999\", \"name\": \"New\", \"slug\": \"new\"}, {\"wip_limit\": null, \"order\": 2, \"is_closed\": false, \"is_archived\": false, \"color\": \"#f57900\", \"name\": \"Ready\", \"slug\": \"ready\"}, {\"wip_limit\": null, \"order\": 3, \"is_closed\": false, \"is_archived\": false, \"color\": \"#729fcf\", \"name\": \"In progress\", \"slug\": \"in-progress\"}, {\"wip_limit\": null, \"order\": 4, \"is_closed\": false, \"is_archived\": false, \"color\": \"#4e9a06\", \"name\": \"Ready for test\", \"slug\": \"ready-for-test\"}, {\"wip_limit\": null, \"order\": 5, \"is_closed\": true, \"is_archived\": false, \"color\": \"#cc0000\", \"name\": \"Done\", \"slug\": \"done\"}, {\"wip_limit\": null, \"order\": 6, \"is_closed\": true, \"is_archived\": true, \"color\": \"#5c3566\", \"name\": \"Archived\", \"slug\": \"archived\"}]", "is_wiki_activated": false, "roles": "[{\"order\": 10, \"slug\": \"ux\", \"permissions\": [\"add_issue\", \"modify_issue\", \"delete_issue\", \"view_issues\", \"add_milestone\", \"modify_milestone\", \"delete_milestone\", \"view_milestones\", \"view_project\", \"add_task\", \"modify_task\", \"delete_task\", \"view_tasks\", \"add_us\", \"modify_us\", \"delete_us\", \"view_us\", \"add_wiki_page\", \"modify_wiki_page\", \"delete_wiki_page\", \"view_wiki_pages\", \"add_wiki_link\", \"delete_wiki_link\", \"view_wiki_links\"], \"name\": \"UX\", \"computable\": true}, {\"order\": 20, \"slug\": \"design\", \"permissions\": [\"add_issue\", \"modify_issue\", \"delete_issue\", \"view_issues\", \"add_milestone\", \"modify_milestone\", \"delete_milestone\", \"view_milestones\", \"view_project\", \"add_task\", \"modify_task\", \"delete_task\", \"view_tasks\", \"add_us\", \"modify_us\", \"delete_us\", \"view_us\", \"add_wiki_page\", \"modify_wiki_page\", \"delete_wiki_page\", \"view_wiki_pages\", \"add_wiki_link\", \"delete_wiki_link\", \"view_wiki_links\"], \"name\": \"Design\", \"computable\": true}, {\"order\": 30, \"slug\": \"front\", \"permissions\": [\"add_issue\", \"modify_issue\", \"delete_issue\", \"view_issues\", \"add_milestone\", \"modify_milestone\", \"delete_milestone\", \"view_milestones\", \"view_project\", \"add_task\", \"modify_task\", \"delete_task\", \"view_tasks\", \"add_us\", \"modify_us\", \"delete_us\", \"view_us\", \"add_wiki_page\", \"modify_wiki_page\", \"delete_wiki_page\", \"view_wiki_pages\", \"add_wiki_link\", \"delete_wiki_link\", \"view_wiki_links\"], \"name\": \"Front\", \"computable\": true}, {\"order\": 40, \"slug\": \"back\", \"permissions\": [\"add_issue\", \"modify_issue\", \"delete_issue\", \"view_issues\", \"add_milestone\", \"modify_milestone\", \"delete_milestone\", \"view_milestones\", \"view_project\", \"add_task\", \"modify_task\", \"delete_task\", \"view_tasks\", \"add_us\", \"modify_us\", \"delete_us\", \"view_us\", \"add_wiki_page\", \"modify_wiki_page\", \"delete_wiki_page\", \"view_wiki_pages\", \"add_wiki_link\", \"delete_wiki_link\", \"view_wiki_links\"], \"name\": \"Back\", \"computable\": true}, {\"order\": 50, \"slug\": \"product-owner\", \"permissions\": [\"add_issue\", \"modify_issue\", \"delete_issue\", \"view_issues\", \"add_milestone\", \"modify_milestone\", \"delete_milestone\", \"view_milestones\", \"view_project\", \"add_task\", \"modify_task\", \"delete_task\", \"view_tasks\", \"add_us\", \"modify_us\", \"delete_us\", \"view_us\", \"add_wiki_page\", \"modify_wiki_page\", \"delete_wiki_page\", \"view_wiki_pages\", \"add_wiki_link\", \"delete_wiki_link\", \"view_wiki_links\"], \"name\": \"Product Owner\", \"computable\": false}, {\"order\": 60, \"slug\": \"stakeholder\", \"permissions\": [\"add_issue\", \"modify_issue\", \"delete_issue\", \"view_issues\", \"view_milestones\", \"view_project\", \"view_tasks\", \"view_us\", \"modify_wiki_page\", \"view_wiki_pages\", \"add_wiki_link\", \"delete_wiki_link\", \"view_wiki_links\"], \"name\": \"Stakeholder\", \"computable\": false}]", "points": "[{\"value\": null, \"name\": \"?\", \"order\": 1}, {\"value\": 0.0, \"name\": \"0\", \"order\": 2}, {\"value\": 0.5, \"name\": \"1/2\", \"order\": 3}, {\"value\": 1.0, \"name\": \"1\", \"order\": 4}, {\"value\": 2.0, \"name\": \"2\", \"order\": 5}, {\"value\": 3.0, \"name\": \"3\", \"order\": 6}, {\"value\": 5.0, \"name\": \"5\", \"order\": 7}, {\"value\": 8.0, \"name\": \"8\", \"order\": 8}, {\"value\": 10.0, \"name\": \"10\", \"order\": 9}, {\"value\": 15.0, \"name\": \"15\", \"order\": 10}, {\"value\": 20.0, \"name\": \"20\", \"order\": 11}, {\"value\": 40.0, \"name\": \"40\", \"order\": 12}]", diff --git a/taiga/projects/migrations/0008_auto_20141024_1012.py b/taiga/projects/migrations/0008_auto_20141024_1012.py index a15b4713..2d4dd1b2 100644 --- a/taiga/projects/migrations/0008_auto_20141024_1012.py +++ b/taiga/projects/migrations/0008_auto_20141024_1012.py @@ -40,19 +40,19 @@ def update_many(objects, fields=[], using="default"): def update_slug(apps, schema_editor): - update_qs = UserStoryStatus.objects.all() + update_qs = UserStoryStatus.objects.all().only("name") for us_status in update_qs: us_status.slug = slugify(unidecode(us_status.name)) update_many(update_qs, fields=["slug"]) - update_qs = TaskStatus.objects.all() + update_qs = TaskStatus.objects.all().only("name") for task_status in update_qs: task_status.slug = slugify(unidecode(task_status.name)) update_many(update_qs, fields=["slug"]) - update_qs = IssueStatus.objects.all() + update_qs = IssueStatus.objects.all().only("name") for issue_status in update_qs: issue_status.slug = slugify(unidecode(issue_status.name)) diff --git a/taiga/projects/migrations/0014_userstorystatus_is_archived.py b/taiga/projects/migrations/0014_userstorystatus_is_archived.py new file mode 100644 index 00000000..889ee10b --- /dev/null +++ b/taiga/projects/migrations/0014_userstorystatus_is_archived.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('projects', '0013_auto_20141210_1040'), + ] + + operations = [ + migrations.AddField( + model_name='userstorystatus', + name='is_archived', + field=models.BooleanField(default=False, verbose_name='is archived'), + preserve_default=True, + ), + ] diff --git a/taiga/projects/migrations/0015_auto_20141230_1212.py b/taiga/projects/migrations/0015_auto_20141230_1212.py new file mode 100644 index 00000000..220ba920 --- /dev/null +++ b/taiga/projects/migrations/0015_auto_20141230_1212.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals +from django.db import models, migrations + + +def fix_project_template_us_status_archived(apps, schema_editor): + ProjectTemplate = apps.get_model("projects", "ProjectTemplate") + for pt in ProjectTemplate.objects.all(): + for us_status in pt.us_statuses: + us_status["is_archived"] = False + + pt.us_statuses.append({ + "color": "#5c3566", + "order": 6, + "is_closed": True, + "is_archived": True, + "wip_limit": None, + "name": "Archived", + "slug": "archived"}) + + pt.save() + +class Migration(migrations.Migration): + + dependencies = [ + ('projects', '0014_userstorystatus_is_archived'), + ] + + operations = [ + migrations.RunPython(fix_project_template_us_status_archived), + ] diff --git a/taiga/projects/models.py b/taiga/projects/models.py index 4c615d05..a90a70fe 100644 --- a/taiga/projects/models.py +++ b/taiga/projects/models.py @@ -323,6 +323,8 @@ class UserStoryStatus(models.Model): verbose_name=_("order")) is_closed = models.BooleanField(default=False, null=False, blank=True, verbose_name=_("is closed")) + is_archived = models.BooleanField(default=False, null=False, blank=True, + verbose_name=_("is archived")) color = models.CharField(max_length=20, null=False, blank=False, default="#999999", verbose_name=_("color")) wip_limit = models.IntegerField(null=True, blank=True, default=None, @@ -690,6 +692,7 @@ class ProjectTemplate(models.Model): name=us_status["name"], slug=us_status["slug"], is_closed=us_status["is_closed"], + is_archived=us_status["is_archived"], color=us_status["color"], wip_limit=us_status["wip_limit"], order=us_status["order"], diff --git a/taiga/projects/userstories/api.py b/taiga/projects/userstories/api.py index 796159e6..4ce739ec 100644 --- a/taiga/projects/userstories/api.py +++ b/taiga/projects/userstories/api.py @@ -52,7 +52,7 @@ class UserStoryViewSet(OCCResourceMixin, HistoryResourceMixin, WatchedResourceMi filter_backends = (filters.CanViewUsFilterBackend, filters.TagsFilter, filters.QFilter) retrieve_exclude_filters = (filters.TagsFilter,) - filter_fields = ['project', 'milestone', 'milestone__isnull', 'status', 'is_archived'] + filter_fields = ['project', 'milestone', 'milestone__isnull', 'status', 'is_archived', 'status__is_archived'] # Specific filter used for filtering neighbor user stories _neighbor_tags_filter = filters.TagsFilter('neighbor_tags') diff --git a/taiga/projects/userstories/migrations/0009_remove_userstory_is_archived.py b/taiga/projects/userstories/migrations/0009_remove_userstory_is_archived.py new file mode 100644 index 00000000..7b5c72fd --- /dev/null +++ b/taiga/projects/userstories/migrations/0009_remove_userstory_is_archived.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('userstories', '0008_auto_20141210_1107'), + ] + + operations = [ + migrations.RemoveField( + model_name='userstory', + name='is_archived', + ), + ] diff --git a/taiga/projects/userstories/models.py b/taiga/projects/userstories/models.py index 54458b3c..a9f64a68 100644 --- a/taiga/projects/userstories/models.py +++ b/taiga/projects/userstories/models.py @@ -64,8 +64,6 @@ class UserStory(OCCModelMixin, WatchedModelMixin, BlockedMixin, TaggedMixin, mod related_name="user_stories", verbose_name=_("status"), on_delete=models.SET_NULL) is_closed = models.BooleanField(default=False) - is_archived = models.BooleanField(default=False, null=False, blank=True, - verbose_name=_("archived")) points = models.ManyToManyField("projects.Points", null=False, blank=False, related_name="userstories", through="RolePoints", verbose_name=_("points")) diff --git a/tests/integration/test_userstories.py b/tests/integration/test_userstories.py index caad1435..a9070e50 100644 --- a/tests/integration/test_userstories.py +++ b/tests/integration/test_userstories.py @@ -190,7 +190,8 @@ def test_archived_filter(client): project = f.ProjectFactory.create(owner=user) f.MembershipFactory.create(project=project, user=user, is_owner=True) f.UserStoryFactory.create(project=project) - f.UserStoryFactory.create(is_archived=True, project=project) + archived_status = f.UserStoryStatusFactory.create(is_archived=True) + f.UserStoryFactory.create(status=archived_status, project=project) client.login(user) @@ -200,11 +201,11 @@ def test_archived_filter(client): response = client.get(url, data) assert len(json.loads(response.content)) == 2 - data = {"is_archived": 0} + data = {"status__is_archived": 0} response = client.get(url, data) assert len(json.loads(response.content)) == 1 - data = {"is_archived": 1} + data = {"status__is_archived": 1} response = client.get(url, data) assert len(json.loads(response.content)) == 1