From 49e32d8e57b271254fd32d71dd9defb9cd51545d Mon Sep 17 00:00:00 2001 From: FinnStutzenstein Date: Fri, 20 Jan 2017 10:23:14 +0100 Subject: [PATCH] Possibility to send extra startup data (closes #2885) --- openslides/assignments/apps.py | 12 +++++++++ .../assignments/static/js/assignments/base.js | 12 --------- .../assignments/static/js/assignments/site.js | 23 +++++----------- openslides/core/apps.py | 19 ++++++++++++++ openslides/core/views.py | 26 ++++++++++--------- tests/integration/core/test_views.py | 24 +++++++++++++++++ 6 files changed, 76 insertions(+), 40 deletions(-) diff --git a/openslides/assignments/apps.py b/openslides/assignments/apps.py index 6a796d687..d2ca4d030 100644 --- a/openslides/assignments/apps.py +++ b/openslides/assignments/apps.py @@ -28,3 +28,15 @@ class AssignmentsAppConfig(AppConfig): def get_startup_elements(self): from ..utils.collection import Collection 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] diff --git a/openslides/assignments/static/js/assignments/base.js b/openslides/assignments/static/js/assignments/base.js index e09cd9135..1dfde308f 100644 --- a/openslides/assignments/static/js/assignments/base.js +++ b/openslides/assignments/static/js/assignments/base.js @@ -330,18 +330,6 @@ angular.module('OpenSlidesApp.assignments', []) useClass: jsDataModel, verboseName: gettext('Election'), 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: { getResourceName: function () { return name; diff --git a/openslides/assignments/static/js/assignments/site.js b/openslides/assignments/static/js/assignments/site.js index e6d612603..197bb9177 100644 --- a/openslides/assignments/static/js/assignments/site.js +++ b/openslides/assignments/static/js/assignments/site.js @@ -41,22 +41,13 @@ angular.module('OpenSlidesApp.assignments.site', [ abstract: true, template: "", }) - .state('assignments.assignment.list', { - resolve: { - phases: ['Assignment', function (Assignment) { - return Assignment.getPhases(); - }], - } - }) + .state('assignments.assignment.list', {}) .state('assignments.assignment.detail', { controller: 'AssignmentDetailCtrl', resolve: { assignmentId: ['$stateParams', function($stateParams) { return $stateParams.id; }], - phases: ['Assignment', function (Assignment) { - return Assignment.getPhases(); - }], } }) // redirects to assignment detail and opens assignment edit form dialog, uses edit url, @@ -263,11 +254,11 @@ angular.module('OpenSlidesApp.assignments.site', [ 'osTableFilter', 'osTableSort', 'gettext', - 'phases', 'PdfCreate', + 'AssignmentPhases', function($scope, ngDialog, AssignmentForm, Assignment, Tag, Agenda, Projector, ProjectionDefault, gettextCatalog, AssignmentContentProvider, AssignmentCatalogContentProvider, PdfMakeDocumentProvider, - User, osTableFilter, osTableSort, gettext, phases, PdfCreate) { + User, osTableFilter, osTableSort, gettext, phases, PdfCreate, AssignmentPhases) { Assignment.bindAll({}, $scope, 'assignments'); Tag.bindAll({}, $scope, 'tags'); $scope.$watch(function () { @@ -278,7 +269,7 @@ angular.module('OpenSlidesApp.assignments.site', [ $scope.defaultProjectorId = projectiondefault.projector_id; } }); - $scope.phases = phases; + $scope.phases = AssignmentPhases; $scope.alert = {}; // Filtering @@ -404,7 +395,6 @@ angular.module('OpenSlidesApp.assignments.site', [ 'Assignment', 'User', 'assignmentId', - 'phases', 'Projector', 'ProjectionDefault', 'AssignmentContentProvider', @@ -413,9 +403,10 @@ angular.module('OpenSlidesApp.assignments.site', [ 'PdfMakeBallotPaperProvider', 'gettextCatalog', 'PdfCreate', + 'AssignmentPhases', function($scope, $http, $filter, filterFilter, gettext, ngDialog, AssignmentForm, operator, Assignment, User, assignmentId, phases, Projector, ProjectionDefault, AssignmentContentProvider, BallotContentProvider, - PdfMakeDocumentProvider, PdfMakeBallotPaperProvider, gettextCatalog, PdfCreate) { + PdfMakeDocumentProvider, PdfMakeBallotPaperProvider, gettextCatalog, PdfCreate, AssignmentPhases) { var assignment = Assignment.get(assignmentId); User.bindAll({}, $scope, 'users'); Assignment.loadRelations(assignment, 'agenda_item'); @@ -435,7 +426,7 @@ angular.module('OpenSlidesApp.assignments.site', [ $scope.assignment = Assignment.get(assignment.id); }); $scope.candidateSelectBox = {}; - $scope.phases = phases; + $scope.phases = AssignmentPhases; $scope.alert = {}; $scope.activeTab = 0; diff --git a/openslides/core/apps.py b/openslides/core/apps.py index 3abd4e47a..6d6f2fdff 100644 --- a/openslides/core/apps.py +++ b/openslides/core/apps.py @@ -1,4 +1,5 @@ from django.apps import AppConfig +from django.conf import settings class CoreAppConfig(AppConfig): @@ -62,3 +63,21 @@ class CoreAppConfig(AppConfig): for model in ('Projector', 'ChatMessage', 'Tag', 'ProjectorMessage', 'Countdown'): yield Collection(self.get_model(model).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] diff --git a/openslides/core/views.py b/openslides/core/views.py index df4976111..23e04d20f 100644 --- a/openslides/core/views.py +++ b/openslides/core/views.py @@ -140,17 +140,20 @@ class WebclientJavaScriptView(utils_views.View): else: js_files.extend(app_js_files) - client_settings_keys = [ - 'MOTIONS_ALLOW_AMENDMENTS_OF_AMENDMENTS' - ] - client_settings = {} - for key in client_settings_keys: + # angular constants + angular_constants = '' + for app in apps.get_app_configs(): 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: - # Settings key does not exist. Do nothing. The client will - # treat this as undefined. - pass + # The app doesn't have this method. Continue to next app. + continue + 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 # 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}) - .constant('OpenSlidesSettings', {settings}); + angular.module('OpenSlidesApp.{realm}', {angular_modules}){angular_constants}; var deferres = []; {js_files}.forEach( function(js_file) {{ deferres.push(loadScript(js_file)); }} ); $.when.apply(this,deferres).done( function() {{ 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) + """ }()); """) diff --git a/tests/integration/core/test_views.py b/tests/integration/core/test_views.py index 23bc01d51..02306eda3 100644 --- a/tests/integration/core/test_views.py +++ b/tests/integration/core/test_views.py @@ -1,5 +1,6 @@ import json +from django.apps import apps from django.core.urlresolvers import reverse from rest_framework import status from rest_framework.test import APIClient @@ -76,6 +77,29 @@ class VersionView(TestCase): '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): """ Tests requests to deal with config variables.