Merge pull request #1661 from normanjaeckel/CKEditor
Added CKEditor to custom slide create and edit form.
This commit is contained in:
commit
0cce7f967b
@ -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"
|
||||
}
|
||||
}
|
||||
|
14
gulpfile.js
14
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'));
|
||||
|
@ -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){}]);
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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>
|
||||
|
@ -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">
|
||||
|
@ -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
|
||||
|
@ -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')
|
||||
|
Loading…
Reference in New Issue
Block a user