Merge pull request #1466 from ostcar/django_urls
Use django url patterns in angular
This commit is contained in:
commit
146548a309
@ -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
|
||||
|
@ -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'),
|
||||
)
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
0
tests/unit/core/__init__.py
Normal file
0
tests/unit/core/__init__.py
Normal file
21
tests/unit/core/test_views.py
Normal file
21
tests/unit/core/test_views.py
Normal 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/'})
|
Loading…
Reference in New Issue
Block a user