diff --git a/openslides/core/static/js/core.js b/openslides/core/static/js/core.js
index 58d5d49db..6d132be6e 100644
--- a/openslides/core/static/js/core.js
+++ b/openslides/core/static/js/core.js
@@ -9,11 +9,12 @@ angular.module('OpenSlidesApp.core', [])
var result = {},
views = parent(state);
- if (state.abstract) {
+ if (state.abstract || state.data && state.data.extern) {
return views;
}
angular.forEach(views, function(config, name) {
+
// Sets default values for templateUrl
var patterns = state.name.split('.'),
templateUrl,
@@ -75,9 +76,9 @@ angular.module('OpenSlidesApp.core', [])
.config(function($stateProvider, $locationProvider) {
// Core urls
$stateProvider.state('dashboard', {
- url: '/',
- templateUrl: 'static/templates/dashboard.html'
- });
+ url: '/',
+ templateUrl: 'static/templates/dashboard.html'
+ });
$locationProvider.html5Mode(true);
})
@@ -98,6 +99,30 @@ angular.module('OpenSlidesApp.core', [])
};
})
+.provider('runtimeStates', function($stateProvider) {
+ this.$get = function($q, $timeout, $state) {
+ return {
+ addState: function(name, state) {
+ $stateProvider.state(name, state);
+ }
+ }
+ }
+})
+
+.run(function(runtimeStates, $http) {
+ $http.get('/core/url_patterns/').then(function(data) {
+ for (var pattern in data.data) {
+ runtimeStates.addState(pattern, {
+ 'url': data.data[pattern],
+ data: {extern: true},
+ onEnter: function($window) {
+ $window.location.href = this.url;
+ }
+ });
+ }
+ });
+})
+
.run(function(DS, autoupdate) {
autoupdate.on_message(function(data) {
// TODO: when MODEL.find() is called after this
diff --git a/openslides/core/urls.py b/openslides/core/urls.py
index acddec2d7..9936f08d7 100644
--- a/openslides/core/urls.py
+++ b/openslides/core/urls.py
@@ -43,4 +43,9 @@ urlpatterns = patterns(
url(r'tags/$',
views.TagListView.as_view(),
name='core_tag_list'),
+
+ # Ajax Urls
+ url(r'^core/url_patterns/$',
+ views.UrlPatternsView.as_view(),
+ name='core_url_patterns'),
)
diff --git a/openslides/core/views.py b/openslides/core/views.py
index 53e1b589e..e9175476a 100644
--- a/openslides/core/views.py
+++ b/openslides/core/views.py
@@ -1,27 +1,33 @@
+import re
+
from django.conf import settings
from django.contrib import messages
from django.contrib.staticfiles import finders
from django.core.exceptions import PermissionDenied
-from django.core.urlresolvers import reverse
+from django.core.urlresolvers import get_resolver, reverse
from django.db import IntegrityError
+from django.http import HttpResponse
from django.shortcuts import redirect, render_to_response
from django.template import RequestContext
from django.utils.importlib import import_module
from django.utils.translation import ugettext as _
from haystack.views import SearchView as _SearchView
-from django.http import HttpResponse
from openslides import __version__ as openslides_version
from openslides.config.api import config
from openslides.utils import views as utils_views
-from openslides.utils.plugins import get_plugin_description, get_plugin_verbose_name, get_plugin_version
+from openslides.utils.plugins import (
+ get_plugin_description,
+ get_plugin_verbose_name,
+ get_plugin_version,
+)
from openslides.utils.rest_api import ModelViewSet
from openslides.utils.signals import template_manipulation
from openslides.utils.widgets import Widget
+from .exceptions import TagException
from .forms import SelectWidgetsForm
from .models import CustomSlide, Tag
-from .exceptions import TagException
from .serializers import CustomSlideSerializer, TagSerializer
@@ -338,3 +344,20 @@ class TagViewSet(ModelViewSet):
if (self.action in ('create', 'update', 'destroy') and
not request.user.has_perm('core.can_manage_tags')):
self.permission_denied(request)
+
+
+class UrlPatternsView(utils_views.APIView):
+ """
+ Returns a dictonary with all url patterns as json.
+ """
+ URL_KWARGS_REGEX = re.compile(r'%\((\w*)\)s')
+ http_method_names = ['get']
+
+ def get_context_data(self, **context):
+ result = {}
+ url_dict = get_resolver(None).reverse_dict
+ for pattern_name in filter(lambda key: isinstance(key, str), url_dict.keys()):
+ url = url_dict[pattern_name][0][0][0]
+ result[pattern_name] = self.URL_KWARGS_REGEX.sub(r':\1', url)
+
+ return result
diff --git a/openslides/users/static/js/users/users.js b/openslides/users/static/js/users/users.js
index 37d0bd77d..bd3e3e2d6 100644
--- a/openslides/users/static/js/users/users.js
+++ b/openslides/users/static/js/users/users.js
@@ -2,82 +2,82 @@ angular.module('OpenSlidesApp.users', [])
.config(function($stateProvider) {
$stateProvider
- .state('users', {
- url: '/users',
- abstract: true,
- template: "",
- })
- .state('users.user', {
- abstract: true,
- template: "",
- })
- .state('users.user.list', {
- resolve: {
- users: function(User) {
- return User.findAll();
- }
+ .state('users', {
+ url: '/users',
+ abstract: true,
+ template: "",
+ })
+ .state('users.user', {
+ abstract: true,
+ template: "",
+ })
+ .state('users.user.list', {
+ resolve: {
+ users: function(User) {
+ return User.findAll();
}
- })
- .state('users.user.create', {
- resolve: {
- groups: function(Group) {
- return Group.findAll();
- }
+ }
+ })
+ .state('users.user.create', {
+ resolve: {
+ groups: function(Group) {
+ return Group.findAll();
}
- })
- .state('users.user.detail', {
- resolve: {
- user: function(User, $stateParams) {
- return User.find($stateParams.id);
- }
+ }
+ })
+ .state('users.user.detail', {
+ resolve: {
+ user: function(User, $stateParams) {
+ return User.find($stateParams.id);
}
- })
- .state('users.user.detail.update', {
- views: {
- '@users.user': {}
- },
- resolve: {
- groups: function(Group) {
- return Group.findAll();
- }
+ }
+ })
+ .state('users.user.detail.update', {
+ views: {
+ '@users.user': {}
+ },
+ resolve: {
+ groups: function(Group) {
+ return Group.findAll();
}
- })
- .state('users.user.csv-import', {
- url: '/csv-import',
- controller: 'UserCSVImportCtrl',
- })
- // groups
- .state('users.group', {
- url: '/groups',
- abstract: true,
- template: "",
- })
- .state('users.group.list', {
- resolve: {
- groups: function(Group) {
- return Group.findAll();
- }
+ }
+ })
+ .state('users.user.csv-import', {
+ url: '/csv-import',
+ controller: 'UserCSVImportCtrl',
+ })
+ // groups
+ .state('users.group', {
+ url: '/groups',
+ abstract: true,
+ template: "",
+ })
+ .state('users.group.list', {
+ resolve: {
+ groups: function(Group) {
+ return Group.findAll();
}
- })
- .state('users.group.create', {
- resolve: {
- groups: function(Group) {
- return Group.findAll();
- }
+ }
+ })
+ .state('users.group.create', {
+ resolve: {
+ groups: function(Group) {
+ return Group.findAll();
}
- })
- .state('users.group.detail', {
- resolve: {
- group: function(Group, $stateParams) {
- return Group.find($stateParams.id);
- }
+ }
+ })
+ .state('users.group.detail', {
+ resolve: {
+ group: function(Group, $stateParams) {
+ return Group.find($stateParams.id);
}
- })
- .state('users.group.detail.update', {
- views: {
- '@users.group': {}
- }
- });
+ }
+ })
+ .state('users.group.detail.update', {
+ views: {
+ '@users.group': {}
+ }
+ });
})
.factory('operator', function(User, Group) {
diff --git a/openslides/users/views.py b/openslides/users/views.py
index d64f60ffd..687666ea3 100644
--- a/openslides/users/views.py
+++ b/openslides/users/views.py
@@ -28,6 +28,8 @@ from .serializers import (
)
+# Views to generate PDFs
+
class UsersListPDF(PDFView):
"""
Generate the userliste as PDF.
@@ -61,15 +63,7 @@ class UsersPasswordsPDF(PDFView):
users_passwords_to_pdf(pdf)
-class UserCSVImportView(CSVImportView):
- """
- Import users via CSV.
- """
- required_permission = 'users.can_manage'
- success_url_name = 'user_list'
- template_name = 'users/user_form_csv_import.html'
- import_function = staticmethod(import_users)
-
+# Viewsets for the rest api
class UserViewSet(ModelViewSet):
"""
@@ -136,44 +130,7 @@ class GroupViewSet(ModelViewSet):
return response
-class UserSettingsView(LoginMixin, UpdateView):
- required_permission = None
- template_name = 'users/settings.html'
- success_url_name = 'user_settings'
- model = User
- form_class = UsersettingsForm
- url_name_args = []
-
- def get_initial(self):
- initial = super().get_initial()
- initial['language'] = self.request.session.get('django_language', self.request.LANGUAGE_CODE)
- return initial
-
- def form_valid(self, form):
- self.request.LANGUAGE_CODE = self.request.session['django_language'] = form.cleaned_data['language']
- activate(self.request.LANGUAGE_CODE)
- return super().form_valid(form)
-
- def get_object(self):
- return self.request.user
-
-
-class UserPasswordSettingsView(LoginMixin, FormView):
- required_permission = None
- template_name = 'users/password_change.html'
- success_url_name = 'core_dashboard'
- form_class = PasswordChangeForm
-
- def form_valid(self, form):
- form.save()
- messages.success(self.request, _('Password successfully changed.'))
- return super().form_valid(form)
-
- def get_form_kwargs(self):
- kwargs = super().get_form_kwargs()
- kwargs['user'] = self.request.user
- return kwargs
-
+# API Views
class UserLoginView(APIView):
"""
@@ -224,3 +181,54 @@ class WhoAmIView(APIView):
return super().get_context_data(
user_id=self.request.user.pk,
**context)
+
+
+# Deprecated views. Will be removed after the implementation in angularjs
+
+class UserCSVImportView(CSVImportView):
+ """
+ Import users via CSV.
+ """
+ required_permission = 'users.can_manage'
+ success_url_name = 'user_list'
+ template_name = 'users/user_form_csv_import.html'
+ import_function = staticmethod(import_users)
+
+
+class UserSettingsView(LoginMixin, UpdateView):
+ required_permission = None
+ template_name = 'users/settings.html'
+ success_url_name = 'user_settings'
+ model = User
+ form_class = UsersettingsForm
+ url_name_args = []
+
+ def get_initial(self):
+ initial = super().get_initial()
+ initial['language'] = self.request.session.get('django_language', self.request.LANGUAGE_CODE)
+ return initial
+
+ def form_valid(self, form):
+ self.request.LANGUAGE_CODE = self.request.session['django_language'] = form.cleaned_data['language']
+ activate(self.request.LANGUAGE_CODE)
+ return super().form_valid(form)
+
+ def get_object(self):
+ return self.request.user
+
+
+class UserPasswordSettingsView(LoginMixin, FormView):
+ required_permission = None
+ template_name = 'users/password_change.html'
+ success_url_name = 'core_dashboard'
+ form_class = PasswordChangeForm
+
+ def form_valid(self, form):
+ form.save()
+ messages.success(self.request, _('Password successfully changed.'))
+ return super().form_valid(form)
+
+ def get_form_kwargs(self):
+ kwargs = super().get_form_kwargs()
+ kwargs['user'] = self.request.user
+ return kwargs
diff --git a/tests/unit/core/__init__.py b/tests/unit/core/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/unit/core/test_views.py b/tests/unit/core/test_views.py
new file mode 100644
index 000000000..36f1df6b3
--- /dev/null
+++ b/tests/unit/core/test_views.py
@@ -0,0 +1,21 @@
+from unittest import TestCase
+from unittest.mock import patch
+
+from openslides.core import views
+
+
+class TestUrlPatternsView(TestCase):
+ @patch('openslides.core.views.get_resolver')
+ def test_get_context_data(self, mock_resolver):
+ mock_resolver().reverse_dict = {
+ 'url_pattern1': [[['my_url1']]],
+ 'url_pattern2': [[['my_url2/%(kwarg)s/']]],
+ ('not_a_str', ): [[['not_a_str']]]}
+ view = views.UrlPatternsView()
+
+ context = view.get_context_data()
+
+ self.assertEqual(
+ context,
+ {'url_pattern1': 'my_url1',
+ 'url_pattern2': 'my_url2/:kwarg/'})