diff --git a/settings/common.py b/settings/common.py index ee33a4ba..ba0d1254 100644 --- a/settings/common.py +++ b/settings/common.py @@ -257,6 +257,7 @@ INSTALLED_APPS = [ "django.contrib.messages", "django.contrib.admin", "django.contrib.staticfiles", + "django.contrib.sitemaps", "taiga.base", "taiga.base.api", @@ -449,9 +450,16 @@ BITBUCKET_VALID_ORIGIN_IPS = ["131.103.20.165", "131.103.20.166"] GITLAB_VALID_ORIGIN_IPS = [] EXPORTS_TTL = 60 * 60 * 24 # 24 hours + CELERY_ENABLED = False WEBHOOKS_ENABLED = False + +# If is True /front/sitemap.xml show a valid sitemap of taiga-front client +FRONT_SITEMAP_ENABLED = False +FRONT_SITEMAP_CACHE_TIMEOUT = 24*60*60 # In second + + from .sr import * diff --git a/settings/local.py.example b/settings/local.py.example index 2bc48b45..a74baa27 100644 --- a/settings/local.py.example +++ b/settings/local.py.example @@ -62,3 +62,8 @@ DATABASES = { #GITHUB_API_URL = "https://api.github.com/" #GITHUB_API_CLIENT_ID = "yourgithubclientid" #GITHUB_API_CLIENT_SECRET = "yourgithubclientsecret" + +# SITEMAP +# If is True /front/sitemap.xml show a valid sitemap of taiga-front client +#FRONT_SITEMAP_ENABLED = False +#FRONT_SITEMAP_CACHE_TIMEOUT = 24*60*60 # In second diff --git a/taiga/front/__init__.py b/taiga/front/__init__.py index 5d85e566..e69de29b 100644 --- a/taiga/front/__init__.py +++ b/taiga/front/__init__.py @@ -1,57 +0,0 @@ -# Copyright (C) 2014 Andrey Antukh -# 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 . - -from django_jinja import library -from django_sites import get_by_id as get_site_by_id - - -urls = { - "home": "/", - - "login": "/login", - "change-password": "/change-password/{0}", - "change-email": "/change-email/{0}", - "cancel-account": "/cancel-account/{0}", - "invitation": "/invitation/{0}", - - "user": "/profile/{}", - - "project": "/project/{0}", - - "backlog": "/project/{0}/backlog/", - "taskboard": "/project/{0}/taskboard/{1}", - "kanban": "/project/{0}/kanban/", - - "userstory": "/project/{0}/us/{1}", - "task": "/project/{0}/task/{1}", - - "issues": "/project/{0}/issues", - "issue": "/project/{0}/issue/{1}", - - "wiki": "/project/{0}/wiki/{1}", - - "team": "/project/{0}/team/", - - "project-admin": "/project/{0}/admin/project-profile/details", -} - - -@library.global_function(name="resolve_front_url") -def resolve(type, *args): - site = get_site_by_id("front") - url_tmpl = "{scheme}//{domain}{url}" - - scheme = site.scheme and "{0}:".format(site.scheme) or "" - url = urls[type].format(*args) - return url_tmpl.format(scheme=scheme, domain=site.domain, url=url) diff --git a/taiga/front/sitemaps/__init__.py b/taiga/front/sitemaps/__init__.py new file mode 100644 index 00000000..ba5da7bd --- /dev/null +++ b/taiga/front/sitemaps/__init__.py @@ -0,0 +1,60 @@ +# Copyright (C) 2015 David Barragán +# Copyright (C) 2015 Taiga Agile LLC +# +# 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 . + +from collections import OrderedDict + +from .generics import GenericSitemap + +from .projects import ProjectsSitemap +from .projects import ProjectBacklogsSitemap +from .projects import ProjectKanbansSitemap +from .projects import ProjectIssuesSitemap +from .projects import ProjectTeamsSitemap + +from .milestones import MilestonesSitemap + +from .userstories import UserStoriesSitemap + +from .tasks import TasksSitemap + +from .issues import IssuesSitemap + +from .wiki import WikiPagesSitemap + +from .users import UsersSitemap + + +sitemaps = OrderedDict([ + ("generics", GenericSitemap), + + ("projects", ProjectsSitemap), + ("project-backlogs", ProjectBacklogsSitemap), + ("project-kanbans", ProjectKanbansSitemap), + ("project-issues-list", ProjectIssuesSitemap), + ("project-teams", ProjectTeamsSitemap), + + ("milestones", MilestonesSitemap), + + ("userstories", UserStoriesSitemap), + + ("tasks", TasksSitemap), + + ("issues", IssuesSitemap), + + ("wikipages", WikiPagesSitemap), + + ("users", UsersSitemap) +]) diff --git a/taiga/front/sitemaps/base.py b/taiga/front/sitemaps/base.py new file mode 100644 index 00000000..83967f4d --- /dev/null +++ b/taiga/front/sitemaps/base.py @@ -0,0 +1,45 @@ +# Copyright (C) 2015 David Barragán +# Copyright (C) 2015 Taiga Agile LLC +# +# 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 . + +from django.contrib.sitemaps import Sitemap as DjangoSitemap + + +class Sitemap(DjangoSitemap): + def get_urls(self, page=1, site=None, protocol=None): + urls = [] + latest_lastmod = None + all_items_lastmod = True # track if all items have a lastmod + for item in self.paginator.page(page).object_list: + loc = self.__get('location', item) + priority = self.__get('priority', item, None) + lastmod = self.__get('lastmod', item, None) + if all_items_lastmod: + all_items_lastmod = lastmod is not None + if (all_items_lastmod and + (latest_lastmod is None or lastmod > latest_lastmod)): + latest_lastmod = lastmod + url_info = { + 'item': item, + 'location': loc, + 'lastmod': lastmod, + 'changefreq': self.__get('changefreq', item, None), + 'priority': str(priority if priority is not None else ''), + } + urls.append(url_info) + if all_items_lastmod and latest_lastmod: + self.latest_lastmod = latest_lastmod + + return urls diff --git a/taiga/front/sitemaps/generics.py b/taiga/front/sitemaps/generics.py new file mode 100644 index 00000000..180c6eb0 --- /dev/null +++ b/taiga/front/sitemaps/generics.py @@ -0,0 +1,42 @@ +# Copyright (C) 2015 David Barragán +# Copyright (C) 2015 Taiga Agile LLC +# +# 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 . + +from django.db.models import Q +from django.apps import apps + +from taiga.front.templatetags.functions import resolve + +from .base import Sitemap + + +class GenericSitemap(Sitemap): + def items(self): + return [ + {"url_key": "home", "changefreq": "monthly", "priority": 0.6}, + {"url_key": "login", "changefreq": "monthly", "priority": 0.6}, + {"url_key": "register", "changefreq": "monthly", "priority": 0.6}, + {"url_key": "forgot-password", "changefreq": "monthly", "priority": 0.6} + ] + + def location(self, obj): + return resolve(obj["url_key"]) + + def changefreq(self, obj): + return obj.get("changefreq", None) + + def priority(self, obj): + return obj.get("priority", None) + diff --git a/taiga/front/sitemaps/issues.py b/taiga/front/sitemaps/issues.py new file mode 100644 index 00000000..e4404138 --- /dev/null +++ b/taiga/front/sitemaps/issues.py @@ -0,0 +1,49 @@ +# Copyright (C) 2015 David Barragán +# Copyright (C) 2015 Taiga Agile LLC +# +# 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 . + +from django.db.models import Q +from django.apps import apps + +from taiga.front.templatetags.functions import resolve + +from .base import Sitemap + + +class IssuesSitemap(Sitemap): + def items(self): + issue_model = apps.get_model("issues", "Issue") + + # Get issues of public projects OR private projects if anon user can view them + queryset = issue_model.objects.filter(Q(project__is_private=False) | + Q(project__is_private=True, + project__anon_permissions__contains=["view_issues"])) + + # Project data is needed + queryset = queryset.select_related("project") + + return queryset + + def location(self, obj): + return resolve("issue", obj.project.slug, obj.ref) + + def lastmod(self, obj): + return obj.modified_date + + def changefreq(self, obj): + return "daily" + + def priority(self, obj): + return 0.6 diff --git a/taiga/front/sitemaps/milestones.py b/taiga/front/sitemaps/milestones.py new file mode 100644 index 00000000..7dde324b --- /dev/null +++ b/taiga/front/sitemaps/milestones.py @@ -0,0 +1,51 @@ +# Copyright (C) 2015 David Barragán +# Copyright (C) 2015 Taiga Agile LLC +# +# 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 . + +from django.db.models import Q +from django.apps import apps + +from taiga.front.templatetags.functions import resolve + +from .base import Sitemap + + +class MilestonesSitemap(Sitemap): + def items(self): + milestone_model = apps.get_model("milestones", "Milestone") + + # Get US of public projects OR private projects if anon user can view them and us and tasks + queryset = milestone_model.objects.filter(Q(project__is_private=False) | + Q(project__is_private=True, + project__anon_permissions__contains=["view_milestones", + "view_us", + "view_tasks"])) + + # Project data is needed + queryset = queryset.select_related("project") + + return queryset + + def location(self, obj): + return resolve("taskboard", obj.project.slug, obj.slug) + + def lastmod(self, obj): + return obj.modified_date + + def changefreq(self, obj): + return "daily" + + def priority(self, obj): + return 0.6 diff --git a/taiga/front/sitemaps/projects.py b/taiga/front/sitemaps/projects.py new file mode 100644 index 00000000..bbbbfbb8 --- /dev/null +++ b/taiga/front/sitemaps/projects.py @@ -0,0 +1,154 @@ +# Copyright (C) 2015 David Barragán +# Copyright (C) 2015 Taiga Agile LLC +# +# 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 . + +from django.db.models import Q +from django.apps import apps + +from taiga.front.templatetags.functions import resolve + +from .base import Sitemap + + +class ProjectsSitemap(Sitemap): + def items(self): + project_model = apps.get_model("projects", "Project") + + # Get public projects OR private projects if anon user can view them + queryset = project_model.objects.filter(Q(is_private=False) | + Q(is_private=True, + anon_permissions__contains=["view_project"])) + + return queryset + + def location(self, obj): + return resolve("project", obj.slug) + + def lastmod(self, obj): + return obj.modified_date + + def changefreq(self, obj): + return "daily" + + def priority(self, obj): + return 0.6 + + +class ProjectBacklogsSitemap(Sitemap): + def items(self): + project_model = apps.get_model("projects", "Project") + + # Get public projects OR private projects if anon user can view them and user stories + queryset = project_model.objects.filter(Q(is_private=False) | + Q(is_private=True, + anon_permissions__contains=["view_project", + "view_us"])) + + # Exclude projects without backlog enabled + queryset = queryset.exclude(is_backlog_activated=False) + + return queryset + + def location(self, obj): + return resolve("backlog", obj.slug) + + def lastmod(self, obj): + return obj.modified_date + + def changefreq(self, obj): + return "daily" + + def priority(self, obj): + return 0.6 + + +class ProjectKanbansSitemap(Sitemap): + def items(self): + project_model = apps.get_model("projects", "Project") + + # Get public projects OR private projects if anon user can view them and user stories + queryset = project_model.objects.filter(Q(is_private=False) | + Q(is_private=True, + anon_permissions__contains=["view_project", + "view_us"])) + + # Exclude projects without kanban enabled + queryset = queryset.exclude(is_kanban_activated=False) + + return queryset + + def location(self, obj): + return resolve("kanban", obj.slug) + + def lastmod(self, obj): + return obj.modified_date + + def changefreq(self, obj): + return "daily" + + def priority(self, obj): + return 0.6 + + +class ProjectIssuesSitemap(Sitemap): + def items(self): + project_model = apps.get_model("projects", "Project") + + # Get public projects OR private projects if anon user can view them and issues + queryset = project_model.objects.filter(Q(is_private=False) | + Q(is_private=True, + anon_permissions__contains=["view_project", + "view_issues"])) + + # Exclude projects without issues enabled + queryset = queryset.exclude(is_issues_activated=False) + + return queryset + + def location(self, obj): + return resolve("issues", obj.slug) + + def lastmod(self, obj): + return obj.modified_date + + def changefreq(self, obj): + return "daily" + + def priority(self, obj): + return 0.6 + + +class ProjectTeamsSitemap(Sitemap): + def items(self): + project_model = apps.get_model("projects", "Project") + + # Get public projects OR private projects if anon user can view them + queryset = project_model.objects.filter(Q(is_private=False) | + Q(is_private=True, + anon_permissions__contains=["view_project"])) + + return queryset + + def location(self, obj): + return resolve("team", obj.slug) + + def lastmod(self, obj): + return obj.modified_date + + def changefreq(self, obj): + return "daily" + + def priority(self, obj): + return 0.6 diff --git a/taiga/front/sitemaps/tasks.py b/taiga/front/sitemaps/tasks.py new file mode 100644 index 00000000..264be4de --- /dev/null +++ b/taiga/front/sitemaps/tasks.py @@ -0,0 +1,49 @@ +# Copyright (C) 2015 David Barragán +# Copyright (C) 2015 Taiga Agile LLC +# +# 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 . + +from django.db.models import Q +from django.apps import apps + +from taiga.front.templatetags.functions import resolve + +from .base import Sitemap + + +class TasksSitemap(Sitemap): + def items(self): + task_model = apps.get_model("tasks", "Task") + + # Get tasks of public projects OR private projects if anon user can view them + queryset = task_model.objects.filter(Q(project__is_private=False) | + Q(project__is_private=True, + project__anon_permissions__contains=["view_tasks"])) + + # Project data is needed + queryset = queryset.select_related("project") + + return queryset + + def location(self, obj): + return resolve("task", obj.project.slug, obj.ref) + + def lastmod(self, obj): + return obj.modified_date + + def changefreq(self, obj): + return "daily" + + def priority(self, obj): + return 0.4 diff --git a/taiga/front/sitemaps/users.py b/taiga/front/sitemaps/users.py new file mode 100644 index 00000000..c29420e0 --- /dev/null +++ b/taiga/front/sitemaps/users.py @@ -0,0 +1,44 @@ +# Copyright (C) 2015 David Barragán +# Copyright (C) 2015 Taiga Agile LLC +# +# 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 . + +from django.apps import apps + +from taiga.front.templatetags.functions import resolve + +from .base import Sitemap + + +class UsersSitemap(Sitemap): + def items(self): + user_model = apps.get_model("users", "User") + + # Only active users and not system users + queryset = user_model.objects.filter(is_active=True, + is_system=False) + + return queryset + + def location(self, obj): + return resolve("user", obj.username) + + def lastmod(self, obj): + return None + + def changefreq(self, obj): + return "daily" + + def priority(self, obj): + return 0.6 diff --git a/taiga/front/sitemaps/userstories.py b/taiga/front/sitemaps/userstories.py new file mode 100644 index 00000000..da16d19b --- /dev/null +++ b/taiga/front/sitemaps/userstories.py @@ -0,0 +1,49 @@ +# Copyright (C) 2015 David Barragán +# Copyright (C) 2015 Taiga Agile LLC +# +# 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 . + +from django.db.models import Q +from django.apps import apps + +from taiga.front.templatetags.functions import resolve + +from .base import Sitemap + + +class UserStoriesSitemap(Sitemap): + def items(self): + us_model = apps.get_model("userstories", "UserStory") + + # Get US of public projects OR private projects if anon user can view them + queryset = us_model.objects.filter(Q(project__is_private=False) | + Q(project__is_private=True, + project__anon_permissions__contains=["view_us"])) + + # Project data is needed + queryset = queryset.select_related("project") + + return queryset + + def location(self, obj): + return resolve("userstory", obj.project.slug, obj.ref) + + def lastmod(self, obj): + return obj.modified_date + + def changefreq(self, obj): + return "daily" + + def priority(self, obj): + return 0.6 diff --git a/taiga/front/sitemaps/wiki.py b/taiga/front/sitemaps/wiki.py new file mode 100644 index 00000000..eeb96a58 --- /dev/null +++ b/taiga/front/sitemaps/wiki.py @@ -0,0 +1,52 @@ +# Copyright (C) 2015 David Barragán +# Copyright (C) 2015 Taiga Agile LLC +# +# 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 . + +from django.db.models import Q +from django.apps import apps + +from taiga.front.templatetags.functions import resolve + +from .base import Sitemap + + +class WikiPagesSitemap(Sitemap): + def items(self): + wiki_page_model = apps.get_model("wiki", "WikiPage") + + # Get wiki pages of public projects OR private projects if anon user can view them + queryset = wiki_page_model.objects.filter(Q(project__is_private=False) | + Q(project__is_private=True, + project__anon_permissions__contains=["view_wiki_pages"])) + + # Exclude wiki pages from projects without wiki section enabled + queryset = queryset.exclude(project__is_wiki_activated=False) + + # Project data is needed + queryset = queryset.select_related("project") + + return queryset + + def location(self, obj): + return resolve("wiki", obj.project.slug, obj.slug) + + def lastmod(self, obj): + return obj.modified_date + + def changefreq(self, obj): + return "daily" + + def priority(self, obj): + return 0.6 diff --git a/taiga/front/templatetags/__init__.py b/taiga/front/templatetags/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/taiga/front/templatetags/functions.py b/taiga/front/templatetags/functions.py new file mode 100644 index 00000000..9a510d50 --- /dev/null +++ b/taiga/front/templatetags/functions.py @@ -0,0 +1,34 @@ +# Copyright (C) 2015 Andrey Antukh +# Copyright (C) 2015 Jesús Espino +# Copyright (C) 2015 David Barragán +# 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 . + + +from django_jinja import library +from django_sites import get_by_id as get_site_by_id + +from taiga.front.urls import urls + + +register = library.Library() + + +@register.global_function(name="resolve_front_url") +def resolve(type, *args): + site = get_site_by_id("front") + url_tmpl = "{scheme}//{domain}{url}" + + scheme = site.scheme and "{0}:".format(site.scheme) or "" + url = urls[type].format(*args) + return url_tmpl.format(scheme=scheme, domain=site.domain, url=url) diff --git a/taiga/front/urls.py b/taiga/front/urls.py new file mode 100644 index 00000000..b377f655 --- /dev/null +++ b/taiga/front/urls.py @@ -0,0 +1,49 @@ +# Copyright (C) 2015 Andrey Antukh +# Copyright (C) 2015 Jesús Espino +# Copyright (C) 2015 David Barragán +# 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 . + + +urls = { + "home": "/", + "login": "/login", + "register": "/register", + "forgot-password": "/forgot-password", + + "change-password": "/change-password/{0}", # user.token + "change-email": "/change-email/{0}", # user.email_token + "cancel-account": "/cancel-account/{0}", # auth.token.get_token_for_user(user) + "invitation": "/invitation/{0}", # membership.token + + "user": "/profile/{0}", # user.username + + "project": "/project/{0}", # project.slug + + "backlog": "/project/{0}/backlog/", # project.slug + "taskboard": "/project/{0}/taskboard/{1}", # project.slug, milestone.slug + "kanban": "/project/{0}/kanban/", # project.slug + + "userstory": "/project/{0}/us/{1}", # project.slug, us.ref + "task": "/project/{0}/task/{1}", # project.slug, task.ref + + "issues": "/project/{0}/issues", # project.slug + "issue": "/project/{0}/issue/{1}", # project.slug, issue.ref + + "wiki": "/project/{0}/wiki/{1}", # project.slug, wikipage.slug + + "team": "/project/{0}/team/", # project.slug + + "project-admin": "/project/{0}/admin/project-profile/details", # project.slug +} + diff --git a/taiga/mdrender/extensions/references.py b/taiga/mdrender/extensions/references.py index 28f81a50..d472d663 100644 --- a/taiga/mdrender/extensions/references.py +++ b/taiga/mdrender/extensions/references.py @@ -28,7 +28,7 @@ from markdown.inlinepatterns import Pattern from markdown.util import etree from taiga.projects.references.services import get_instance_by_ref -from taiga.front import resolve +from taiga.front.templatetags.functions import resolve class TaigaReferencesExtension(Extension): diff --git a/taiga/mdrender/extensions/target_link.py b/taiga/mdrender/extensions/target_link.py index 26cc6a5f..992399ea 100644 --- a/taiga/mdrender/extensions/target_link.py +++ b/taiga/mdrender/extensions/target_link.py @@ -21,7 +21,7 @@ import markdown from markdown.treeprocessors import Treeprocessor -from taiga.front import resolve +from taiga.front.templatetags.functions import resolve class TargetBlankLinkExtension(markdown.Extension): diff --git a/taiga/mdrender/extensions/wikilinks.py b/taiga/mdrender/extensions/wikilinks.py index 1c16ae54..1fd703b3 100644 --- a/taiga/mdrender/extensions/wikilinks.py +++ b/taiga/mdrender/extensions/wikilinks.py @@ -21,7 +21,7 @@ from markdown.treeprocessors import Treeprocessor from markdown.util import etree -from taiga.front import resolve +from taiga.front.templatetags.functions import resolve from taiga.base.utils.slug import slugify import re diff --git a/taiga/urls.py b/taiga/urls.py index 90cea932..416da685 100644 --- a/taiga/urls.py +++ b/taiga/urls.py @@ -16,12 +16,16 @@ from django.conf import settings from django.conf.urls import patterns, include, url -from django.contrib.staticfiles.urls import staticfiles_urlpatterns from django.contrib import admin from .routers import router from .contrib_routers import router as contrib_router + +############################################## +# Default +############################################## + urlpatterns = [ url(r'^api/v1/', include(router.urls)), url(r'^api/v1/', include(contrib_router.urls)), @@ -29,21 +33,51 @@ urlpatterns = [ url(r'^admin/', include(admin.site.urls)), ] -def mediafiles_urlpatterns(prefix): - """ - Method for serve media files with runserver. - """ - import re - from django.views.static import serve +handler500 = "taiga.base.api.views.api_server_error" - return [ - url(r'^%s(?P.*)$' % re.escape(prefix.lstrip('/')), serve, - {'document_root': settings.MEDIA_ROOT}) + +############################################## +# Front sitemap +############################################## + +if settings.FRONT_SITEMAP_ENABLED: + from django.contrib.sitemaps.views import index + from django.contrib.sitemaps.views import sitemap + from django.views.decorators.cache import cache_page + + from taiga.front.sitemaps import sitemaps + + urlpatterns += [ + url(r"^front/sitemap\.xml$", + cache_page(settings.FRONT_SITEMAP_CACHE_TIMEOUT)(index), + {"sitemaps": sitemaps, 'sitemap_url_name': 'front-sitemap'}, + name="front-sitemap-index"), + url(r"^front/sitemap-(?P
.+)\.xml$", + cache_page(settings.FRONT_SITEMAP_CACHE_TIMEOUT)(sitemap), + {"sitemaps": sitemaps}, + name="front-sitemap") ] + +############################################## +# Static and media files in debug mode +############################################## + if settings.DEBUG: + from django.contrib.staticfiles.urls import staticfiles_urlpatterns + + def mediafiles_urlpatterns(prefix): + """ + Method for serve media files with runserver. + """ + import re + from django.views.static import serve + + return [ + url(r'^%s(?P.*)$' % re.escape(prefix.lstrip('/')), serve, + {'document_root': settings.MEDIA_ROOT}) + ] + # Hardcoded only for development server urlpatterns += staticfiles_urlpatterns(prefix="/static/") urlpatterns += mediafiles_urlpatterns(prefix="/media/") - -handler500 = "taiga.base.api.views.api_server_error"