diff --git a/gulpfile.js b/gulpfile.js index 2c91e09a0..9a7240997 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,4 +1,4 @@ -/*! +/** * Gulp tasks for development and production. * * Run @@ -17,6 +17,7 @@ var argv = require('yargs').argv, concat = require('gulp-concat'), gulpif = require('gulp-if'), gettext = require('gulp-angular-gettext'), + jshint = require('gulp-jshint'), mainBowerFiles = require('main-bower-files'), minifyCSS = require('gulp-minify-css'), path = require('path'), @@ -25,9 +26,14 @@ var argv = require('yargs').argv, // Directory where the results go var output_directory = path.join('openslides', 'static'); + +/** + * Default tasks to be run before start. + */ + // Catches all JavaScript files from all bower components and concats them to // one file js/openslides-libs.js. In production mode the file is uglified. -gulp.task('js', function() { +gulp.task('js-libs', function() { return gulp.src(mainBowerFiles({ filter: /\.js$/ })) @@ -38,7 +44,7 @@ gulp.task('js', function() { // Catches all CSS files from all bower components and concats them to one file // css/openslides-libs.css. In production mode the file is uglified. -gulp.task('css', function() { +gulp.task('css-libs', function() { return gulp.src(mainBowerFiles({ filter: /\.css$/ })) @@ -48,13 +54,22 @@ gulp.task('css', function() { }); // Catches all font files from all bower components. -gulp.task('fonts', function() { +gulp.task('fonts-libs', function() { return gulp.src(mainBowerFiles({ filter: /\.(eot)|(svg)|(ttf)|(woff)|(woff2)$/ })) .pipe(gulp.dest(path.join(output_directory, 'fonts'))); }); +// Gulp default task. Runs all other tasks before. +gulp.task('default', ['js-libs', 'css-libs', 'fonts-libs'], function() {}); + + +/** + * Extra tasks that have to be called manually. Useful for development and + * packageing. + */ + // Extracts translatable strings using angular-gettext and saves them in file // openslides/locale/angular-gettext/template-en.pot. gulp.task('pot', function () { @@ -74,5 +89,9 @@ gulp.task('translations', function () { .pipe(gulp.dest(path.join(output_directory, 'i18n'))); }); -// Gulp default task. Runs all other tasks before. -gulp.task('default', ['js', 'css', 'fonts'], function() {}); +// Checks JavaScript using JSHint +gulp.task( 'jshint', function() { + return gulp.src([ 'gulpfile.js', path.join( 'openslides', '*', 'static', '**', '*.js' ) ]) + .pipe(jshint()) + .pipe(jshint.reporter('default')); +}); diff --git a/openslides/core/views.py b/openslides/core/views.py index 5fc10bdc8..c79207944 100644 --- a/openslides/core/views.py +++ b/openslides/core/views.py @@ -58,7 +58,12 @@ class IndexView(utils_views.CSRFMixin, utils_views.View): class ProjectorView(utils_views.View): """ - Access the projector. + The primary view for OpenSlides projector using AngularJS. + + The default base template is 'openslides/core/static/templates/projector.html'. + You can override it by simply adding a custom 'templates/projector.html' + file to the custom staticfiles directory. See STATICFILES_DIRS in + settings.py. """ def get(self, *args, **kwargs): diff --git a/openslides/users/apps.py b/openslides/users/apps.py index 1aac71ca0..3b36eda7e 100644 --- a/openslides/users/apps.py +++ b/openslides/users/apps.py @@ -6,7 +6,7 @@ class UsersAppConfig(AppConfig): verbose_name = 'OpenSlides Users' angular_site_module = True angular_projector_module = True - js_files = ['js/users/users.js'] + js_files = ['js/users/base.js', 'js/users/site.js', 'js/users/projector.js'] def ready(self): # Load projector elements. diff --git a/openslides/users/static/js/users/base.js b/openslides/users/static/js/users/base.js new file mode 100644 index 000000000..0fea9bfb7 --- /dev/null +++ b/openslides/users/static/js/users/base.js @@ -0,0 +1,79 @@ +(function () { + +'use strict'; + +angular.module('OpenSlidesApp.users', []) + +.factory('User', ['DS', 'Group', 'jsDataModel', function(DS, Group, jsDataModel) { + var name = 'users/user'; + return DS.defineResource({ + name: name, + useClass: jsDataModel, + methods: { + getResourceName: function () { + return name; + }, + get_short_name: function() { + // should be the same as in the python user model. + var firstName = _.trim(this.first_name), + lastName = _.trim(this.last_name), + name; + + if (firstName && lastName) { + // TODO: check config + name = [firstName, lastName].join(' '); + } else { + name = firstName || lastName || this.username; + } + return name; + }, + get_full_name: function() { + // should be the same as in the python user model. + var firstName = _.trim(this.first_name), + lastName = _.trim(this.last_name), + structure_level = _.trim(this.structure_level), + name; + + if (firstName && lastName) { + // TODO: check config + name = [firstName, lastName].join(' '); + } else { + name = firstName || lastName || this.username; + } + if (structure_level) { + name = name + " (" + structure_level + ")"; + } + return name; + }, + getPerms: function() { + var allPerms = []; + var allGroups = this.groups; + // Add registered group + allGroups.push(2); + _.forEach(allGroups, function(groupId) { + // Get group from server + Group.find(groupId); + // But do not work with the returned promise, because in + // this case this method can not be called in $watch + var group = Group.get(groupId); + if (group) { + _.forEach(group.permissions, function(perm) { + allPerms.push(perm); + }); + } + }); + return _.uniq(allPerms); + }, + }, + }); +}]) + +.factory('Group', ['DS', function(DS) { + return DS.defineResource({ + name: 'users/group', + }); +}]) + +.run(['User', 'Group', function(User, Group) {}]); + +}()); diff --git a/openslides/users/static/js/users/projector.js b/openslides/users/static/js/users/projector.js new file mode 100644 index 000000000..c375c0259 --- /dev/null +++ b/openslides/users/static/js/users/projector.js @@ -0,0 +1,22 @@ +(function () { + +'use strict'; + +angular.module('OpenSlidesApp.users.projector', ['OpenSlidesApp.users']) + +.config(function(slidesProvider) { + slidesProvider.registerSlide('users/user', { + template: 'static/templates/users/slide_user.html', + }); +}) + +.controller('SlideUserCtrl', function($scope, User) { + // Attention! Each object that is used here has to be dealt on server side. + // Add it to the coresponding get_requirements method of the ProjectorElement + // class. + var id = $scope.element.id; + User.find(id); + User.bindOne(id, $scope, 'user'); +}); + +}()); diff --git a/openslides/users/static/js/users/users.js b/openslides/users/static/js/users/site.js similarity index 82% rename from openslides/users/static/js/users/users.js rename to openslides/users/static/js/users/site.js index 6e1363668..686509415 100644 --- a/openslides/users/static/js/users/users.js +++ b/openslides/users/static/js/users/site.js @@ -1,79 +1,6 @@ -"use strict"; - -angular.module('OpenSlidesApp.users', []) - -.factory('User', ['DS', 'Group', 'jsDataModel', function(DS, Group, jsDataModel) { - var name = 'users/user' - return DS.defineResource({ - name: name, - useClass: jsDataModel, - methods: { - getResourceName: function () { - return name; - }, - get_short_name: function() { - // should be the same as in the python user model. - var firstName = _.trim(this.first_name), - lastName = _.trim(this.last_name), - name; - - if (firstName && lastName) { - // TODO: check config - name = [firstName, lastName].join(' '); - } else { - name = firstName || lastName || this.username; - } - return name; - }, - get_full_name: function() { - // should be the same as in the python user model. - var firstName = _.trim(this.first_name), - lastName = _.trim(this.last_name), - structure_level = _.trim(this.structure_level), - name; - - if (firstName && lastName) { - // TODO: check config - name = [firstName, lastName].join(' '); - } else { - name = firstName || lastName || this.username; - } - if (structure_level) { - name = name + " (" + structure_level + ")"; - } - return name; - }, - getPerms: function() { - var allPerms = []; - var allGroups = this.groups; - // Add registered group - allGroups.push(2); - _.forEach(allGroups, function(groupId) { - // Get group from server - Group.find(groupId); - // But do not work with the returned promise, because in - // this case this method can not be called in $watch - var group = Group.get(groupId); - if (group) { - _.forEach(group.permissions, function(perm) { - allPerms.push(perm); - }); - } - }); - return _.uniq(allPerms); - }, - }, - }); -}]) - -.factory('Group', ['DS', function(DS) { - return DS.defineResource({ - name: 'users/group', - }); -}]) - -.run(['User', 'Group', function(User, Group) {}]); +(function () { +'use strict'; angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users']) @@ -162,7 +89,7 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users']) .state('users.group.create', { resolve: { permissions: function($http) { - return $http({ 'method': 'OPTIONS', 'url': '/rest/users/group/' }) + return $http({ 'method': 'OPTIONS', 'url': '/rest/users/group/' }); } } }) @@ -179,7 +106,7 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users']) }, resolve: { permissions: function($http) { - return $http({ 'method': 'OPTIONS', 'url': '/rest/users/group/' }) + return $http({ 'method': 'OPTIONS', 'url': '/rest/users/group/' }); } } }); @@ -229,7 +156,7 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users']) } return _.intersection(perms, operator.perms).length > 0; }, - } + }; return operator; } ]) @@ -260,7 +187,7 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users']) link: function($scope, $element, $attr, ctrl, $transclude) { var block, childScope, previousElements, perms; if ($attr.osPerms[0] === '!') { - perms = _.trimLeft($attr.osPerms, '!') + perms = _.trimLeft($attr.osPerms, '!'); } else { perms = $attr.osPerms; } @@ -325,7 +252,7 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users']) link: function(scope, element, $attr) { var perms; if ($attr.osPermsLite[0] === '!') { - perms = _.trimLeft($attr.osPermsLite, '!') + perms = _.trimLeft($attr.osPermsLite, '!'); } else { perms = $attr.osPermsLite; } @@ -346,7 +273,7 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users']) } ); } - } + }; } ]) @@ -481,7 +408,7 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users']) } ); }); - } + }; // import from csv file $scope.csv = { @@ -503,7 +430,7 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users']) user.last_name = obj[i].last_name; user.structure_level = obj[i].structure_level; user.groups = []; - if (obj[i].groups != '') { + if (obj[i].groups !== '') { var groups = obj[i].groups.replace('"','').split(","); groups.forEach(function(group) { user.groups.push(group); @@ -518,7 +445,7 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users']) ); } $scope.csvimported = true; - } + }; $scope.clear = function () { $scope.csv.result = null; @@ -574,24 +501,6 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users']) }; }); - -angular.module('OpenSlidesApp.users.projector', ['OpenSlidesApp.users']) - -.config(function(slidesProvider) { - slidesProvider.registerSlide('users/user', { - template: 'static/templates/users/slide_user.html', - }); -}) - -.controller('SlideUserCtrl', function($scope, User) { - // Attention! Each object that is used here has to be dealt on server side. - // Add it to the coresponding get_requirements method of the ProjectorElement - // class. - var id = $scope.element.id; - User.find(id); - User.bindOne(id, $scope, 'user'); -}); - // this is code from angular.js. Find a way to call this function from this file function getBlockNodes(nodes) { // TODO(perf): just check if all items in `nodes` are siblings and if they are return the original @@ -608,3 +517,5 @@ function getBlockNodes(nodes) { return $(blockNodes); } + +}()); diff --git a/openslides/utils/autoupdate.py b/openslides/utils/autoupdate.py index 3bb33c2b5..2992ea3b1 100644 --- a/openslides/utils/autoupdate.py +++ b/openslides/utils/autoupdate.py @@ -136,7 +136,7 @@ def run_tornado(addr, port, *args, **kwargs): # Collect urls sock_js_router = SockJSRouter(OpenSlidesSockJSConnection, '/sockjs') other_urls = [ - (r"%s(.*)" % settings.STATIC_URL, DjangoStaticFileHandler), + (r'%s(.*)' % settings.STATIC_URL, DjangoStaticFileHandler), (r'%s(.*)' % settings.MEDIA_URL, StaticFileHandler, {'path': settings.MEDIA_ROOT}), ('.*', FallbackHandler, dict(fallback=app))] diff --git a/package.json b/package.json index c66ca6872..01954f55b 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "gulp-uglify": "~1.0.2", "main-bower-files": "~2.4.1", "yargs": "~1.3.3", - "po2json": "~0.3.2" + "po2json": "~0.3.2", + "gulp-jshint": "~1.11.2" } }