Use ui-router to handle django urls

See: #1453
This commit is contained in:
Oskar Hahn 2015-02-14 10:10:08 +01:00
parent 962dd209f5
commit 80ca3f2484
7 changed files with 206 additions and 124 deletions

View File

@ -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

View File

@ -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'),
)

View File

@ -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

View File

@ -2,82 +2,82 @@ angular.module('OpenSlidesApp.users', [])
.config(function($stateProvider) {
$stateProvider
.state('users', {
url: '/users',
abstract: true,
template: "<ui-view/>",
})
.state('users.user', {
abstract: true,
template: "<ui-view/>",
})
.state('users.user.list', {
resolve: {
users: function(User) {
return User.findAll();
}
.state('users', {
url: '/users',
abstract: true,
template: "<ui-view/>",
})
.state('users.user', {
abstract: true,
template: "<ui-view/>",
})
.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: "<ui-view/>",
})
.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: "<ui-view/>",
})
.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) {

View File

@ -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

View File

View File

@ -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/'})