US#45: Working the base of the proyect template system
parent
4887ca55a9
commit
ee75818a18
|
@ -1,3 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
python ./manage.py dumpdata -n --indent=4 users.Role > taiga/users/fixtures/initial_role.json
|
|
|
@ -15,10 +15,11 @@ echo "-> Load initial domain"
|
||||||
python manage.py loaddata initial_domains --traceback
|
python manage.py loaddata initial_domains --traceback
|
||||||
echo "-> Load initial user"
|
echo "-> Load initial user"
|
||||||
python manage.py loaddata initial_user --traceback
|
python manage.py loaddata initial_user --traceback
|
||||||
|
echo "-> Load initial project_templates"
|
||||||
|
python manage.py loaddata initial_project_templates --traceback
|
||||||
echo "-> Load initial roles"
|
echo "-> Load initial roles"
|
||||||
python manage.py loaddata initial_role --traceback
|
python manage.py loaddata initial_role --traceback
|
||||||
echo "-> Generate sample data"
|
echo "-> Generate sample data"
|
||||||
python manage.py sample_data --traceback
|
python manage.py sample_data --traceback
|
||||||
echo "-> Generate initial versions of objects"
|
echo "-> Generate initial versions of objects"
|
||||||
python manage.py createinitialrevisions --traceback
|
python manage.py createinitialrevisions --traceback
|
||||||
|
|
||||||
|
|
|
@ -293,6 +293,7 @@ REST_FRAMEWORK = {
|
||||||
"MAX_PAGINATE_BY": 1000,
|
"MAX_PAGINATE_BY": 1000,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFAULT_PROJECT_TEMPLATE = "scrum"
|
||||||
|
|
||||||
# NOTE: DON'T INSERT MORE SETTINGS AFTER THIS LINE
|
# NOTE: DON'T INSERT MORE SETTINGS AFTER THIS LINE
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ urls.urlpatterns += patterns("",
|
||||||
|
|
||||||
|
|
||||||
class AuthServicesTests(test.TestCase):
|
class AuthServicesTests(test.TestCase):
|
||||||
fixtures = ["initial_domains.json",]
|
fixtures = ["initial_domains.json", "initial_project_templates.json",]
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.user1 = create_user(1)
|
self.user1 = create_user(1)
|
||||||
|
@ -184,7 +184,7 @@ class TokenAuthenticationBackendTests(test.TestCase):
|
||||||
|
|
||||||
|
|
||||||
class RegisterApiTests(test.TestCase):
|
class RegisterApiTests(test.TestCase):
|
||||||
fixtures = ["initial_domains.json",]
|
fixtures = ["initial_domains.json", "initial_project_templates.json",]
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.user1 = create_user(1)
|
self.user1 = create_user(1)
|
||||||
|
|
|
@ -21,6 +21,8 @@ from rest_framework import serializers
|
||||||
from reversion.models import Version
|
from reversion.models import Version
|
||||||
import reversion
|
import reversion
|
||||||
|
|
||||||
|
from taiga.domains.base import get_active_domain
|
||||||
|
|
||||||
|
|
||||||
class PickleField(serializers.WritableField):
|
class PickleField(serializers.WritableField):
|
||||||
"""
|
"""
|
||||||
|
@ -33,6 +35,27 @@ class PickleField(serializers.WritableField):
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
class JsonField(serializers.WritableField):
|
||||||
|
"""
|
||||||
|
Json objects serializer.
|
||||||
|
"""
|
||||||
|
def to_native(self, obj):
|
||||||
|
return obj
|
||||||
|
|
||||||
|
def from_native(self, data):
|
||||||
|
return data
|
||||||
|
|
||||||
|
class AutoDomainField(serializers.WritableField):
|
||||||
|
"""
|
||||||
|
Automatically set domain field serializer.
|
||||||
|
"""
|
||||||
|
def to_native(self, obj):
|
||||||
|
return obj
|
||||||
|
|
||||||
|
def from_native(self, data):
|
||||||
|
domain = get_active_domain()
|
||||||
|
return domain.id
|
||||||
|
|
||||||
class VersionSerializer(serializers.ModelSerializer):
|
class VersionSerializer(serializers.ModelSerializer):
|
||||||
created_date = serializers.SerializerMethodField("get_created_date")
|
created_date = serializers.SerializerMethodField("get_created_date")
|
||||||
content_type = serializers.SerializerMethodField("get_content_type")
|
content_type = serializers.SerializerMethodField("get_content_type")
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from taiga.users.serializers import UserSerializer
|
from taiga.users.serializers import UserSerializer
|
||||||
|
|
||||||
|
@ -20,14 +22,18 @@ from .models import Domain, DomainMember
|
||||||
|
|
||||||
class DomainSerializer(serializers.ModelSerializer):
|
class DomainSerializer(serializers.ModelSerializer):
|
||||||
projects = serializers.SerializerMethodField('get_projects')
|
projects = serializers.SerializerMethodField('get_projects')
|
||||||
|
default_project_template = serializers.SerializerMethodField('get_default_project_template')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Domain
|
model = Domain
|
||||||
fields = ('public_register', 'default_language', "projects")
|
fields = ('public_register', 'default_language', "projects", "default_project_template")
|
||||||
|
|
||||||
def get_projects(self, obj):
|
def get_projects(self, obj):
|
||||||
return map(lambda x: {"id": x.id, "name": x.name, "slug": x.slug, "owner": x.owner.id}, obj.projects.all().order_by('name'))
|
return map(lambda x: {"id": x.id, "name": x.name, "slug": x.slug, "owner": x.owner.id}, obj.projects.all().order_by('name'))
|
||||||
|
|
||||||
|
def get_default_project_template(self, obj):
|
||||||
|
return settings.DEFAULT_PROJECT_TEMPLATE
|
||||||
|
|
||||||
|
|
||||||
class DomainMemberSerializer(serializers.ModelSerializer):
|
class DomainMemberSerializer(serializers.ModelSerializer):
|
||||||
user = UserSerializer()
|
user = UserSerializer()
|
||||||
|
|
|
@ -51,7 +51,7 @@ from unittest.mock import MagicMock
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
class ChangesTest(test.TestCase):
|
class ChangesTest(test.TestCase):
|
||||||
fixtures = ["initial_domains.json"]
|
fixtures = ["initial_domains.json", "initial_project_templates.json"]
|
||||||
|
|
||||||
def test_emit_change_for_model(self):
|
def test_emit_change_for_model(self):
|
||||||
user = create_user(1) # Project owner
|
user = create_user(1) # Project owner
|
||||||
|
|
|
@ -298,3 +298,12 @@ class QuestionStatusViewSet(ModelCrudViewSet, BulkUpdateOrderMixin):
|
||||||
bulk_update_param = "bulk_question_statuses"
|
bulk_update_param = "bulk_question_statuses"
|
||||||
bulk_update_perm = "change_questionstatus"
|
bulk_update_perm = "change_questionstatus"
|
||||||
bulk_update_order = services.bulk_update_question_status_order
|
bulk_update_order = services.bulk_update_question_status_order
|
||||||
|
|
||||||
|
class ProjectTemplateViewSet(ModelCrudViewSet):
|
||||||
|
model = models.ProjectTemplate
|
||||||
|
serializer_class = serializers.ProjectTemplateSerializer
|
||||||
|
permission_classes = (IsAuthenticated, permissions.ProjectTemplatePermission)
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
domain = get_active_domain()
|
||||||
|
return models.ProjectTemplate.objects.filter(Q(domain=domain) | Q(domain__isnull=True))
|
||||||
|
|
|
@ -14,463 +14,7 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
|
||||||
|
|
||||||
|
|
||||||
VIDEOCONFERENCES_CHOICES = (
|
VIDEOCONFERENCES_CHOICES = (
|
||||||
("appear-in", "AppearIn"),
|
("appear-in", "AppearIn"),
|
||||||
("talky", "Talky"),
|
("talky", "Talky"),
|
||||||
)
|
)
|
||||||
|
|
||||||
US_STATUSES = (
|
|
||||||
(1, _("Open"), False, True, "#669933"),
|
|
||||||
(2, _("Closed"), True, False, "#999999"),
|
|
||||||
)
|
|
||||||
|
|
||||||
TASK_STATUSES = (
|
|
||||||
(1, _("New"), False, True, "#999999"),
|
|
||||||
(2, _("In progress"), False, False, "#ff9900"),
|
|
||||||
(3, _("Ready for test"), True, False, "#ffcc00"),
|
|
||||||
(4, _("Closed"), True, False, "#669900"),
|
|
||||||
(5, _("Needs Info"), False, False, "#999999"),
|
|
||||||
)
|
|
||||||
|
|
||||||
POINTS_CHOICES = (
|
|
||||||
(1, u"?", None, True),
|
|
||||||
(2, u"0", 0, False),
|
|
||||||
(3, u"1/2", 0.5, False),
|
|
||||||
(4, u"1", 1, False),
|
|
||||||
(5, u"2", 2, False),
|
|
||||||
(6, u"3", 3, False),
|
|
||||||
(7, u"5", 5, False),
|
|
||||||
(8, u"8", 8, False),
|
|
||||||
(9, u"10", 10, False),
|
|
||||||
(10, u"15", 15, False),
|
|
||||||
(11, u"20", 20, False),
|
|
||||||
(12, u"40", 40, False),
|
|
||||||
)
|
|
||||||
|
|
||||||
PRIORITY_CHOICES = (
|
|
||||||
(1, _(u"Low"), "#666666", False),
|
|
||||||
(3, _(u"Normal"), "#669933", True),
|
|
||||||
(5, _(u"High"), "#CC0000", False),
|
|
||||||
)
|
|
||||||
|
|
||||||
SEVERITY_CHOICES = (
|
|
||||||
(1, _(u"Wishlist"), "#666666", False),
|
|
||||||
(2, _(u"Minor"), "#669933", False),
|
|
||||||
(3, _(u"Normal"), "#0000FF", True),
|
|
||||||
(4, _(u"Important"), "#FFA500", False),
|
|
||||||
(5, _(u"Critical"), "#CC0000", False),
|
|
||||||
)
|
|
||||||
|
|
||||||
ISSUE_STATUSES = (
|
|
||||||
(1, _("New"), False, "#8C2318", True),
|
|
||||||
(2, _("In progress"), False, "#5E8C6A", False),
|
|
||||||
(3, _("Ready for test"), True, "#88A65E", False),
|
|
||||||
(4, _("Closed"), True, "#BFB35A", False),
|
|
||||||
(5, _("Needs Info"), False, "#89BAB4", False),
|
|
||||||
(6, _("Rejected"), True, "#CC0000", False),
|
|
||||||
(7, _("Postponed"), False, "#666666", False),
|
|
||||||
)
|
|
||||||
|
|
||||||
ISSUE_TYPES = (
|
|
||||||
(1, _(u"Bug"), "#89BAB4", True),
|
|
||||||
)
|
|
||||||
|
|
||||||
QUESTION_STATUS = (
|
|
||||||
(1, _("Pending"), False, "#FFA500", True),
|
|
||||||
(2, _("Answered"), False, "#669933", False),
|
|
||||||
(3, _("Closed"), True,"#BFB35A", False),
|
|
||||||
)
|
|
||||||
|
|
||||||
ROLES = (
|
|
||||||
(10, "ux", "UX", True, [
|
|
||||||
[ "add_issue", "issues", "issue" ],
|
|
||||||
[ "change_issue", "issues", "issue" ],
|
|
||||||
[ "delete_issue", "issues", "issue" ],
|
|
||||||
[ "view_issue", "issues", "issue" ],
|
|
||||||
[ "add_milestone", "milestones", "milestone" ],
|
|
||||||
[ "change_milestone", "milestones", "milestone" ],
|
|
||||||
[ "delete_milestone", "milestones", "milestone" ],
|
|
||||||
[ "view_milestone", "milestones", "milestone" ],
|
|
||||||
[ "add_attachment", "projects", "attachment" ],
|
|
||||||
[ "change_attachment", "projects", "attachment" ],
|
|
||||||
[ "delete_attachment", "projects", "attachment" ],
|
|
||||||
[ "view_attachment", "projects", "attachment" ],
|
|
||||||
[ "add_issuestatus", "projects", "issuestatus" ],
|
|
||||||
[ "change_issuestatus", "projects", "issuestatus" ],
|
|
||||||
[ "delete_issuestatus", "projects", "issuestatus" ],
|
|
||||||
[ "view_issuestatus", "projects", "issuestatus" ],
|
|
||||||
[ "add_issuetype", "projects", "issuetype" ],
|
|
||||||
[ "change_issuetype", "projects", "issuetype" ],
|
|
||||||
[ "delete_issuetype", "projects", "issuetype" ],
|
|
||||||
[ "view_issuetype", "projects", "issuetype" ],
|
|
||||||
[ "add_membership", "projects", "membership" ],
|
|
||||||
[ "change_membership", "projects", "membership" ],
|
|
||||||
[ "delete_membership", "projects", "membership" ],
|
|
||||||
[ "view_membership", "projects", "membership" ],
|
|
||||||
[ "add_points", "projects", "points" ],
|
|
||||||
[ "change_points", "projects", "points" ],
|
|
||||||
[ "delete_points", "projects", "points" ],
|
|
||||||
[ "view_points", "projects", "points" ],
|
|
||||||
[ "add_priority", "projects", "priority" ],
|
|
||||||
[ "change_priority", "projects", "priority" ],
|
|
||||||
[ "delete_priority", "projects", "priority" ],
|
|
||||||
[ "view_priority", "projects", "priority" ],
|
|
||||||
[ "add_project", "projects", "project" ],
|
|
||||||
[ "change_project", "projects", "project" ],
|
|
||||||
[ "delete_project", "projects", "project" ],
|
|
||||||
[ "view_project", "projects", "project" ],
|
|
||||||
[ "add_severity", "projects", "severity" ],
|
|
||||||
[ "change_severity", "projects", "severity" ],
|
|
||||||
[ "delete_severity", "projects", "severity" ],
|
|
||||||
[ "view_severity", "projects", "severity" ],
|
|
||||||
[ "add_taskstatus", "projects", "taskstatus" ],
|
|
||||||
[ "change_taskstatus", "projects", "taskstatus" ],
|
|
||||||
[ "delete_taskstatus", "projects", "taskstatus" ],
|
|
||||||
[ "view_taskstatus", "projects", "taskstatus" ],
|
|
||||||
[ "add_userstorystatus", "projects", "userstorystatus" ],
|
|
||||||
[ "change_userstorystatus", "projects", "userstorystatus" ],
|
|
||||||
[ "delete_userstorystatus", "projects", "userstorystatus" ],
|
|
||||||
[ "view_userstorystatus", "projects", "userstorystatus" ],
|
|
||||||
[ "add_task", "tasks", "task" ],
|
|
||||||
[ "change_task", "tasks", "task" ],
|
|
||||||
[ "delete_task", "tasks", "task" ],
|
|
||||||
[ "view_task", "tasks", "task" ],
|
|
||||||
[ "add_role", "users", "role" ],
|
|
||||||
[ "change_role", "users", "role" ],
|
|
||||||
[ "delete_role", "users", "role" ],
|
|
||||||
[ "view_role", "users", "role" ],
|
|
||||||
[ "change_user", "users", "user" ],
|
|
||||||
[ "view_user", "users", "user" ],
|
|
||||||
[ "add_rolepoints", "userstories", "rolepoints" ],
|
|
||||||
[ "change_rolepoints", "userstories", "rolepoints" ],
|
|
||||||
[ "delete_rolepoints", "userstories", "rolepoints" ],
|
|
||||||
[ "view_rolepoints", "userstories", "rolepoints" ],
|
|
||||||
[ "add_userstory", "userstories", "userstory" ],
|
|
||||||
[ "change_userstory", "userstories", "userstory" ],
|
|
||||||
[ "delete_userstory", "userstories", "userstory" ],
|
|
||||||
[ "view_userstory", "userstories", "userstory" ],
|
|
||||||
[ "add_wikipage", "wiki", "wikipage" ],
|
|
||||||
[ "change_wikipage", "wiki", "wikipage" ],
|
|
||||||
[ "delete_wikipage", "wiki", "wikipage" ],
|
|
||||||
[ "view_wikipage", "wiki", "wikipage" ]
|
|
||||||
]),
|
|
||||||
(20, "design", "Design", True, [
|
|
||||||
[ "add_issue", "issues", "issue" ],
|
|
||||||
[ "change_issue", "issues", "issue" ],
|
|
||||||
[ "delete_issue", "issues", "issue" ],
|
|
||||||
[ "view_issue", "issues", "issue" ],
|
|
||||||
[ "add_milestone", "milestones", "milestone" ],
|
|
||||||
[ "change_milestone", "milestones", "milestone" ],
|
|
||||||
[ "delete_milestone", "milestones", "milestone" ],
|
|
||||||
[ "view_milestone", "milestones", "milestone" ],
|
|
||||||
[ "add_attachment", "projects", "attachment" ],
|
|
||||||
[ "change_attachment", "projects", "attachment" ],
|
|
||||||
[ "delete_attachment", "projects", "attachment" ],
|
|
||||||
[ "view_attachment", "projects", "attachment" ],
|
|
||||||
[ "add_issuestatus", "projects", "issuestatus" ],
|
|
||||||
[ "change_issuestatus", "projects", "issuestatus" ],
|
|
||||||
[ "delete_issuestatus", "projects", "issuestatus" ],
|
|
||||||
[ "view_issuestatus", "projects", "issuestatus" ],
|
|
||||||
[ "add_issuetype", "projects", "issuetype" ],
|
|
||||||
[ "change_issuetype", "projects", "issuetype" ],
|
|
||||||
[ "delete_issuetype", "projects", "issuetype" ],
|
|
||||||
[ "view_issuetype", "projects", "issuetype" ],
|
|
||||||
[ "add_membership", "projects", "membership" ],
|
|
||||||
[ "change_membership", "projects", "membership" ],
|
|
||||||
[ "delete_membership", "projects", "membership" ],
|
|
||||||
[ "view_membership", "projects", "membership" ],
|
|
||||||
[ "add_points", "projects", "points" ],
|
|
||||||
[ "change_points", "projects", "points" ],
|
|
||||||
[ "delete_points", "projects", "points" ],
|
|
||||||
[ "view_points", "projects", "points" ],
|
|
||||||
[ "add_priority", "projects", "priority" ],
|
|
||||||
[ "change_priority", "projects", "priority" ],
|
|
||||||
[ "delete_priority", "projects", "priority" ],
|
|
||||||
[ "view_priority", "projects", "priority" ],
|
|
||||||
[ "add_project", "projects", "project" ],
|
|
||||||
[ "change_project", "projects", "project" ],
|
|
||||||
[ "delete_project", "projects", "project" ],
|
|
||||||
[ "view_project", "projects", "project" ],
|
|
||||||
[ "add_severity", "projects", "severity" ],
|
|
||||||
[ "change_severity", "projects", "severity" ],
|
|
||||||
[ "delete_severity", "projects", "severity" ],
|
|
||||||
[ "view_severity", "projects", "severity" ],
|
|
||||||
[ "add_taskstatus", "projects", "taskstatus" ],
|
|
||||||
[ "change_taskstatus", "projects", "taskstatus" ],
|
|
||||||
[ "delete_taskstatus", "projects", "taskstatus" ],
|
|
||||||
[ "view_taskstatus", "projects", "taskstatus" ],
|
|
||||||
[ "add_userstorystatus", "projects", "userstorystatus" ],
|
|
||||||
[ "change_userstorystatus", "projects", "userstorystatus" ],
|
|
||||||
[ "delete_userstorystatus", "projects", "userstorystatus" ],
|
|
||||||
[ "view_userstorystatus", "projects", "userstorystatus" ],
|
|
||||||
[ "add_task", "tasks", "task" ],
|
|
||||||
[ "change_task", "tasks", "task" ],
|
|
||||||
[ "delete_task", "tasks", "task" ],
|
|
||||||
[ "view_task", "tasks", "task" ],
|
|
||||||
[ "add_role", "users", "role" ],
|
|
||||||
[ "change_role", "users", "role" ],
|
|
||||||
[ "delete_role", "users", "role" ],
|
|
||||||
[ "view_role", "users", "role" ],
|
|
||||||
[ "change_user", "users", "user" ],
|
|
||||||
[ "view_user", "users", "user" ],
|
|
||||||
[ "add_rolepoints", "userstories", "rolepoints" ],
|
|
||||||
[ "change_rolepoints", "userstories", "rolepoints" ],
|
|
||||||
[ "delete_rolepoints", "userstories", "rolepoints" ],
|
|
||||||
[ "view_rolepoints", "userstories", "rolepoints" ],
|
|
||||||
[ "add_userstory", "userstories", "userstory" ],
|
|
||||||
[ "change_userstory", "userstories", "userstory" ],
|
|
||||||
[ "delete_userstory", "userstories", "userstory" ],
|
|
||||||
[ "view_userstory", "userstories", "userstory" ],
|
|
||||||
[ "add_wikipage", "wiki", "wikipage" ],
|
|
||||||
[ "change_wikipage", "wiki", "wikipage" ],
|
|
||||||
[ "delete_wikipage", "wiki", "wikipage" ],
|
|
||||||
[ "view_wikipage", "wiki", "wikipage" ]
|
|
||||||
]),
|
|
||||||
(30, "front", "Front", True, [
|
|
||||||
[ "add_issue", "issues", "issue" ],
|
|
||||||
[ "change_issue", "issues", "issue" ],
|
|
||||||
[ "delete_issue", "issues", "issue" ],
|
|
||||||
[ "view_issue", "issues", "issue" ],
|
|
||||||
[ "add_milestone", "milestones", "milestone" ],
|
|
||||||
[ "change_milestone", "milestones", "milestone" ],
|
|
||||||
[ "delete_milestone", "milestones", "milestone" ],
|
|
||||||
[ "view_milestone", "milestones", "milestone" ],
|
|
||||||
[ "add_attachment", "projects", "attachment" ],
|
|
||||||
[ "change_attachment", "projects", "attachment" ],
|
|
||||||
[ "delete_attachment", "projects", "attachment" ],
|
|
||||||
[ "view_attachment", "projects", "attachment" ],
|
|
||||||
[ "add_issuestatus", "projects", "issuestatus" ],
|
|
||||||
[ "change_issuestatus", "projects", "issuestatus" ],
|
|
||||||
[ "delete_issuestatus", "projects", "issuestatus" ],
|
|
||||||
[ "view_issuestatus", "projects", "issuestatus" ],
|
|
||||||
[ "add_issuetype", "projects", "issuetype" ],
|
|
||||||
[ "change_issuetype", "projects", "issuetype" ],
|
|
||||||
[ "delete_issuetype", "projects", "issuetype" ],
|
|
||||||
[ "view_issuetype", "projects", "issuetype" ],
|
|
||||||
[ "add_membership", "projects", "membership" ],
|
|
||||||
[ "change_membership", "projects", "membership" ],
|
|
||||||
[ "delete_membership", "projects", "membership" ],
|
|
||||||
[ "view_membership", "projects", "membership" ],
|
|
||||||
[ "add_points", "projects", "points" ],
|
|
||||||
[ "change_points", "projects", "points" ],
|
|
||||||
[ "delete_points", "projects", "points" ],
|
|
||||||
[ "view_points", "projects", "points" ],
|
|
||||||
[ "add_priority", "projects", "priority" ],
|
|
||||||
[ "change_priority", "projects", "priority" ],
|
|
||||||
[ "delete_priority", "projects", "priority" ],
|
|
||||||
[ "view_priority", "projects", "priority" ],
|
|
||||||
[ "add_project", "projects", "project" ],
|
|
||||||
[ "change_project", "projects", "project" ],
|
|
||||||
[ "delete_project", "projects", "project" ],
|
|
||||||
[ "view_project", "projects", "project" ],
|
|
||||||
[ "add_severity", "projects", "severity" ],
|
|
||||||
[ "change_severity", "projects", "severity" ],
|
|
||||||
[ "delete_severity", "projects", "severity" ],
|
|
||||||
[ "view_severity", "projects", "severity" ],
|
|
||||||
[ "add_taskstatus", "projects", "taskstatus" ],
|
|
||||||
[ "change_taskstatus", "projects", "taskstatus" ],
|
|
||||||
[ "delete_taskstatus", "projects", "taskstatus" ],
|
|
||||||
[ "view_taskstatus", "projects", "taskstatus" ],
|
|
||||||
[ "add_userstorystatus", "projects", "userstorystatus" ],
|
|
||||||
[ "change_userstorystatus", "projects", "userstorystatus" ],
|
|
||||||
[ "delete_userstorystatus", "projects", "userstorystatus" ],
|
|
||||||
[ "view_userstorystatus", "projects", "userstorystatus" ],
|
|
||||||
[ "add_task", "tasks", "task" ],
|
|
||||||
[ "change_task", "tasks", "task" ],
|
|
||||||
[ "delete_task", "tasks", "task" ],
|
|
||||||
[ "view_task", "tasks", "task" ],
|
|
||||||
[ "add_role", "users", "role" ],
|
|
||||||
[ "change_role", "users", "role" ],
|
|
||||||
[ "delete_role", "users", "role" ],
|
|
||||||
[ "view_role", "users", "role" ],
|
|
||||||
[ "change_user", "users", "user" ],
|
|
||||||
[ "view_user", "users", "user" ],
|
|
||||||
[ "add_rolepoints", "userstories", "rolepoints" ],
|
|
||||||
[ "change_rolepoints", "userstories", "rolepoints" ],
|
|
||||||
[ "delete_rolepoints", "userstories", "rolepoints" ],
|
|
||||||
[ "view_rolepoints", "userstories", "rolepoints" ],
|
|
||||||
[ "add_userstory", "userstories", "userstory" ],
|
|
||||||
[ "change_userstory", "userstories", "userstory" ],
|
|
||||||
[ "delete_userstory", "userstories", "userstory" ],
|
|
||||||
[ "view_userstory", "userstories", "userstory" ],
|
|
||||||
[ "add_wikipage", "wiki", "wikipage" ],
|
|
||||||
[ "change_wikipage", "wiki", "wikipage" ],
|
|
||||||
[ "delete_wikipage", "wiki", "wikipage" ],
|
|
||||||
[ "view_wikipage", "wiki", "wikipage" ]
|
|
||||||
]),
|
|
||||||
(40, "back", "Back", True, [
|
|
||||||
[ "add_issue", "issues", "issue" ],
|
|
||||||
[ "change_issue", "issues", "issue" ],
|
|
||||||
[ "delete_issue", "issues", "issue" ],
|
|
||||||
[ "view_issue", "issues", "issue" ],
|
|
||||||
[ "add_milestone", "milestones", "milestone" ],
|
|
||||||
[ "change_milestone", "milestones", "milestone" ],
|
|
||||||
[ "delete_milestone", "milestones", "milestone" ],
|
|
||||||
[ "view_milestone", "milestones", "milestone" ],
|
|
||||||
[ "add_attachment", "projects", "attachment" ],
|
|
||||||
[ "change_attachment", "projects", "attachment" ],
|
|
||||||
[ "delete_attachment", "projects", "attachment" ],
|
|
||||||
[ "view_attachment", "projects", "attachment" ],
|
|
||||||
[ "add_issuestatus", "projects", "issuestatus" ],
|
|
||||||
[ "change_issuestatus", "projects", "issuestatus" ],
|
|
||||||
[ "delete_issuestatus", "projects", "issuestatus" ],
|
|
||||||
[ "view_issuestatus", "projects", "issuestatus" ],
|
|
||||||
[ "add_issuetype", "projects", "issuetype" ],
|
|
||||||
[ "change_issuetype", "projects", "issuetype" ],
|
|
||||||
[ "delete_issuetype", "projects", "issuetype" ],
|
|
||||||
[ "view_issuetype", "projects", "issuetype" ],
|
|
||||||
[ "add_membership", "projects", "membership" ],
|
|
||||||
[ "change_membership", "projects", "membership" ],
|
|
||||||
[ "delete_membership", "projects", "membership" ],
|
|
||||||
[ "view_membership", "projects", "membership" ],
|
|
||||||
[ "add_points", "projects", "points" ],
|
|
||||||
[ "change_points", "projects", "points" ],
|
|
||||||
[ "delete_points", "projects", "points" ],
|
|
||||||
[ "view_points", "projects", "points" ],
|
|
||||||
[ "add_priority", "projects", "priority" ],
|
|
||||||
[ "change_priority", "projects", "priority" ],
|
|
||||||
[ "delete_priority", "projects", "priority" ],
|
|
||||||
[ "view_priority", "projects", "priority" ],
|
|
||||||
[ "add_project", "projects", "project" ],
|
|
||||||
[ "change_project", "projects", "project" ],
|
|
||||||
[ "delete_project", "projects", "project" ],
|
|
||||||
[ "view_project", "projects", "project" ],
|
|
||||||
[ "add_severity", "projects", "severity" ],
|
|
||||||
[ "change_severity", "projects", "severity" ],
|
|
||||||
[ "delete_severity", "projects", "severity" ],
|
|
||||||
[ "view_severity", "projects", "severity" ],
|
|
||||||
[ "add_taskstatus", "projects", "taskstatus" ],
|
|
||||||
[ "change_taskstatus", "projects", "taskstatus" ],
|
|
||||||
[ "delete_taskstatus", "projects", "taskstatus" ],
|
|
||||||
[ "view_taskstatus", "projects", "taskstatus" ],
|
|
||||||
[ "add_userstorystatus", "projects", "userstorystatus" ],
|
|
||||||
[ "change_userstorystatus", "projects", "userstorystatus" ],
|
|
||||||
[ "delete_userstorystatus", "projects", "userstorystatus" ],
|
|
||||||
[ "view_userstorystatus", "projects", "userstorystatus" ],
|
|
||||||
[ "add_task", "tasks", "task" ],
|
|
||||||
[ "change_task", "tasks", "task" ],
|
|
||||||
[ "delete_task", "tasks", "task" ],
|
|
||||||
[ "view_task", "tasks", "task" ],
|
|
||||||
[ "add_role", "users", "role" ],
|
|
||||||
[ "change_role", "users", "role" ],
|
|
||||||
[ "delete_role", "users", "role" ],
|
|
||||||
[ "view_role", "users", "role" ],
|
|
||||||
[ "change_user", "users", "user" ],
|
|
||||||
[ "view_user", "users", "user" ],
|
|
||||||
[ "add_rolepoints", "userstories", "rolepoints" ],
|
|
||||||
[ "change_rolepoints", "userstories", "rolepoints" ],
|
|
||||||
[ "delete_rolepoints", "userstories", "rolepoints" ],
|
|
||||||
[ "view_rolepoints", "userstories", "rolepoints" ],
|
|
||||||
[ "add_userstory", "userstories", "userstory" ],
|
|
||||||
[ "change_userstory", "userstories", "userstory" ],
|
|
||||||
[ "delete_userstory", "userstories", "userstory" ],
|
|
||||||
[ "view_userstory", "userstories", "userstory" ],
|
|
||||||
[ "add_wikipage", "wiki", "wikipage" ],
|
|
||||||
[ "change_wikipage", "wiki", "wikipage" ],
|
|
||||||
[ "delete_wikipage", "wiki", "wikipage" ],
|
|
||||||
[ "view_wikipage", "wiki", "wikipage" ]
|
|
||||||
]),
|
|
||||||
(50, "product-ouner", "Product Owner", False, [
|
|
||||||
[ "add_issue", "issues", "issue" ],
|
|
||||||
[ "change_issue", "issues", "issue" ],
|
|
||||||
[ "delete_issue", "issues", "issue" ],
|
|
||||||
[ "view_issue", "issues", "issue" ],
|
|
||||||
[ "add_milestone", "milestones", "milestone" ],
|
|
||||||
[ "change_milestone", "milestones", "milestone" ],
|
|
||||||
[ "delete_milestone", "milestones", "milestone" ],
|
|
||||||
[ "view_milestone", "milestones", "milestone" ],
|
|
||||||
[ "add_attachment", "projects", "attachment" ],
|
|
||||||
[ "change_attachment", "projects", "attachment" ],
|
|
||||||
[ "delete_attachment", "projects", "attachment" ],
|
|
||||||
[ "view_attachment", "projects", "attachment" ],
|
|
||||||
[ "add_issuestatus", "projects", "issuestatus" ],
|
|
||||||
[ "change_issuestatus", "projects", "issuestatus" ],
|
|
||||||
[ "delete_issuestatus", "projects", "issuestatus" ],
|
|
||||||
[ "view_issuestatus", "projects", "issuestatus" ],
|
|
||||||
[ "add_issuetype", "projects", "issuetype" ],
|
|
||||||
[ "change_issuetype", "projects", "issuetype" ],
|
|
||||||
[ "delete_issuetype", "projects", "issuetype" ],
|
|
||||||
[ "view_issuetype", "projects", "issuetype" ],
|
|
||||||
[ "add_membership", "projects", "membership" ],
|
|
||||||
[ "change_membership", "projects", "membership" ],
|
|
||||||
[ "delete_membership", "projects", "membership" ],
|
|
||||||
[ "view_membership", "projects", "membership" ],
|
|
||||||
[ "add_points", "projects", "points" ],
|
|
||||||
[ "change_points", "projects", "points" ],
|
|
||||||
[ "delete_points", "projects", "points" ],
|
|
||||||
[ "view_points", "projects", "points" ],
|
|
||||||
[ "add_priority", "projects", "priority" ],
|
|
||||||
[ "change_priority", "projects", "priority" ],
|
|
||||||
[ "delete_priority", "projects", "priority" ],
|
|
||||||
[ "view_priority", "projects", "priority" ],
|
|
||||||
[ "add_project", "projects", "project" ],
|
|
||||||
[ "change_project", "projects", "project" ],
|
|
||||||
[ "delete_project", "projects", "project" ],
|
|
||||||
[ "view_project", "projects", "project" ],
|
|
||||||
[ "add_severity", "projects", "severity" ],
|
|
||||||
[ "change_severity", "projects", "severity" ],
|
|
||||||
[ "delete_severity", "projects", "severity" ],
|
|
||||||
[ "view_severity", "projects", "severity" ],
|
|
||||||
[ "add_taskstatus", "projects", "taskstatus" ],
|
|
||||||
[ "change_taskstatus", "projects", "taskstatus" ],
|
|
||||||
[ "delete_taskstatus", "projects", "taskstatus" ],
|
|
||||||
[ "view_taskstatus", "projects", "taskstatus" ],
|
|
||||||
[ "add_userstorystatus", "projects", "userstorystatus" ],
|
|
||||||
[ "change_userstorystatus", "projects", "userstorystatus" ],
|
|
||||||
[ "delete_userstorystatus", "projects", "userstorystatus" ],
|
|
||||||
[ "view_userstorystatus", "projects", "userstorystatus" ],
|
|
||||||
[ "add_task", "tasks", "task" ],
|
|
||||||
[ "change_task", "tasks", "task" ],
|
|
||||||
[ "delete_task", "tasks", "task" ],
|
|
||||||
[ "view_task", "tasks", "task" ],
|
|
||||||
[ "add_role", "users", "role" ],
|
|
||||||
[ "change_role", "users", "role" ],
|
|
||||||
[ "delete_role", "users", "role" ],
|
|
||||||
[ "view_role", "users", "role" ],
|
|
||||||
[ "change_user", "users", "user" ],
|
|
||||||
[ "view_user", "users", "user" ],
|
|
||||||
[ "add_rolepoints", "userstories", "rolepoints" ],
|
|
||||||
[ "change_rolepoints", "userstories", "rolepoints" ],
|
|
||||||
[ "delete_rolepoints", "userstories", "rolepoints" ],
|
|
||||||
[ "view_rolepoints", "userstories", "rolepoints" ],
|
|
||||||
[ "add_userstory", "userstories", "userstory" ],
|
|
||||||
[ "change_userstory", "userstories", "userstory" ],
|
|
||||||
[ "delete_userstory", "userstories", "userstory" ],
|
|
||||||
[ "view_userstory", "userstories", "userstory" ],
|
|
||||||
[ "add_wikipage", "wiki", "wikipage" ],
|
|
||||||
[ "change_wikipage", "wiki", "wikipage" ],
|
|
||||||
[ "delete_wikipage", "wiki", "wikipage" ],
|
|
||||||
[ "view_wikipage", "wiki", "wikipage" ]
|
|
||||||
]),
|
|
||||||
(60, "stakeholder", "Stakeholder", False, [
|
|
||||||
[ "add_issue", "issues", "issue" ],
|
|
||||||
[ "change_issue", "issues", "issue" ],
|
|
||||||
[ "delete_issue", "issues", "issue" ],
|
|
||||||
[ "view_issue", "issues", "issue" ],
|
|
||||||
[ "view_milestone", "milestones", "milestone" ],
|
|
||||||
[ "add_attachment", "projects", "attachment" ],
|
|
||||||
[ "change_attachment", "projects", "attachment" ],
|
|
||||||
[ "delete_attachment", "projects", "attachment" ],
|
|
||||||
[ "view_attachment", "projects", "attachment" ],
|
|
||||||
[ "view_issuestatus", "projects", "issuestatus" ],
|
|
||||||
[ "view_issuetype", "projects", "issuetype" ],
|
|
||||||
[ "view_membership", "projects", "membership" ],
|
|
||||||
[ "view_points", "projects", "points" ],
|
|
||||||
[ "view_priority", "projects", "priority" ],
|
|
||||||
[ "view_project", "projects", "project" ],
|
|
||||||
[ "view_severity", "projects", "severity" ],
|
|
||||||
[ "view_taskstatus", "projects", "taskstatus" ],
|
|
||||||
[ "view_userstorystatus", "projects", "userstorystatus" ],
|
|
||||||
[ "view_task", "tasks", "task" ],
|
|
||||||
[ "view_role", "users", "role" ],
|
|
||||||
[ "change_user", "users", "user" ],
|
|
||||||
[ "view_user", "users", "user" ],
|
|
||||||
[ "view_rolepoints", "userstories", "rolepoints" ],
|
|
||||||
[ "view_userstory", "userstories", "userstory" ],
|
|
||||||
[ "change_wikipage", "wiki", "wikipage" ],
|
|
||||||
[ "view_wikipage", "wiki", "wikipage" ]
|
|
||||||
])
|
|
||||||
)
|
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -15,7 +15,7 @@ from . import create_issue
|
||||||
|
|
||||||
|
|
||||||
class IssuesTestCase(test.TestCase):
|
class IssuesTestCase(test.TestCase):
|
||||||
fixtures = ["initial_domains.json"]
|
fixtures = ["initial_domains.json", "initial_project_templates.json"]
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.user1 = create_user(1) # Project owner
|
self.user1 = create_user(1) # Project owner
|
||||||
|
|
|
@ -30,7 +30,7 @@ from . import create_milestone
|
||||||
|
|
||||||
|
|
||||||
class MilestonesTestCase(test.TestCase):
|
class MilestonesTestCase(test.TestCase):
|
||||||
fixtures = ["initial_domains.json",]
|
fixtures = ["initial_domains.json", "initial_project_templates.json",]
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.user1 = create_user(1)
|
self.user1 = create_user(1)
|
||||||
|
|
|
@ -31,6 +31,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from picklefield.fields import PickledObjectField
|
from picklefield.fields import PickledObjectField
|
||||||
|
from django_pgjson.fields import JsonField
|
||||||
|
|
||||||
from taiga.users.models import Role
|
from taiga.users.models import Role
|
||||||
from taiga.domains.models import DomainMember
|
from taiga.domains.models import DomainMember
|
||||||
|
@ -520,6 +521,241 @@ class QuestionStatus(models.Model):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectTemplate(models.Model):
|
||||||
|
name = models.CharField(max_length=250, unique=True, null=False, blank=False,
|
||||||
|
verbose_name=_("name"))
|
||||||
|
slug = models.SlugField(max_length=250, unique=True, null=False, blank=True,
|
||||||
|
verbose_name=_("slug"))
|
||||||
|
description = models.TextField(null=False, blank=False,
|
||||||
|
verbose_name=_("description"))
|
||||||
|
created_date = models.DateTimeField(auto_now_add=True, null=False, blank=False,
|
||||||
|
verbose_name=_("created date"))
|
||||||
|
modified_date = models.DateTimeField(auto_now=True, null=False, blank=False,
|
||||||
|
verbose_name=_("modified date"))
|
||||||
|
domain = models.ForeignKey("domains.Domain", related_name="templates", null=True, blank=True,
|
||||||
|
default=None, verbose_name=_("domain"))
|
||||||
|
|
||||||
|
is_backlog_activated = models.BooleanField(default=True, null=False, blank=True,
|
||||||
|
verbose_name=_("active backlog panel"))
|
||||||
|
is_kanban_activated = models.BooleanField(default=False, null=False, blank=True,
|
||||||
|
verbose_name=_("active kanban panel"))
|
||||||
|
is_wiki_activated = models.BooleanField(default=True, null=False, blank=True,
|
||||||
|
verbose_name=_("active wiki panel"))
|
||||||
|
is_issues_activated = models.BooleanField(default=True, null=False, blank=True,
|
||||||
|
verbose_name=_("active issues panel"))
|
||||||
|
videoconferences = models.CharField(max_length=250, null=True, blank=True,
|
||||||
|
choices=choices.VIDEOCONFERENCES_CHOICES,
|
||||||
|
verbose_name=_("videoconference system"))
|
||||||
|
videoconferences_salt = models.CharField(max_length=250, null=True, blank=True,
|
||||||
|
verbose_name=_("videoconference room salt"))
|
||||||
|
|
||||||
|
default_options = JsonField(null=True, blank=True, default=None, verbose_name=_("default options"))
|
||||||
|
us_statuses = JsonField(null=True, blank=True, default=None, verbose_name=_("us statuses"))
|
||||||
|
points = JsonField(null=True, blank=True, default=None, verbose_name=_("us points"))
|
||||||
|
task_statuses = JsonField(null=True, blank=True, default=None, verbose_name=_("task statuses"))
|
||||||
|
issue_statuses = JsonField(null=True, blank=True, default=None, verbose_name=_("issue statuses"))
|
||||||
|
issue_types = JsonField(null=True, blank=True, default=None, verbose_name=_("issue types"))
|
||||||
|
priorities = JsonField(null=True, blank=True, default=None, verbose_name=_("issue types"))
|
||||||
|
severities = JsonField(null=True, blank=True, default=None, verbose_name=_("issue types"))
|
||||||
|
roles = JsonField(null=True, blank=True, default=None, verbose_name=_("roles"))
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = "project template"
|
||||||
|
verbose_name_plural = "project templates"
|
||||||
|
ordering = ["name"]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<Project Template {0}>".format(self.slug)
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
def load_data_from_project(self, project):
|
||||||
|
self.is_backlog_activated = project.is_backlog_activated
|
||||||
|
self.is_kanban_activated = project.is_kanban_activated
|
||||||
|
self.is_wiki_activated = project.is_wiki_activated
|
||||||
|
self.is_issues_activated = project.is_issues_activated
|
||||||
|
self.videoconferences = project.videoconferences
|
||||||
|
self.videoconferences_salt = project.videoconferences_salt
|
||||||
|
|
||||||
|
self.default_options = {
|
||||||
|
"points": project.default_points.name,
|
||||||
|
"us_status": project.default_us_status.name,
|
||||||
|
"task_status": project.default_task_status.name,
|
||||||
|
"issue_status": project.default_issue_status.name,
|
||||||
|
"issue_type": project.default_issue_type.name,
|
||||||
|
"priority": project.default_priority.name,
|
||||||
|
"severity": project.default_severity.name
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
self.us_statuses = []
|
||||||
|
for us_status in project.us_statuses.all():
|
||||||
|
self.us_statuses.append({
|
||||||
|
"name": us_status.name,
|
||||||
|
"is_closed": us_status.is_closed,
|
||||||
|
"color": us_status.color,
|
||||||
|
"wip_limit": us_status.wip_limit,
|
||||||
|
"order": us_status.order,
|
||||||
|
})
|
||||||
|
|
||||||
|
self.points = []
|
||||||
|
for us_point in project.points.all():
|
||||||
|
self.points.append({
|
||||||
|
"name": us_point.name,
|
||||||
|
"value": us_point.value,
|
||||||
|
"order": us_point.order,
|
||||||
|
})
|
||||||
|
|
||||||
|
self.task_statuses = []
|
||||||
|
for task_status in project.task_statuses.all():
|
||||||
|
self.task_statuses.append({
|
||||||
|
"name": task_status.name,
|
||||||
|
"is_closed": task_status.is_closed,
|
||||||
|
"color": task_status.color,
|
||||||
|
"order": task_status.order,
|
||||||
|
})
|
||||||
|
|
||||||
|
self.issue_statuses = []
|
||||||
|
for issue_status in project.issue_statuses.all():
|
||||||
|
self.issue_statuses.append({
|
||||||
|
"name": issue_status.name,
|
||||||
|
"is_closed": issue_status.is_closed,
|
||||||
|
"color": issue_status.color,
|
||||||
|
"order": issue_status.order,
|
||||||
|
})
|
||||||
|
|
||||||
|
self.issue_types = []
|
||||||
|
for issue_type in project.issue_types.all():
|
||||||
|
self.issue_types.append({
|
||||||
|
"name": issue_type.name,
|
||||||
|
"color": issue_type.color,
|
||||||
|
"order": issue_type.order,
|
||||||
|
})
|
||||||
|
|
||||||
|
self.priorities = []
|
||||||
|
for priority in project.priorities.all():
|
||||||
|
self.priorities.append({
|
||||||
|
"name": priority.name,
|
||||||
|
"color": priority.color,
|
||||||
|
"order": priority.order,
|
||||||
|
})
|
||||||
|
|
||||||
|
self.severities = []
|
||||||
|
for severity in project.severities.all():
|
||||||
|
self.severities.append({
|
||||||
|
"name": severity.name,
|
||||||
|
"color": severity.color,
|
||||||
|
"order": severity.order,
|
||||||
|
})
|
||||||
|
|
||||||
|
self.roles = []
|
||||||
|
for role in project.roles.all():
|
||||||
|
permissions = [p.codename for p in role.permissions.all()]
|
||||||
|
self.roles.append({
|
||||||
|
"name": role.name,
|
||||||
|
"slug": role.slug,
|
||||||
|
"permissions": permissions,
|
||||||
|
"order": role.order,
|
||||||
|
"computable": role.computable
|
||||||
|
})
|
||||||
|
|
||||||
|
def apply_to_project(self, project):
|
||||||
|
if project.id is None:
|
||||||
|
raise "Project need an id (must be a saved project)"
|
||||||
|
|
||||||
|
project.is_backlog_activated = self.is_backlog_activated
|
||||||
|
project.is_kanban_activated = self.is_kanban_activated
|
||||||
|
project.is_wiki_activated = self.is_wiki_activated
|
||||||
|
project.is_issues_activated = self.is_issues_activated
|
||||||
|
project.videoconferences = self.videoconferences
|
||||||
|
project.videoconferences_salt = self.videoconferences_salt
|
||||||
|
|
||||||
|
for us_status in self.us_statuses:
|
||||||
|
UserStoryStatus.objects.create(
|
||||||
|
name=us_status["name"],
|
||||||
|
is_closed=us_status["is_closed"],
|
||||||
|
color=us_status["color"],
|
||||||
|
wip_limit=us_status["wip_limit"],
|
||||||
|
order=us_status["order"],
|
||||||
|
project=project
|
||||||
|
)
|
||||||
|
|
||||||
|
for point in self.points:
|
||||||
|
Points.objects.create(
|
||||||
|
name=point["name"],
|
||||||
|
value=point["value"],
|
||||||
|
order=point["order"],
|
||||||
|
project=project
|
||||||
|
)
|
||||||
|
|
||||||
|
for task_status in self.task_statuses:
|
||||||
|
TaskStatus.objects.create(
|
||||||
|
name=task_status["name"],
|
||||||
|
is_closed=task_status["is_closed"],
|
||||||
|
color=task_status["color"],
|
||||||
|
order=task_status["order"],
|
||||||
|
project=project
|
||||||
|
)
|
||||||
|
|
||||||
|
for issue_status in self.issue_statuses:
|
||||||
|
IssueStatus.objects.create(
|
||||||
|
name=issue_status["name"],
|
||||||
|
is_closed=issue_status["is_closed"],
|
||||||
|
color=issue_status["color"],
|
||||||
|
order=issue_status["order"],
|
||||||
|
project=project
|
||||||
|
)
|
||||||
|
|
||||||
|
for issue_type in self.issue_types:
|
||||||
|
IssueType.objects.create(
|
||||||
|
name=issue_type["name"],
|
||||||
|
color=issue_type["color"],
|
||||||
|
order=issue_type["order"],
|
||||||
|
project=project
|
||||||
|
)
|
||||||
|
|
||||||
|
for priority in self.priorities:
|
||||||
|
Priority.objects.create(
|
||||||
|
name=priority["name"],
|
||||||
|
color=priority["color"],
|
||||||
|
order=priority["order"],
|
||||||
|
project=project
|
||||||
|
)
|
||||||
|
|
||||||
|
for severity in self.severities:
|
||||||
|
Severity.objects.create(
|
||||||
|
name=severity["name"],
|
||||||
|
color=severity["color"],
|
||||||
|
order=severity["order"],
|
||||||
|
project=project
|
||||||
|
)
|
||||||
|
|
||||||
|
for role in self.roles:
|
||||||
|
newRoleInstance = Role.objects.create(
|
||||||
|
name=role["name"],
|
||||||
|
slug=role["slug"],
|
||||||
|
order=role["order"],
|
||||||
|
computable=role["computable"],
|
||||||
|
project=project
|
||||||
|
)
|
||||||
|
permissions = [Permission.objects.get(codename=codename) for codename in role["permissions"]]
|
||||||
|
for permission in permissions:
|
||||||
|
newRoleInstance.permissions.add(permission)
|
||||||
|
|
||||||
|
project.default_points = Points.objects.get(name=self.default_options["points"], project=project)
|
||||||
|
project.default_us_status = UserStoryStatus.objects.get(name=self.default_options["us_status"], project=project)
|
||||||
|
project.default_task_status = TaskStatus.objects.get(name=self.default_options["task_status"], project=project)
|
||||||
|
project.default_issue_status = IssueStatus.objects.get(name=self.default_options["issue_status"], project=project)
|
||||||
|
project.default_issue_type = IssueType.objects.get(name=self.default_options["issue_type"], project=project)
|
||||||
|
project.default_priority = Priority.objects.get(name=self.default_options["priority"], project=project)
|
||||||
|
project.default_severity = Severity.objects.get(name=self.default_options["severity"], project=project)
|
||||||
|
|
||||||
|
return project
|
||||||
|
|
||||||
# Reversion registration (usufull for base.notification and for meke a historical)
|
# Reversion registration (usufull for base.notification and for meke a historical)
|
||||||
reversion.register(Project)
|
reversion.register(Project)
|
||||||
reversion.register(Attachment)
|
reversion.register(Attachment)
|
||||||
|
@ -570,67 +806,7 @@ def project_post_save(sender, instance, created, **kwargs):
|
||||||
if not created:
|
if not created:
|
||||||
return
|
return
|
||||||
|
|
||||||
# USs
|
template_slug = getattr(instance, "template", settings.DEFAULT_PROJECT_TEMPLATE)
|
||||||
for order, name, value, is_default in choices.POINTS_CHOICES:
|
template = ProjectTemplate.objects.get(slug=template_slug, domain__isnull=True)
|
||||||
obj = Points.objects.create(project=instance, name=name, order=order, value=value)
|
template.apply_to_project(instance)
|
||||||
if is_default:
|
|
||||||
instance.default_points = obj
|
|
||||||
|
|
||||||
for order, name, is_closed, is_default, color in choices.US_STATUSES:
|
|
||||||
obj = UserStoryStatus.objects.create(name=name, order=order, color=color,
|
|
||||||
is_closed=is_closed, project=instance)
|
|
||||||
if is_default:
|
|
||||||
instance.default_us_status = obj
|
|
||||||
|
|
||||||
# Tasks
|
|
||||||
for order, name, is_closed, is_default, color in choices.TASK_STATUSES:
|
|
||||||
obj = TaskStatus.objects.create(name=name, order=order, color=color,
|
|
||||||
is_closed=is_closed, project=instance)
|
|
||||||
if is_default:
|
|
||||||
instance.default_task_status = obj
|
|
||||||
|
|
||||||
# Issues
|
|
||||||
for order, name, color, is_default in choices.PRIORITY_CHOICES:
|
|
||||||
obj = Priority.objects.create(project=instance, name=name, order=order, color=color)
|
|
||||||
if is_default:
|
|
||||||
instance.default_priority = obj
|
|
||||||
|
|
||||||
for order, name, color, is_default in choices.SEVERITY_CHOICES:
|
|
||||||
obj = Severity.objects.create(project=instance, name=name, order=order, color=color)
|
|
||||||
if is_default:
|
|
||||||
instance.default_severity = obj
|
|
||||||
|
|
||||||
for order, name, is_closed, color, is_default in choices.ISSUE_STATUSES:
|
|
||||||
obj = IssueStatus.objects.create(name=name, order=order,
|
|
||||||
is_closed=is_closed, project=instance, color=color)
|
|
||||||
if is_default:
|
|
||||||
instance.default_issue_status = obj
|
|
||||||
|
|
||||||
for order, name, color, is_default in choices.ISSUE_TYPES:
|
|
||||||
obj = IssueType.objects.create(project=instance, name=name, order=order, color=color)
|
|
||||||
if is_default:
|
|
||||||
instance.default_issue_type = obj
|
|
||||||
|
|
||||||
# Questions
|
|
||||||
for order, name, is_closed, color, is_default in choices.QUESTION_STATUS:
|
|
||||||
obj = QuestionStatus.objects.create(name=name, order=order,
|
|
||||||
is_closed=is_closed, project=instance, color=color)
|
|
||||||
if is_default:
|
|
||||||
instance.default_question_status = obj
|
|
||||||
|
|
||||||
# Permissions
|
|
||||||
for order, slug, name, computable, permissions in choices.ROLES:
|
|
||||||
obj = Role.objects.create(slug=slug, name=name, order=order, computable=computable, project=instance)
|
|
||||||
for permission in permissions:
|
|
||||||
try:
|
|
||||||
perm = Permission.objects.get(codename=permission[0], content_type__app_label=permission[1], content_type__model=permission[2])
|
|
||||||
obj.permissions.add(perm)
|
|
||||||
except Permission.DoesNotExist:
|
|
||||||
pass
|
|
||||||
|
|
||||||
instance.save()
|
instance.save()
|
||||||
|
|
||||||
from taiga.projects.template_manager import ProjectTemplateManager
|
|
||||||
if hasattr(instance, "template"):
|
|
||||||
template_manager = ProjectTemplateManager()
|
|
||||||
template_manager.apply(instance.template, instance)
|
|
||||||
|
|
|
@ -168,3 +168,12 @@ class QuestionStatusPermission(BasePermission):
|
||||||
delete_permission = "delete_questionstatus"
|
delete_permission = "delete_questionstatus"
|
||||||
safe_methods = ["HEAD", "OPTIONS"]
|
safe_methods = ["HEAD", "OPTIONS"]
|
||||||
path_to_project = ["project"]
|
path_to_project = ["project"]
|
||||||
|
|
||||||
|
class ProjectTemplatePermission(BasePermission):
|
||||||
|
def has_permission(self, request, view):
|
||||||
|
domain = get_active_domain()
|
||||||
|
return domain.user_is_owner(request.user)
|
||||||
|
|
||||||
|
def has_object_permission(self, request, view, obj):
|
||||||
|
domain = get_active_domain()
|
||||||
|
return domain.user_is_owner(request.user)
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
from os import path
|
from os import path
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from taiga.base.serializers import PickleField
|
from taiga.base.serializers import PickleField, JsonField, AutoDomainField
|
||||||
from taiga.users.models import Role
|
from taiga.users.models import Role
|
||||||
|
|
||||||
from . import models
|
from . import models
|
||||||
|
@ -182,3 +182,20 @@ class RoleSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Role
|
model = Role
|
||||||
fields = ('id', 'name', 'permissions', 'computable', 'project', 'order')
|
fields = ('id', 'name', 'permissions', 'computable', 'project', 'order')
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectTemplateSerializer(serializers.ModelSerializer):
|
||||||
|
domain = AutoDomainField()
|
||||||
|
|
||||||
|
default_options = JsonField()
|
||||||
|
us_statuses = JsonField()
|
||||||
|
points = JsonField()
|
||||||
|
task_statuses = JsonField()
|
||||||
|
issue_statuses = JsonField()
|
||||||
|
issue_types = JsonField()
|
||||||
|
priorities = JsonField()
|
||||||
|
severities = JsonField()
|
||||||
|
roles = JsonField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = models.ProjectTemplate
|
||||||
|
|
|
@ -34,7 +34,7 @@ from . import create_task
|
||||||
|
|
||||||
|
|
||||||
class TasksTestCase(test.TestCase):
|
class TasksTestCase(test.TestCase):
|
||||||
fixtures = ["initial_domains.json"]
|
fixtures = ["initial_domains.json", "initial_project_templates.json"]
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.user1 = create_user(1) # Project owner
|
self.user1 = create_user(1) # Project owner
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
# Copyright (C) 2014 Andrey Antukh <niwi@niwi.be>
|
|
||||||
# Copyright (C) 2014 Jesús Espino <jespinog@gmail.com>
|
|
||||||
# Copyright (C) 2014 David Barragán <bameda@dbarragan.com>
|
|
||||||
# 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 taiga.projects.models import UserStoryStatus
|
|
||||||
|
|
||||||
|
|
||||||
class ProjectTemplateManager(object):
|
|
||||||
def apply(self, template, project):
|
|
||||||
if not hasattr(self, "template"):
|
|
||||||
return False
|
|
||||||
template = getattr(self, "template")
|
|
||||||
template(project)
|
|
||||||
|
|
||||||
def legal(self, project):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def pure_kanban(self, project):
|
|
||||||
project.is_backlog_activated = False
|
|
||||||
project.is_kanban_activated = True
|
|
||||||
project.is_wiki_activated = False
|
|
||||||
project.is_issues_activated = False
|
|
||||||
project.save()
|
|
||||||
|
|
||||||
us_status = project.us_statuses.get(order=1)
|
|
||||||
us_status.name = "To do"
|
|
||||||
us_status.color = "#999999"
|
|
||||||
us_status.save()
|
|
||||||
|
|
||||||
us_status = project.us_statuses.get(order=2)
|
|
||||||
us_status.name = "Doing"
|
|
||||||
us_status.color = "#ff9900"
|
|
||||||
us_status.is_closed = False
|
|
||||||
us_status.save()
|
|
||||||
|
|
||||||
us_status = UserStoryStatus()
|
|
||||||
us_status.order = 3
|
|
||||||
us_status.name = "Done"
|
|
||||||
us_status.color = "#ffcc00"
|
|
||||||
us_status.project = project
|
|
||||||
us_status.is_closed = True
|
|
||||||
us_status.save()
|
|
|
@ -24,14 +24,15 @@ from django.core import mail
|
||||||
from django.db.models import get_model
|
from django.db.models import get_model
|
||||||
|
|
||||||
from taiga.users.tests import create_user
|
from taiga.users.tests import create_user
|
||||||
from taiga.projects.models import Project, Membership
|
from taiga.projects.models import Project, Membership, ProjectTemplate
|
||||||
|
from taiga.domains.models import Domain
|
||||||
|
|
||||||
from . import create_project
|
from . import create_project
|
||||||
from . import add_membership
|
from . import add_membership
|
||||||
|
|
||||||
|
|
||||||
class ProfileTestCase(test.TestCase):
|
class ProfileTestCase(test.TestCase):
|
||||||
fixtures = ["initial_domains.json"]
|
fixtures = ["initial_domains.json", "initial_project_templates.json"]
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.user1 = create_user(1, is_superuser=True)
|
self.user1 = create_user(1, is_superuser=True)
|
||||||
|
@ -182,7 +183,7 @@ class ProfileTestCase(test.TestCase):
|
||||||
|
|
||||||
|
|
||||||
class ProjectsTestCase(test.TestCase):
|
class ProjectsTestCase(test.TestCase):
|
||||||
fixtures = ["initial_role.json", "initial_domains.json"]
|
fixtures = ["initial_domains.json", "initial_project_templates.json"]
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.user1 = create_user(1)
|
self.user1 = create_user(1)
|
||||||
|
@ -462,3 +463,264 @@ class ProjectsTestCase(test.TestCase):
|
||||||
self.assertEqual(response.status_code, 404)
|
self.assertEqual(response.status_code, 404)
|
||||||
self.assertEqual(Project.objects.all().count(), 4)
|
self.assertEqual(Project.objects.all().count(), 4)
|
||||||
self.client.logout()
|
self.client.logout()
|
||||||
|
|
||||||
|
class ProjectTemplatesTestCase(test.TestCase):
|
||||||
|
fixtures = ["initial_domains.json", "initial_project_templates.json"]
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.user1 = create_user(1)
|
||||||
|
self.user2 = create_user(2)
|
||||||
|
self.domain = Domain.objects.all()[0]
|
||||||
|
self.domain.owner = self.user1
|
||||||
|
|
||||||
|
def test_list_project_templates_by_anon(self):
|
||||||
|
response = self.client.get(reverse("project-templates-list"))
|
||||||
|
self.assertEqual(response.status_code, 401)
|
||||||
|
|
||||||
|
def test_list_project_templates_by_domain_owner(self):
|
||||||
|
response = self.client.login(username=self.user1.username,
|
||||||
|
password=self.user1.username)
|
||||||
|
self.assertTrue(response)
|
||||||
|
response = self.client.get(reverse("project-templates-list"))
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
projects_list = response.data
|
||||||
|
self.assertEqual(len(projects_list), 2)
|
||||||
|
self.client.logout()
|
||||||
|
|
||||||
|
def test_list_projects_by_not_domain_owner(self):
|
||||||
|
response = self.client.login(username=self.user2.username,
|
||||||
|
password=self.user2.username)
|
||||||
|
self.assertTrue(response)
|
||||||
|
response = self.client.get(reverse("project-templates-list"))
|
||||||
|
self.assertEqual(response.status_code, 403)
|
||||||
|
|
||||||
|
def test_view_project_template_by_anon(self):
|
||||||
|
response = self.client.get(reverse("project-templates-detail", args=(1,)))
|
||||||
|
self.assertEqual(response.status_code, 401)
|
||||||
|
|
||||||
|
def test_view_project_template_by_domain_owner(self):
|
||||||
|
response = self.client.login(username=self.user1.username,
|
||||||
|
password=self.user1.username)
|
||||||
|
self.assertTrue(response)
|
||||||
|
response = self.client.get(reverse("project-templates-detail", args=(1,)))
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
response = self.client.get(reverse("project-templates-detail", args=(2,)))
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.client.logout()
|
||||||
|
|
||||||
|
def test_view_project_template_by_not_domain_owner(self):
|
||||||
|
response = self.client.login(username=self.user2.username,
|
||||||
|
password=self.user2.username)
|
||||||
|
self.assertTrue(response)
|
||||||
|
response = self.client.get(reverse("project-templates-detail", args=(1,)))
|
||||||
|
self.assertEqual(response.status_code, 403)
|
||||||
|
response = self.client.get(reverse("project-templates-detail", args=(2,)))
|
||||||
|
self.assertEqual(response.status_code, 403)
|
||||||
|
self.client.logout()
|
||||||
|
|
||||||
|
def test_create_project_template_by_anon(self):
|
||||||
|
data = {
|
||||||
|
"name": "Test Project Template",
|
||||||
|
"slug": "test-project-template",
|
||||||
|
"description": "A new Test Project Template",
|
||||||
|
}
|
||||||
|
|
||||||
|
self.assertEqual(ProjectTemplate.objects.all().count(), 2)
|
||||||
|
response = self.client.post(
|
||||||
|
reverse("project-templates-list"),
|
||||||
|
json.dumps(data),
|
||||||
|
content_type="application/json")
|
||||||
|
self.assertEqual(response.status_code, 401)
|
||||||
|
self.assertEqual(ProjectTemplate.objects.all().count(), 2)
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"name": "Test Project Template 2",
|
||||||
|
"slug": "test-project-template-2",
|
||||||
|
"description": "A new Test Project Template",
|
||||||
|
"domain": 100,
|
||||||
|
}
|
||||||
|
|
||||||
|
response = self.client.post(
|
||||||
|
reverse("project-templates-list"),
|
||||||
|
json.dumps(data),
|
||||||
|
content_type="application/json")
|
||||||
|
self.assertEqual(response.status_code, 401)
|
||||||
|
self.assertEqual(ProjectTemplate.objects.all().count(), 2)
|
||||||
|
|
||||||
|
def test_create_project_template_by_domain_owner(self):
|
||||||
|
data = {
|
||||||
|
"name": "Test Project Template",
|
||||||
|
"slug": "test-project-template",
|
||||||
|
"description": "A new Test Project Template",
|
||||||
|
}
|
||||||
|
|
||||||
|
self.assertEqual(ProjectTemplate.objects.all().count(), 2)
|
||||||
|
response = self.client.login(username=self.user1.username,
|
||||||
|
password=self.user1.username)
|
||||||
|
self.assertTrue(response)
|
||||||
|
response = self.client.post(reverse("project-templates-list"), json.dumps(data),
|
||||||
|
content_type="application/json")
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 201)
|
||||||
|
self.assertEqual(ProjectTemplate.objects.all().count(), 3)
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"name": "Test Project Template 2",
|
||||||
|
"slug": "test-project-template-2",
|
||||||
|
"description": "A new Test Project Template",
|
||||||
|
"domain": 100,
|
||||||
|
}
|
||||||
|
|
||||||
|
response = self.client.login(username=self.user1.username,
|
||||||
|
password=self.user1.username)
|
||||||
|
self.assertTrue(response)
|
||||||
|
response = self.client.post(reverse("project-templates-list"), json.dumps(data),
|
||||||
|
content_type="application/json")
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 201)
|
||||||
|
self.assertEqual(ProjectTemplate.objects.all().count(), 4)
|
||||||
|
template = ProjectTemplate.objects.order_by('-created_date')[0]
|
||||||
|
self.assertEqual(template.domain.id, 1)
|
||||||
|
|
||||||
|
self.client.logout()
|
||||||
|
|
||||||
|
ProjectTemplate.objects.order_by("created_date")[0:2].delete()
|
||||||
|
|
||||||
|
def test_create_project_template_by_not_domain_owner(self):
|
||||||
|
data = {
|
||||||
|
"name": "Test Project Template",
|
||||||
|
"slug": "test-project-template",
|
||||||
|
"description": "A new Test Project Template",
|
||||||
|
}
|
||||||
|
|
||||||
|
self.assertEqual(ProjectTemplate.objects.all().count(), 2)
|
||||||
|
response = self.client.login(username=self.user1.username,
|
||||||
|
password=self.user1.username)
|
||||||
|
self.assertTrue(response)
|
||||||
|
response = self.client.post(
|
||||||
|
reverse("project-templates-list"),
|
||||||
|
json.dumps(data),
|
||||||
|
content_type="application/json")
|
||||||
|
self.assertEqual(response.status_code, 401)
|
||||||
|
self.assertEqual(ProjectTemplate.objects.all().count(), 2)
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"name": "Test Project Template 2",
|
||||||
|
"slug": "test-project-template-2",
|
||||||
|
"description": "A new Test Project Template",
|
||||||
|
"domain": 100
|
||||||
|
}
|
||||||
|
|
||||||
|
response = self.client.post(
|
||||||
|
reverse("project-templates-list"),
|
||||||
|
json.dumps(data),
|
||||||
|
content_type="application/json")
|
||||||
|
self.assertEqual(response.status_code, 401)
|
||||||
|
self.assertEqual(ProjectTemplate.objects.all().count(), 2)
|
||||||
|
self.client.logout()
|
||||||
|
|
||||||
|
# def test_edit_project_by_anon(self):
|
||||||
|
# data = {
|
||||||
|
# "description": "Edited project description",
|
||||||
|
# }
|
||||||
|
|
||||||
|
# self.assertEqual(Project.objects.all().count(), 4)
|
||||||
|
# self.assertNotEqual(data["description"], self.project1.description)
|
||||||
|
# response = self.client.patch(
|
||||||
|
# reverse("projects-detail", args=(self.project1.id,)),
|
||||||
|
# json.dumps(data),
|
||||||
|
# content_type="application/json")
|
||||||
|
# self.assertEqual(response.status_code, 401)
|
||||||
|
# self.assertEqual(Project.objects.all().count(), 4)
|
||||||
|
|
||||||
|
# def test_edit_project_by_owner(self):
|
||||||
|
# data = {
|
||||||
|
# "description": "Modified project description",
|
||||||
|
# }
|
||||||
|
|
||||||
|
# self.assertEqual(Project.objects.all().count(), 4)
|
||||||
|
# self.assertNotEqual(data["description"], self.project1.description)
|
||||||
|
# response = self.client.login(username=self.user1.username,
|
||||||
|
# password=self.user1.username)
|
||||||
|
# self.assertTrue(response)
|
||||||
|
# response = self.client.patch(
|
||||||
|
# reverse("projects-detail", args=(self.project1.id,)),
|
||||||
|
# json.dumps(data),
|
||||||
|
# content_type="application/json")
|
||||||
|
# self.assertEqual(response.status_code, 200)
|
||||||
|
# self.assertEqual(data["description"], response.data["description"])
|
||||||
|
# self.assertEqual(Project.objects.all().count(), 4)
|
||||||
|
# self.client.logout()
|
||||||
|
|
||||||
|
# def test_edit_project_by_membership(self):
|
||||||
|
# data = {
|
||||||
|
# "description": "Edited project description",
|
||||||
|
# }
|
||||||
|
|
||||||
|
# self.assertEqual(Project.objects.all().count(), 4)
|
||||||
|
# self.assertNotEqual(data["description"], self.project1.description)
|
||||||
|
# response = self.client.login(username=self.user3.username,
|
||||||
|
# password=self.user3.username)
|
||||||
|
# self.assertTrue(response)
|
||||||
|
# response = self.client.patch(
|
||||||
|
# reverse("projects-detail", args=(self.project1.id,)),
|
||||||
|
# json.dumps(data),
|
||||||
|
# content_type="application/json")
|
||||||
|
# self.assertEqual(response.status_code, 200)
|
||||||
|
# self.assertEqual(data["description"], response.data["description"])
|
||||||
|
# self.assertEqual(Project.objects.all().count(), 4)
|
||||||
|
# self.client.logout()
|
||||||
|
|
||||||
|
# def test_edit_project_by_not_membership(self):
|
||||||
|
# data = {
|
||||||
|
# "description": "Edited project description",
|
||||||
|
# }
|
||||||
|
|
||||||
|
# self.assertEqual(Project.objects.all().count(), 4)
|
||||||
|
# self.assertNotEqual(data["description"], self.project1.description)
|
||||||
|
# response = self.client.login(username=self.user2.username,
|
||||||
|
# password=self.user2.username)
|
||||||
|
# self.assertTrue(response)
|
||||||
|
# response = self.client.patch(
|
||||||
|
# reverse("projects-detail", args=(self.project1.id,)),
|
||||||
|
# json.dumps(data),
|
||||||
|
# content_type="application/json")
|
||||||
|
# self.assertEqual(response.status_code, 404)
|
||||||
|
# self.assertEqual(Project.objects.all().count(), 4)
|
||||||
|
# self.client.logout()
|
||||||
|
|
||||||
|
# def test_delete_project_by_anon(self):
|
||||||
|
# self.assertEqual(Project.objects.all().count(), 4)
|
||||||
|
# response = self.client.delete(reverse("projects-detail", args=(self.project1.id,)))
|
||||||
|
# self.assertEqual(response.status_code, 401)
|
||||||
|
# self.assertEqual(Project.objects.all().count(), 4)
|
||||||
|
|
||||||
|
# def test_delete_project_by_owner(self):
|
||||||
|
# self.assertEqual(Project.objects.all().count(), 4)
|
||||||
|
# response = self.client.login(username=self.user1.username,
|
||||||
|
# password=self.user1.username)
|
||||||
|
# self.assertTrue(response)
|
||||||
|
# response = self.client.delete(reverse("projects-detail", args=(self.project1.id,)))
|
||||||
|
# self.assertEqual(response.status_code, 204)
|
||||||
|
# self.assertEqual(Project.objects.all().count(), 3)
|
||||||
|
# self.client.logout()
|
||||||
|
|
||||||
|
# def test_delete_project_by_membership(self):
|
||||||
|
# self.assertEqual(Project.objects.all().count(), 4)
|
||||||
|
# response = self.client.login(username=self.user3.username,
|
||||||
|
# password=self.user3.username)
|
||||||
|
# self.assertTrue(response)
|
||||||
|
# response = self.client.delete(reverse("projects-detail", args=(self.project1.id,)))
|
||||||
|
# self.assertEqual(response.status_code, 403)
|
||||||
|
# self.assertEqual(Project.objects.all().count(), 4)
|
||||||
|
# self.client.logout()
|
||||||
|
|
||||||
|
# def test_delete_project_by_not_membership(self):
|
||||||
|
# self.assertEqual(Project.objects.all().count(), 4)
|
||||||
|
# response = self.client.login(username=self.user1.username,
|
||||||
|
# password=self.user1.username)
|
||||||
|
# self.assertTrue(response)
|
||||||
|
# response = self.client.delete(reverse("projects-detail", args=(self.project3.id,)))
|
||||||
|
# self.assertEqual(response.status_code, 404)
|
||||||
|
# self.assertEqual(Project.objects.all().count(), 4)
|
||||||
|
# self.client.logout()
|
||||||
|
|
|
@ -32,7 +32,7 @@ from . import create_project
|
||||||
from . import add_membership
|
from . import add_membership
|
||||||
|
|
||||||
class AllProjectEventsNotificationsTestCase(test.TestCase):
|
class AllProjectEventsNotificationsTestCase(test.TestCase):
|
||||||
fixtures = ["initial_domains.json"]
|
fixtures = ["initial_domains.json", "initial_project_templates.json"]
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.user1 = create_user(1)
|
self.user1 = create_user(1)
|
||||||
|
@ -82,7 +82,7 @@ class AllProjectEventsNotificationsTestCase(test.TestCase):
|
||||||
self.user1.save()
|
self.user1.save()
|
||||||
|
|
||||||
class OnlyAssigendNotificationsTestCase(test.TestCase):
|
class OnlyAssigendNotificationsTestCase(test.TestCase):
|
||||||
fixtures = ["initial_domains.json"]
|
fixtures = ["initial_domains.json", "initial_project_templates.json"]
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.user1 = create_user(1)
|
self.user1 = create_user(1)
|
||||||
|
@ -153,7 +153,7 @@ class OnlyAssigendNotificationsTestCase(test.TestCase):
|
||||||
self.user1.save()
|
self.user1.save()
|
||||||
|
|
||||||
class OnlyOwnerNotificationsTestCase(test.TestCase):
|
class OnlyOwnerNotificationsTestCase(test.TestCase):
|
||||||
fixtures = ["initial_domains.json"]
|
fixtures = ["initial_domains.json", "initial_project_templates.json"]
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.user1 = create_user(1)
|
self.user1 = create_user(1)
|
||||||
|
|
|
@ -33,7 +33,7 @@ import reversion
|
||||||
|
|
||||||
|
|
||||||
class UserStoriesTestCase(test.TestCase):
|
class UserStoriesTestCase(test.TestCase):
|
||||||
fixtures = ["initial_domains.json"]
|
fixtures = ["initial_domains.json", "initial_project_templates.json"]
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.user1 = create_user(1) # Project owner
|
self.user1 = create_user(1) # Project owner
|
||||||
|
|
|
@ -26,7 +26,7 @@ from . import create_userstory
|
||||||
|
|
||||||
|
|
||||||
class UserStoriesServiceTestCase(test.TestCase):
|
class UserStoriesServiceTestCase(test.TestCase):
|
||||||
fixtures = ["initial_domains.json"]
|
fixtures = ["initial_domains.json", "initial_project_templates.json"]
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.user1 = create_user(1) # Project owner
|
self.user1 = create_user(1) # Project owner
|
||||||
|
|
|
@ -30,7 +30,7 @@ from . import create_wiki_page
|
||||||
|
|
||||||
|
|
||||||
class WikiPagesTestCase(test.TestCase):
|
class WikiPagesTestCase(test.TestCase):
|
||||||
fixtures = ["initial_domains.json"]
|
fixtures = ["initial_domains.json", "initial_project_templates.json"]
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.user1 = create_user(1)
|
self.user1 = create_user(1)
|
||||||
|
|
|
@ -64,9 +64,11 @@ from taiga.projects.api import IssueStatusViewSet
|
||||||
from taiga.projects.api import IssueTypeViewSet
|
from taiga.projects.api import IssueTypeViewSet
|
||||||
from taiga.projects.api import PriorityViewSet
|
from taiga.projects.api import PriorityViewSet
|
||||||
from taiga.projects.api import SeverityViewSet
|
from taiga.projects.api import SeverityViewSet
|
||||||
|
from taiga.projects.api import ProjectTemplateViewSet
|
||||||
|
|
||||||
router.register(r"roles", RolesViewSet, base_name="roles")
|
router.register(r"roles", RolesViewSet, base_name="roles")
|
||||||
router.register(r"projects", ProjectViewSet, base_name="projects")
|
router.register(r"projects", ProjectViewSet, base_name="projects")
|
||||||
|
router.register(r"project-templates", ProjectTemplateViewSet, base_name="project-templates")
|
||||||
router.register(r"memberships", MembershipViewSet, base_name="memberships")
|
router.register(r"memberships", MembershipViewSet, base_name="memberships")
|
||||||
router.register(r"invitations", InvitationViewSet, base_name="invitations")
|
router.register(r"invitations", InvitationViewSet, base_name="invitations")
|
||||||
router.register(r"userstory-statuses", UserStoryStatusViewSet, base_name="userstory-statuses")
|
router.register(r"userstory-statuses", UserStoryStatusViewSet, base_name="userstory-statuses")
|
||||||
|
|
Loading…
Reference in New Issue