Merge pull request #2895 from FinnStutzenstein/Issue2885

Possibility to send extra startup data (closes #2885)
This commit is contained in:
Norman Jäckel 2017-02-01 11:45:21 +01:00 committed by GitHub
commit b6db7d481b
6 changed files with 76 additions and 40 deletions

View File

@ -28,3 +28,15 @@ class AssignmentsAppConfig(AppConfig):
def get_startup_elements(self): def get_startup_elements(self):
from ..utils.collection import Collection from ..utils.collection import Collection
return [Collection(self.get_model('Assignment').get_collection_string())] return [Collection(self.get_model('Assignment').get_collection_string())]
def get_angular_constants(self):
assignment = self.get_model('Assignment')
data = {
'name': 'AssignmentPhases',
'value': []}
for phase in assignment.PHASES:
data['value'].append({
'value': phase[0],
'display_name': phase[1],
})
return [data]

View File

@ -330,18 +330,6 @@ angular.module('OpenSlidesApp.assignments', [])
useClass: jsDataModel, useClass: jsDataModel,
verboseName: gettext('Election'), verboseName: gettext('Election'),
verboseNamePlural: gettext('Elections'), verboseNamePlural: gettext('Elections'),
phases: phases,
// TODO (Issue 2885): Do not query this from server. It should be included in the startup data.
// Remove than all 'phases' injections from resolvers.
getPhases: function () {
if (!this.phases) {
this.phases = $http({ 'method': 'OPTIONS', 'url': '/rest/assignments/assignment/' })
.then(function(phases) {
return phases.data.actions.POST.phase.choices;
});
}
return this.phases;
},
methods: { methods: {
getResourceName: function () { getResourceName: function () {
return name; return name;

View File

@ -41,22 +41,13 @@ angular.module('OpenSlidesApp.assignments.site', [
abstract: true, abstract: true,
template: "<ui-view/>", template: "<ui-view/>",
}) })
.state('assignments.assignment.list', { .state('assignments.assignment.list', {})
resolve: {
phases: ['Assignment', function (Assignment) {
return Assignment.getPhases();
}],
}
})
.state('assignments.assignment.detail', { .state('assignments.assignment.detail', {
controller: 'AssignmentDetailCtrl', controller: 'AssignmentDetailCtrl',
resolve: { resolve: {
assignmentId: ['$stateParams', function($stateParams) { assignmentId: ['$stateParams', function($stateParams) {
return $stateParams.id; return $stateParams.id;
}], }],
phases: ['Assignment', function (Assignment) {
return Assignment.getPhases();
}],
} }
}) })
// redirects to assignment detail and opens assignment edit form dialog, uses edit url, // redirects to assignment detail and opens assignment edit form dialog, uses edit url,
@ -263,11 +254,11 @@ angular.module('OpenSlidesApp.assignments.site', [
'osTableFilter', 'osTableFilter',
'osTableSort', 'osTableSort',
'gettext', 'gettext',
'phases',
'PdfCreate', 'PdfCreate',
'AssignmentPhases',
function($scope, ngDialog, AssignmentForm, Assignment, Tag, Agenda, Projector, ProjectionDefault, function($scope, ngDialog, AssignmentForm, Assignment, Tag, Agenda, Projector, ProjectionDefault,
gettextCatalog, AssignmentContentProvider, AssignmentCatalogContentProvider, PdfMakeDocumentProvider, gettextCatalog, AssignmentContentProvider, AssignmentCatalogContentProvider, PdfMakeDocumentProvider,
User, osTableFilter, osTableSort, gettext, phases, PdfCreate) { User, osTableFilter, osTableSort, gettext, phases, PdfCreate, AssignmentPhases) {
Assignment.bindAll({}, $scope, 'assignments'); Assignment.bindAll({}, $scope, 'assignments');
Tag.bindAll({}, $scope, 'tags'); Tag.bindAll({}, $scope, 'tags');
$scope.$watch(function () { $scope.$watch(function () {
@ -278,7 +269,7 @@ angular.module('OpenSlidesApp.assignments.site', [
$scope.defaultProjectorId = projectiondefault.projector_id; $scope.defaultProjectorId = projectiondefault.projector_id;
} }
}); });
$scope.phases = phases; $scope.phases = AssignmentPhases;
$scope.alert = {}; $scope.alert = {};
// Filtering // Filtering
@ -404,7 +395,6 @@ angular.module('OpenSlidesApp.assignments.site', [
'Assignment', 'Assignment',
'User', 'User',
'assignmentId', 'assignmentId',
'phases',
'Projector', 'Projector',
'ProjectionDefault', 'ProjectionDefault',
'AssignmentContentProvider', 'AssignmentContentProvider',
@ -413,9 +403,10 @@ angular.module('OpenSlidesApp.assignments.site', [
'PdfMakeBallotPaperProvider', 'PdfMakeBallotPaperProvider',
'gettextCatalog', 'gettextCatalog',
'PdfCreate', 'PdfCreate',
'AssignmentPhases',
function($scope, $http, $filter, filterFilter, gettext, ngDialog, AssignmentForm, operator, Assignment, function($scope, $http, $filter, filterFilter, gettext, ngDialog, AssignmentForm, operator, Assignment,
User, assignmentId, phases, Projector, ProjectionDefault, AssignmentContentProvider, BallotContentProvider, User, assignmentId, phases, Projector, ProjectionDefault, AssignmentContentProvider, BallotContentProvider,
PdfMakeDocumentProvider, PdfMakeBallotPaperProvider, gettextCatalog, PdfCreate) { PdfMakeDocumentProvider, PdfMakeBallotPaperProvider, gettextCatalog, PdfCreate, AssignmentPhases) {
var assignment = Assignment.get(assignmentId); var assignment = Assignment.get(assignmentId);
User.bindAll({}, $scope, 'users'); User.bindAll({}, $scope, 'users');
Assignment.loadRelations(assignment, 'agenda_item'); Assignment.loadRelations(assignment, 'agenda_item');
@ -435,7 +426,7 @@ angular.module('OpenSlidesApp.assignments.site', [
$scope.assignment = Assignment.get(assignment.id); $scope.assignment = Assignment.get(assignment.id);
}); });
$scope.candidateSelectBox = {}; $scope.candidateSelectBox = {};
$scope.phases = phases; $scope.phases = AssignmentPhases;
$scope.alert = {}; $scope.alert = {};
$scope.activeTab = 0; $scope.activeTab = 0;

View File

@ -1,4 +1,5 @@
from django.apps import AppConfig from django.apps import AppConfig
from django.conf import settings
class CoreAppConfig(AppConfig): class CoreAppConfig(AppConfig):
@ -62,3 +63,21 @@ class CoreAppConfig(AppConfig):
for model in ('Projector', 'ChatMessage', 'Tag', 'ProjectorMessage', 'Countdown'): for model in ('Projector', 'ChatMessage', 'Tag', 'ProjectorMessage', 'Countdown'):
yield Collection(self.get_model(model).get_collection_string()) yield Collection(self.get_model(model).get_collection_string())
yield Collection(config.get_collection_string()) yield Collection(config.get_collection_string())
def get_angular_constants(self):
# Client settings
client_settings_keys = [
'MOTIONS_ALLOW_AMENDMENTS_OF_AMENDMENTS'
]
client_settings_dict = {}
for key in client_settings_keys:
try:
client_settings_dict[key] = getattr(settings, key)
except AttributeError:
# Settings key does not exist. Do nothing. The client will
# treat this as undefined.
pass
client_settings = {
'name': 'OpenSlidesSettings',
'value': client_settings_dict}
return [client_settings]

View File

@ -140,17 +140,20 @@ class WebclientJavaScriptView(utils_views.View):
else: else:
js_files.extend(app_js_files) js_files.extend(app_js_files)
client_settings_keys = [ # angular constants
'MOTIONS_ALLOW_AMENDMENTS_OF_AMENDMENTS' angular_constants = ''
] for app in apps.get_app_configs():
client_settings = {}
for key in client_settings_keys:
try: try:
client_settings[key] = getattr(settings, key) # Each app can deliver values to angular when implementing this method.
# It should return a list with dicts containing the 'name' and 'value'.
get_angular_constants = app.get_angular_constants
except AttributeError: except AttributeError:
# Settings key does not exist. Do nothing. The client will # The app doesn't have this method. Continue to next app.
# treat this as undefined. continue
pass for constant in get_angular_constants():
value = json.dumps(constant['value'])
name = constant['name']
angular_constants += ".constant('{}', {})".format(name, value)
# Use JavaScript loadScript function from # Use JavaScript loadScript function from
# http://balpha.de/2011/10/jquery-script-insertion-and-its-consequences-for-debugging/ # http://balpha.de/2011/10/jquery-script-insertion-and-its-consequences-for-debugging/
@ -178,14 +181,13 @@ class WebclientJavaScriptView(utils_views.View):
}; };
""" + """ +
""" """
angular.module('OpenSlidesApp.{realm}', {angular_modules}) angular.module('OpenSlidesApp.{realm}', {angular_modules}){angular_constants};
.constant('OpenSlidesSettings', {settings});
var deferres = []; var deferres = [];
{js_files}.forEach( function(js_file) {{ deferres.push(loadScript(js_file)); }} ); {js_files}.forEach( function(js_file) {{ deferres.push(loadScript(js_file)); }} );
$.when.apply(this,deferres).done( function() {{ $.when.apply(this,deferres).done( function() {{
angular.bootstrap(document,['OpenSlidesApp.{realm}']); angular.bootstrap(document,['OpenSlidesApp.{realm}']);
}} ); }} );
""".format(realm=realm, angular_modules=angular_modules, settings=json.dumps(client_settings), js_files=js_files) + """.format(realm=realm, angular_modules=angular_modules, angular_constants=angular_constants, js_files=js_files) +
""" """
}()); }());
""") """)

View File

@ -1,5 +1,6 @@
import json import json
from django.apps import apps
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from rest_framework import status from rest_framework import status
from rest_framework.test import APIClient from rest_framework.test import APIClient
@ -76,6 +77,29 @@ class VersionView(TestCase):
'version': 'unknown'}]}) 'version': 'unknown'}]})
class WebclientJavaScriptView(TestCase):
"""
Tests the generation of the JavaScript startup code.
"""
def test_angular_constants(self):
self.client.login(username='admin', password='admin')
response = self.client.get(reverse('core_webclient_javascript', args=['site']))
content = response.content.decode()
constants = self.get_angular_constants_from_apps()
for constant in constants:
self.assertTrue(json.dumps(constant['value']) in content)
def get_angular_constants_from_apps(self):
constants = []
for app in apps.get_app_configs():
try:
get_angular_constants = app.get_angular_constants
except AttributeError:
continue
constants.extend(get_angular_constants())
return constants
class ConfigViewSet(TestCase): class ConfigViewSet(TestCase):
""" """
Tests requests to deal with config variables. Tests requests to deal with config variables.