Added CKEditor to custom slide create and edit form.
This commit is contained in:
parent
2417549755
commit
d299579f16
@ -26,6 +26,8 @@
|
|||||||
"font-awesome-bower": "~4.4.0",
|
"font-awesome-bower": "~4.4.0",
|
||||||
"js-data": "~2.8.1",
|
"js-data": "~2.8.1",
|
||||||
"js-data-angular": "~3.1.0",
|
"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
|
// 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.
|
// 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({
|
return gulp.src(mainBowerFiles({
|
||||||
filter: /\.js$/
|
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
|
// 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.
|
// 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({
|
return gulp.src(mainBowerFiles({
|
||||||
filter: /\.css$/
|
filter: /\.css$/
|
||||||
}))
|
}))
|
||||||
@ -61,8 +61,14 @@ gulp.task('fonts-libs', function() {
|
|||||||
.pipe(gulp.dest(path.join(output_directory, 'fonts')));
|
.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 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
|
// Checks JavaScript using JSHint
|
||||||
gulp.task( 'jshint', function() {
|
gulp.task( 'jshint', function () {
|
||||||
return gulp.src([ 'gulpfile.js', path.join( 'openslides', '*', 'static', '**', '*.js' ) ])
|
return gulp.src([ 'gulpfile.js', path.join( 'openslides', '*', 'static', '**', '*.js' ) ])
|
||||||
.pipe(jshint())
|
.pipe(jshint())
|
||||||
.pipe(jshint.reporter('default'));
|
.pipe(jshint.reporter('default'));
|
||||||
|
@ -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
|
// Make sure that the DS factories are loaded by making them a dependency
|
||||||
.run(['Projector', 'Config', 'Tag', 'Customslide', function(Projector, Config, Tag, Customslide){}]);
|
.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.
|
'ngSanitize', // TODO: only use this in functions that need it.
|
||||||
'ui.select',
|
'ui.select',
|
||||||
'xeditable',
|
'xeditable',
|
||||||
|
'ckeditor',
|
||||||
])
|
])
|
||||||
|
|
||||||
// Provider to register entries for the main menu.
|
// Provider to register entries for the main menu.
|
||||||
@ -663,8 +664,14 @@ angular.module('OpenSlidesApp.core.site', [
|
|||||||
Customslide.loadRelations(customslide, 'agenda_item');
|
Customslide.loadRelations(customslide, 'agenda_item');
|
||||||
})
|
})
|
||||||
|
|
||||||
.controller('CustomslideCreateCtrl', function($scope, $state, Customslide) {
|
.controller('CustomslideCreateCtrl', [
|
||||||
|
'$scope',
|
||||||
|
'$state',
|
||||||
|
'CKEditorOptions',
|
||||||
|
'Customslide',
|
||||||
|
function($scope, $state, CKEditorOptions, Customslide) {
|
||||||
$scope.customslide = {};
|
$scope.customslide = {};
|
||||||
|
$scope.CKEditorOptions = CKEditorOptions;
|
||||||
$scope.save = function (customslide) {
|
$scope.save = function (customslide) {
|
||||||
Customslide.create(customslide).then(
|
Customslide.create(customslide).then(
|
||||||
function(success) {
|
function(success) {
|
||||||
@ -672,10 +679,18 @@ angular.module('OpenSlidesApp.core.site', [
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
})
|
}
|
||||||
|
])
|
||||||
|
|
||||||
.controller('CustomslideUpdateCtrl', function($scope, $state, Customslide, customslide) {
|
.controller('CustomslideUpdateCtrl', [
|
||||||
|
'$scope',
|
||||||
|
'$state',
|
||||||
|
'CKEditorOptions',
|
||||||
|
'Customslide',
|
||||||
|
'customslide',
|
||||||
|
function($scope, $state, CKEditorOptions, Customslide, customslide) {
|
||||||
$scope.customslide = customslide;
|
$scope.customslide = customslide;
|
||||||
|
$scope.CKEditorOptions = CKEditorOptions;
|
||||||
$scope.save = function (customslide) {
|
$scope.save = function (customslide) {
|
||||||
Customslide.save(customslide).then(
|
Customslide.save(customslide).then(
|
||||||
function(success) {
|
function(success) {
|
||||||
@ -683,7 +698,8 @@ angular.module('OpenSlidesApp.core.site', [
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
})
|
}
|
||||||
|
])
|
||||||
|
|
||||||
// Tag Controller
|
// Tag Controller
|
||||||
.controller('TagListCtrl', function($scope, Tag) {
|
.controller('TagListCtrl', function($scope, Tag) {
|
||||||
|
@ -14,8 +14,8 @@
|
|||||||
<input type="text" ng-model="customslide.title" class="form-control" name="inputTitle" required>
|
<input type="text" ng-model="customslide.title" class="form-control" name="inputTitle" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="textareaDesciption" translate>Text</label>
|
<label for="customSlideTextCKEditor" translate>Text</label>
|
||||||
<textarea ng-model="customslide.text" class="form-control" name="textareaText" />
|
<div id="customSlideTextCKEditor" ckeditor="CKEditorOptions" ng-model="customslide.text"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="submit" ng-click="save(customslide)" class="btn btn-primary" translate>
|
<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/openslides-libs.css">
|
||||||
<link rel="stylesheet" href="static/css/app.css">
|
<link rel="stylesheet" href="static/css/app.css">
|
||||||
<script src="static/js/openslides-libs.js"></script>
|
<script src="static/js/openslides-libs.js"></script>
|
||||||
|
<script src="static/ckeditor/ckeditor.js"></script>
|
||||||
|
|
||||||
<!-- Navbar -->
|
<!-- Navbar -->
|
||||||
<nav id="header" class="navbar navbar-inverse">
|
<nav id="header" class="navbar navbar-inverse">
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import copy
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from django.utils.translation import ugettext_lazy
|
from django.utils.translation import ugettext_lazy
|
||||||
@ -115,45 +114,6 @@ HAYSTACK_SIGNAL_PROCESSOR = 'openslides.utils.haystack_processor.OpenSlidesProce
|
|||||||
# Adds all automaticly collected plugins
|
# Adds all automaticly collected plugins
|
||||||
INSTALLED_PLUGINS = collect_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
|
# Set this True to use tornado as single wsgi server. Set this False to use
|
||||||
# other webserver like Apache or Nginx as wsgi server.
|
# other webserver like Apache or Nginx as wsgi server.
|
||||||
USE_TORNADO_AS_WSGI_SERVER = True
|
USE_TORNADO_AS_WSGI_SERVER = True
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
from unittest.mock import patch
|
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):
|
class TestConfigVariable(TestCase):
|
||||||
@ -22,3 +23,16 @@ class TestConfigVariable(TestCase):
|
|||||||
'test_default_value',
|
'test_default_value',
|
||||||
"The value of config_variable.data['default_value'] should be the same "
|
"The value of config_variable.data['default_value'] should be the same "
|
||||||
"as set as second argument of ConfigVariable()")
|
"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