From 291f60ee9fd1bcd2ea277fa483bdfd634e78a501 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Wed, 1 Jul 2015 17:48:41 +0200 Subject: [PATCH] Added a way to load angular apps dynamical --- openslides/agenda/apps.py | 3 ++ openslides/assignments/__init__.py | 2 +- openslides/assignments/apps.py | 5 +- openslides/core/apps.py | 3 ++ openslides/core/static/js/app.js | 52 ------------------- openslides/core/static/js/{ => core}/core.js | 37 ++++++++++++- openslides/core/static/templates/index.html | 10 +--- .../core/static/templates/projector.html | 10 +--- openslides/core/urls.py | 5 ++ openslides/core/views.py | 44 ++++++++++++++++ openslides/mediafiles/__init__.py | 2 +- openslides/mediafiles/apps.py | 5 +- .../static/js/mediafiles/mediafiles.js | 3 ++ openslides/motions/__init__.py | 2 +- openslides/motions/apps.py | 5 +- openslides/users/apps.py | 3 ++ requirements.txt | 2 +- 17 files changed, 116 insertions(+), 77 deletions(-) delete mode 100644 openslides/core/static/js/app.js rename openslides/core/static/js/{ => core}/core.js (95%) diff --git a/openslides/agenda/apps.py b/openslides/agenda/apps.py index f6a935eb6..60f9aecab 100644 --- a/openslides/agenda/apps.py +++ b/openslides/agenda/apps.py @@ -4,6 +4,9 @@ from django.apps import AppConfig class AgendaAppConfig(AppConfig): name = 'openslides.agenda' verbose_name = 'OpenSlides Agenda' + angular_site_module = True + angular_projector_module = True + js_files = ['js/agenda/agenda.js'] def ready(self): # Load projector elements. diff --git a/openslides/assignments/__init__.py b/openslides/assignments/__init__.py index 3d09acb77..b26bfa2fe 100644 --- a/openslides/assignments/__init__.py +++ b/openslides/assignments/__init__.py @@ -1 +1 @@ -default_app_config = 'openslides.assignments.apps.AssignmentAppConfig' +default_app_config = 'openslides.assignments.apps.AssignmentsAppConfig' diff --git a/openslides/assignments/apps.py b/openslides/assignments/apps.py index 2cc34758d..d00028cce 100644 --- a/openslides/assignments/apps.py +++ b/openslides/assignments/apps.py @@ -1,9 +1,12 @@ from django.apps import AppConfig -class AssignmentAppConfig(AppConfig): +class AssignmentsAppConfig(AppConfig): name = 'openslides.assignments' verbose_name = 'OpenSlides Assignments' + angular_site_module = True + angular_projector_module = True + js_files = ['js/assignments/assignments.js'] def ready(self): # Load projector elements. diff --git a/openslides/core/apps.py b/openslides/core/apps.py index 13861e295..d180b7109 100644 --- a/openslides/core/apps.py +++ b/openslides/core/apps.py @@ -4,6 +4,9 @@ from django.apps import AppConfig class CoreAppConfig(AppConfig): name = 'openslides.core' verbose_name = 'OpenSlides Core' + angular_site_module = True + angular_projector_module = True + js_files = ['js/core/core.js'] def ready(self): # Load projector elements. diff --git a/openslides/core/static/js/app.js b/openslides/core/static/js/app.js deleted file mode 100644 index 7d26154e6..000000000 --- a/openslides/core/static/js/app.js +++ /dev/null @@ -1,52 +0,0 @@ -angular.module('OpenSlidesApp', [ - 'angular-loading-bar', - 'js-data', - 'gettext', - 'ngAnimate', - 'ui.bootstrap', - 'ui.tree', -]); - -angular.module('OpenSlidesApp.projector', [ - 'OpenSlidesApp', - 'OpenSlidesApp.core.projector', - 'OpenSlidesApp.agenda.projector', - 'OpenSlidesApp.motions.projector', - 'OpenSlidesApp.assignments.projector', - 'OpenSlidesApp.users.projector', - 'OpenSlidesApp.mediafiles', -]); - -angular.module('OpenSlidesApp.site', [ - 'OpenSlidesApp', - 'ui.router', - 'ngBootbox', - 'ngFabForm', - 'ngMessages', - 'ngCsvImport', - 'ngSanitize', // TODO: remove this as global dependency - 'ui.select', - 'xeditable', - 'OpenSlidesApp.core.site', - 'OpenSlidesApp.agenda.site', - 'OpenSlidesApp.motions.site', - 'OpenSlidesApp.assignments.site', - 'OpenSlidesApp.users.site', - 'OpenSlidesApp.mediafiles.site', -]) - -.config(function($urlRouterProvider, $locationProvider) { - // define fallback url and html5Mode - $urlRouterProvider.otherwise('/'); - $locationProvider.html5Mode(true); -}) - -.config(function($httpProvider) { - // Combine the django csrf system with the angular csrf system - $httpProvider.defaults.xsrfCookieName = 'csrftoken'; - $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken'; -}) - -.config(function(uiSelectConfig) { - uiSelectConfig.theme = 'bootstrap'; -}); diff --git a/openslides/core/static/js/core.js b/openslides/core/static/js/core/core.js similarity index 95% rename from openslides/core/static/js/core.js rename to openslides/core/static/js/core/core.js index 6b74a5291..ef605bd1c 100644 --- a/openslides/core/static/js/core.js +++ b/openslides/core/static/js/core/core.js @@ -1,5 +1,12 @@ // The core module used for the OpenSlides site and the projector -angular.module('OpenSlidesApp.core', []) +angular.module('OpenSlidesApp.core', [ + 'angular-loading-bar', + 'js-data', + 'gettext', + 'ngAnimate', + 'ui.bootstrap', + 'ui.tree', +]) .config(function(DSProvider) { // Reloads everything after 5 minutes. @@ -146,7 +153,33 @@ angular.module('OpenSlidesApp.core', []) // The core module for the OpenSlides site -angular.module('OpenSlidesApp.core.site', ['OpenSlidesApp.core']) +angular.module('OpenSlidesApp.core.site', [ + 'OpenSlidesApp.core', + 'ui.router', + 'ngBootbox', + 'ngFabForm', + 'ngMessages', + 'ngCsvImport', + 'ngSanitize', // TODO: only use this in functions that need it. + 'ui.select', + 'xeditable', +]) + +.config(function($urlRouterProvider, $locationProvider) { + // define fallback url and html5Mode + $urlRouterProvider.otherwise('/'); + $locationProvider.html5Mode(true); +}) + +.config(function($httpProvider) { + // Combine the django csrf system with the angular csrf system + $httpProvider.defaults.xsrfCookieName = 'csrftoken'; + $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken'; +}) + +.config(function(uiSelectConfig) { + uiSelectConfig.theme = 'bootstrap'; +}) .config(function($stateProvider, $urlMatcherFactoryProvider) { // Make the trailing slash optional diff --git a/openslides/core/static/templates/index.html b/openslides/core/static/templates/index.html index 86fc41d22..51af20959 100644 --- a/openslides/core/static/templates/index.html +++ b/openslides/core/static/templates/index.html @@ -2,7 +2,7 @@ - + @@ -189,10 +189,4 @@ - - - - - - - + diff --git a/openslides/core/static/templates/projector.html b/openslides/core/static/templates/projector.html index 1bf3bd723..2d40a59d0 100644 --- a/openslides/core/static/templates/projector.html +++ b/openslides/core/static/templates/projector.html @@ -1,5 +1,5 @@ - + OpenSlides – Projector @@ -48,10 +48,4 @@ - - - - - - - + diff --git a/openslides/core/urls.py b/openslides/core/urls.py index d9bd83a07..3abb6dd9a 100644 --- a/openslides/core/urls.py +++ b/openslides/core/urls.py @@ -7,10 +7,15 @@ urlpatterns = patterns( url(r'^core/url_patterns/$', views.UrlPatternsView.as_view(), name='core_url_patterns'), + url(r'^core/version/$', views.VersionView.as_view(), name='core_version'), + url(r'^angular_js/(?Psite|projector)/$', + views.AppsJsView.as_view(), + name='core_apps_js'), + # View for the projectors are handelt by angular. url(r'^projector.*$', views.ProjectorView.as_view()), diff --git a/openslides/core/views.py b/openslides/core/views.py index 0c4875e2e..65df4549d 100644 --- a/openslides/core/views.py +++ b/openslides/core/views.py @@ -2,6 +2,7 @@ import re from collections import OrderedDict from operator import attrgetter +from django.apps import apps from django.conf import settings from django.contrib.staticfiles import finders from django.core.urlresolvers import get_resolver @@ -308,3 +309,46 @@ class ConfigViewSet(ViewSet): # Return response. return Response({'key': key, 'value': value}) + + +class AppsJsView(utils_views.View): + """ + Returns javascript code to be called in the angular app. + + The javascript code loads all js-files defined by the installed (django) + apps and creates the angular modules for each angular app. + """ + def get(self, *args, **kwargs): + angular_modules = [] + js_files = [] + for app_config in apps.get_app_configs(): + # Add the angular app, if the module has one. + if getattr(app_config, + 'angular_{}_module'.format(kwargs.get('openslides_app')), + False): + angular_modules.append('OpenSlidesApp.{app_name}.{app}'.format( + app=kwargs.get('openslides_app'), + app_name=app_config.label)) + + # Add all js files that the module needs + try: + app_js_files = app_config.js_files + except AttributeError: + # The app needs no js-files + pass + else: + js_files += [ + '{static}{path}'.format( + static=settings.STATIC_URL, + path=path) + for path in app_js_files] + + return HttpResponse( + "angular.module('OpenSlidesApp.{app}', {angular_modules});" + "var deferres = [];" + "{js_files}.forEach(function(js_file)deferres.push($.getScript(js_file)));" + "$.when.apply(this, deferres).done(function() angular.bootstrap(document,['OpenSlidesApp.{app}']));" + .format( + app=kwargs.get('openslides_app'), + angular_modules=angular_modules, + js_files=js_files)) diff --git a/openslides/mediafiles/__init__.py b/openslides/mediafiles/__init__.py index 6e3261912..c3142580b 100644 --- a/openslides/mediafiles/__init__.py +++ b/openslides/mediafiles/__init__.py @@ -1 +1 @@ -default_app_config = 'openslides.mediafiles.apps.MediafileAppConfig' +default_app_config = 'openslides.mediafiles.apps.MediafilesAppConfig' diff --git a/openslides/mediafiles/apps.py b/openslides/mediafiles/apps.py index 013eca87a..4d6d46042 100644 --- a/openslides/mediafiles/apps.py +++ b/openslides/mediafiles/apps.py @@ -1,9 +1,12 @@ from django.apps import AppConfig -class MediafileAppConfig(AppConfig): +class MediafilesAppConfig(AppConfig): name = 'openslides.mediafiles' verbose_name = 'OpenSlides Mediafiles' + angular_site_module = True + angular_projector_module = True + js_files = ['js/mediafiles/mediafiles.js'] def ready(self): # Load projector elements. diff --git a/openslides/mediafiles/static/js/mediafiles/mediafiles.js b/openslides/mediafiles/static/js/mediafiles/mediafiles.js index 9c0635d4e..e95ed0b80 100644 --- a/openslides/mediafiles/static/js/mediafiles/mediafiles.js +++ b/openslides/mediafiles/static/js/mediafiles/mediafiles.js @@ -85,3 +85,6 @@ angular.module('OpenSlidesApp.mediafiles.site', ['OpenSlidesApp.mediafiles']) ); }; }); + + +angular.module('OpenSlidesApp.mediafiles.projector', ['OpenSlidesApp.mediafiles']); diff --git a/openslides/motions/__init__.py b/openslides/motions/__init__.py index 9d454b8a0..02cf57e7f 100644 --- a/openslides/motions/__init__.py +++ b/openslides/motions/__init__.py @@ -1 +1 @@ -default_app_config = 'openslides.motions.apps.MotionAppConfig' +default_app_config = 'openslides.motions.apps.MotionsAppConfig' diff --git a/openslides/motions/apps.py b/openslides/motions/apps.py index 07ceb3817..c5c62bd2b 100644 --- a/openslides/motions/apps.py +++ b/openslides/motions/apps.py @@ -2,9 +2,12 @@ from django.apps import AppConfig from django.db.models.signals import post_migrate -class MotionAppConfig(AppConfig): +class MotionsAppConfig(AppConfig): name = 'openslides.motions' verbose_name = 'OpenSlides Motion' + angular_site_module = True + angular_projector_module = True + js_files = ['js/motions/motions.js'] def ready(self): # Load projector elements. diff --git a/openslides/users/apps.py b/openslides/users/apps.py index 84113829f..4181d1927 100644 --- a/openslides/users/apps.py +++ b/openslides/users/apps.py @@ -4,6 +4,9 @@ from django.apps import AppConfig class UsersAppConfig(AppConfig): name = 'openslides.users' verbose_name = 'OpenSlides Users' + angular_site_module = True + angular_projector_module = True + js_files = ['js/users/users.js'] def ready(self): # Load projector elements. diff --git a/requirements.txt b/requirements.txt index 4ac762f66..ee50f3c57 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ -r requirements_production.txt # Requirements for development and tests in alphabetical order -coverage>=4.0a5,<4.1.0 +coverage==4.0a5 flake8 isort