Added CKEditor to custom slide create and edit form.

This commit is contained in:
Norman Jäckel 2015-10-28 22:16:10 +01:00
parent 2417549755
commit d299579f16
8 changed files with 87 additions and 68 deletions

View File

@ -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"
}
}

View File

@ -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'));

View File

@ -227,6 +227,26 @@ 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; a[!href]; ol ul{list-style}; li; span{color,background-color}; img;',
removePlugins: 'save, print, preview, pagebreak, templates, showblocks, magicline',
// TODO extraPlugins: 'insertpre', // see http://ckeditor.com/addon/insertpre
toolbar: 'Full',
toolbar_Full: [
{'name': 'document', 'items': ['Source', '-', 'Save', 'DocProps', 'Preview', 'Print', '-', 'Templates']},
{'name': 'clipboard', 'items': ['Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo']},
{'name': 'editing', 'items': ['Find', 'Replace', '-', 'SpellChecker', 'Scayt']},
{'name': 'basicstyles', 'items': ['Bold', 'Italic', 'Underline', 'Strike', '-', 'RemoveFormat']},
{'name': 'paragraph', 'items': ['NumberedList', 'BulletedList', '-', 'InsertPre']},
{'name': 'links', 'items': ['Link', 'Unlink']},
{'name': 'styles', 'items': ['Format', 'TextColor', 'BGColor']},
{'name': 'tools', 'items': ['Maximize', 'ShowBlocks', '-', 'About']},
{'name': 'images', 'items': ['Image']}
]
})
// Make sure that the DS factories are loaded by making them a dependency
.run(['Projector', 'Config', 'Tag', 'Customslide', function(Projector, Config, Tag, Customslide){}]);

View File

@ -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) {

View File

@ -14,8 +14,8 @@
<input type="text" ng-model="customslide.title" class="form-control" name="inputTitle" required>
</div>
<div class="form-group">
<label for="textareaDesciption" translate>Text</label>
<textarea ng-model="customslide.text" class="form-control" name="textareaText" />
<label for="customSlideTextCKEditor" translate>Text</label>
<div id="customSlideTextCKEditor" ckeditor="CKEditorOptions" ng-model="customslide.text"></div>
</div>
<button type="submit" ng-click="save(customslide)" class="btn btn-primary" translate>

View File

@ -9,6 +9,7 @@
<link rel="stylesheet" href="static/css/openslides-libs.css">
<link rel="stylesheet" href="static/css/app.css">
<script src="static/js/openslides-libs.js"></script>
<script src="static/ckeditor/ckeditor.js"></script>
<!-- Navbar -->
<nav id="header" class="navbar navbar-inverse">

View File

@ -1,4 +1,3 @@
import copy
import os
from django.utils.translation import ugettext_lazy
@ -115,45 +114,6 @@ HAYSTACK_SIGNAL_PROCESSOR = 'openslides.utils.haystack_processor.OpenSlidesProce
# Adds all automaticly collected plugins
INSTALLED_PLUGINS = collect_plugins()
# CKeditor settings
CKEDITOR_DEFAULT_CONFIG = {'toolbar': 'Full',
'bodyClass': 'ckeditor_html',
'allowedContent':
'h1 h2 h3 pre b i u strike em; '
# A workaround for the problem described in http://dev.ckeditor.com/ticket/10192
# Hopefully, the problem will be solved in the final version of CKEditor 4.1
# If so, then {margin-left} can be removed
'p{margin-left}; '
'a[!href]; '
'ol ul{list-style}; '
'li; '
'pre; '
'span{color,background-color}; ',
'removePlugins': 'save, print, preview, pagebreak, templates, showblocks, magicline',
'extraPlugins': 'insertpre', # see http://ckeditor.com/addon/insertpre
'toolbar_Full': [
{'name': 'document', 'items': ['Source', '-', 'Save', 'DocProps', 'Preview', 'Print', '-', 'Templates']},
{'name': 'clipboard', 'items': ['Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo']},
{'name': 'editing', 'items': ['Find', 'Replace', '-', 'SpellChecker', 'Scayt']},
{'name': 'basicstyles', 'items': ['Bold', 'Italic', 'Underline', 'Strike', '-', 'RemoveFormat']},
{'name': 'paragraph', 'items': ['NumberedList', 'BulletedList', '-', 'InsertPre']},
{'name': 'links', 'items': ['Link', 'Unlink']},
{'name': 'styles', 'items': ['Format', 'TextColor', 'BGColor']},
{'name': 'tools', 'items': ['Maximize', 'ShowBlocks', '-', 'About']}
]}
CKEDITOR_IMG_CONFIG = copy.deepcopy(CKEDITOR_DEFAULT_CONFIG)
CKEDITOR_IMG_CONFIG['allowedContent'] += 'img; '
CKEDITOR_IMG_CONFIG['toolbar_Full'].append({'name': 'images', 'items': ['Image']})
CKEDITOR_UPLOAD_PATH = 'ckeditor'
CKEDITOR_CONFIGS = {
'default': CKEDITOR_DEFAULT_CONFIG,
'images': CKEDITOR_IMG_CONFIG,
}
# Set this True to use tornado as single wsgi server. Set this False to use
# other webserver like Apache or Nginx as wsgi server.
USE_TORNADO_AS_WSGI_SERVER = True

View File

@ -1,7 +1,8 @@
from unittest import TestCase
from unittest.mock import patch
from openslides.core.config import ConfigVariable
from openslides.core.config import ConfigHandler, ConfigVariable, config
from openslides.core.exceptions import ConfigNotFound
class TestConfigVariable(TestCase):
@ -22,3 +23,16 @@ class TestConfigVariable(TestCase):
'test_default_value',
"The value of config_variable.data['default_value'] should be the same "
"as set as second argument of ConfigVariable()")
class TestConfigHandler(TestCase):
def test_get_from_cache(self):
ConfigHandler._cache = {'key_eeshah4Sho6zailee4ko': 'value_chies7aCohZoo9umieph'}
self.assertEqual(config['key_eeshah4Sho6zailee4ko'], 'value_chies7aCohZoo9umieph')
def test_get_not_found(self):
ConfigHandler._cache = {}
self.assertRaises(
ConfigNotFound,
config.__getitem__,
'key_leehah4Sho4ee7aCohbn')