diff --git a/bower.json b/bower.json index eb398b69a..c0e9df018 100644 --- a/bower.json +++ b/bower.json @@ -26,6 +26,8 @@ "font-awesome-bower": "~4.4.0", "js-data": "~2.8.1", "js-data-angular": "~3.1.0", - "ng-file-upload": "~9.1.2" + "ng-file-upload": "~9.1.2", + "ckeditor": "~4.5.4", + "angular-ckeditor": "~1.0.0" } } diff --git a/gulpfile.js b/gulpfile.js index 9a7240997..dc836ba95 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -33,7 +33,7 @@ var output_directory = path.join('openslides', 'static'); // 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-libs', function() { +gulp.task('js-libs', function () { return gulp.src(mainBowerFiles({ filter: /\.js$/ })) @@ -44,7 +44,7 @@ gulp.task('js-libs', 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-libs', function() { +gulp.task('css-libs', function () { return gulp.src(mainBowerFiles({ filter: /\.css$/ })) @@ -61,8 +61,14 @@ gulp.task('fonts-libs', function() { .pipe(gulp.dest(path.join(output_directory, 'fonts'))); }); +// Extra task only for CKEditor +gulp.task('ckeditor', function () { + return gulp.src(path.join('bower_components', 'ckeditor', '**')) + .pipe(gulp.dest(path.join(output_directory, 'ckeditor'))); +}); + // Gulp default task. Runs all other tasks before. -gulp.task('default', ['js-libs', 'css-libs', 'fonts-libs'], function() {}); +gulp.task('default', ['js-libs', 'css-libs', 'fonts-libs', 'ckeditor'], function () {}); /** @@ -90,7 +96,7 @@ gulp.task('translations', function () { }); // Checks JavaScript using JSHint -gulp.task( 'jshint', function() { +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/static/js/core/base.js b/openslides/core/static/js/core/base.js index 5c1053d36..d8ebf59db 100644 --- a/openslides/core/static/js/core/base.js +++ b/openslides/core/static/js/core/base.js @@ -227,6 +227,36 @@ angular.module('OpenSlidesApp.core', [ }; } ]) + +/* Options for CKEditor used in various create and edit views. */ +.value('CKEditorOptions', { + allowedContent: + 'h1 h2 h3 p pre b i u strike strong em blockquote;' + + 'a[!href];' + + 'img[!src,alt]{width,height,float};' + + 'table tr th td caption;' + + 'li ol ul{list-style};' + + 'span{color,background-color};', + extraPlugins: 'colorbutton', + toolbarGroups: [ + { name: 'clipboard', groups: [ 'clipboard', 'undo' ] }, + { name: 'editing', groups: [ 'find', 'selection', 'spellchecker', 'editing' ] }, + { name: 'forms', groups: [ 'forms' ] }, + { name: 'tools', groups: [ 'tools' ] }, + { name: 'about', groups: [ 'about' ] }, + { name: 'document', groups: [ 'mode', 'document', 'doctools' ] }, + { name: 'others', groups: [ 'others' ] }, + '/', + { name: 'styles', groups: [ 'styles' ] }, + { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] }, + { name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi', 'paragraph' ] }, + { name: 'links', groups: [ 'links' ] }, + { name: 'insert', groups: [ 'insert' ] }, + { name: 'colors', groups: [ 'colors' ] } + ], + removeButtons: 'Anchor,SpecialChar,Subscript,Superscript,Styles,RemoveFormat,HorizontalRule' +}) + // Make sure that the DS factories are loaded by making them a dependency .run(['Projector', 'Config', 'Tag', 'Customslide', function(Projector, Config, Tag, Customslide){}]); diff --git a/openslides/core/static/js/core/site.js b/openslides/core/static/js/core/site.js index 30a5f6ebb..5946bd4bd 100644 --- a/openslides/core/static/js/core/site.js +++ b/openslides/core/static/js/core/site.js @@ -14,6 +14,7 @@ angular.module('OpenSlidesApp.core.site', [ 'ngSanitize', // TODO: only use this in functions that need it. 'ui.select', 'xeditable', + 'ckeditor', ]) // Provider to register entries for the main menu. @@ -663,27 +664,42 @@ angular.module('OpenSlidesApp.core.site', [ Customslide.loadRelations(customslide, 'agenda_item'); }) -.controller('CustomslideCreateCtrl', function($scope, $state, Customslide) { - $scope.customslide = {}; - $scope.save = function (customslide) { - Customslide.create(customslide).then( - function(success) { - $state.go('core.customslide.list'); - } - ); - }; -}) +.controller('CustomslideCreateCtrl', [ + '$scope', + '$state', + 'CKEditorOptions', + 'Customslide', + function($scope, $state, CKEditorOptions, Customslide) { + $scope.customslide = {}; + $scope.CKEditorOptions = CKEditorOptions; + $scope.save = function (customslide) { + Customslide.create(customslide).then( + function(success) { + $state.go('core.customslide.list'); + } + ); + }; + } +]) -.controller('CustomslideUpdateCtrl', function($scope, $state, Customslide, customslide) { - $scope.customslide = customslide; - $scope.save = function (customslide) { - Customslide.save(customslide).then( - function(success) { - $state.go('core.customslide.list'); - } - ); - }; -}) +.controller('CustomslideUpdateCtrl', [ + '$scope', + '$state', + 'CKEditorOptions', + 'Customslide', + 'customslide', + function($scope, $state, CKEditorOptions, Customslide, customslide) { + $scope.customslide = customslide; + $scope.CKEditorOptions = CKEditorOptions; + $scope.save = function (customslide) { + Customslide.save(customslide).then( + function(success) { + $state.go('core.customslide.list'); + } + ); + }; + } +]) // Tag Controller .controller('TagListCtrl', function($scope, Tag) { diff --git a/openslides/core/static/templates/core/customslide-form.html b/openslides/core/static/templates/core/customslide-form.html index 13b0050da..26dcfee16 100644 --- a/openslides/core/static/templates/core/customslide-form.html +++ b/openslides/core/static/templates/core/customslide-form.html @@ -14,8 +14,8 @@