Merge branch 'develop' into static-pages-support

This commit is contained in:
alekseybobkov 2014-10-05 22:46:08 -07:00
commit 799af7a3b3
34 changed files with 11091 additions and 10392 deletions

View File

@ -1,5 +1,6 @@
* **Build 15x** (2014-09-xx)
- Moved `ViewMaker` trait to live under system, it can be useful for Models too.
* **Build 15x** (2014-10-xx)
- Plugins are now updated in order of their dependency definitions.
- Moved `ViewMaker` trait now lives under system, it can be useful for Models too.
* **Build 149** (2014-09-29)
- Added new `hint` form field type (see Backend > Forms docs).

View File

@ -572,6 +572,20 @@ class FormController extends ControllerBehavior
*/
public function formExtendQuery($query) {}
/**
* Static helper for extending form fields.
* @param callable $callback
* @return void
*/
public static function extendFormFields($callback)
{
$calledClass = self::getCalledExtensionClass();
Event::listen('backend.form.extendFields', function($widget) use ($calledClass, $callback) {
if (!is_a($widget->getController(), $calledClass)) return;
$callback($widget, $widget->model, $widget->getContext());
});
}
//
// Internals
//

View File

@ -313,4 +313,18 @@ class ListController extends ControllerBehavior
*/
public function listOverrideHeaderValue($columnName, $definition = null) {}
/**
* Static helper for extending form fields.
* @param callable $callback
* @return void
*/
public static function extendListColumns($callback)
{
$calledClass = self::getCalledExtensionClass();
Event::listen('backend.list.extendColumns', function($widget) use ($calledClass, $callback) {
if (!is_a($widget->getController(), $calledClass)) return;
$callback($widget, $widget->model, $widget->getContext());
});
}
}

View File

@ -9,7 +9,7 @@ use BackendAuth;
use Backend\Models\User;
use Backend\Models\AccessLog;
use Backend\Classes\Controller;
use System\Classes\VersionManager;
use System\Classes\UpdateManager;
use System\Classes\ApplicationException;
use October\Rain\Support\ValidationException;
use Exception;
@ -75,7 +75,7 @@ class Auth extends Controller
], true);
// Load version updates
VersionManager::instance()->updateAll();
UpdateManager::instance()->update();
// Log the sign in event
AccessLog::add($user);

View File

@ -26,9 +26,11 @@
}
window.RedactorPlugins.cleanup = {
init: function () {
this.cleanup = new Cleanup(this)
window.RedactorPlugins.cleanup = function() {
return {
init: function () {
this.cleanup = new Cleanup(this)
}
}
}

View File

@ -32,7 +32,7 @@
*/
this.redactor.$editor.on('click', 'figcaption:empty, cite:empty', $.proxy(function (event) {
$(event.target).prepend('<br />')
this.redactor.selectionEnd(event.target)
this.redactor.caret.setEnd(event.target)
event.stopPropagation()
}, this))
@ -47,7 +47,7 @@
* Prevent user from removing captions or citations with delete/backspace keys
*/
this.redactor.$editor.on('keydown', $.proxy(function (event) {
var current = this.redactor.getCurrent(),
var current = this.redactor.selection.getCurrent(),
isEmpty = !current.length,
isCaptionNode = !!$(current).closest('figcaption, cite').length,
isDeleteKey = $.inArray(event.keyCode, [this.redactor.keyCode.BACKSPACE, this.redactor.keyCode.DELETE]) >= 0
@ -71,14 +71,14 @@
}).remove()
if (this.redactor.opts.visual) {
this.redactor.sync()
this.redactor.code.sync()
}
},
showToolbar: function (event) {
var $figure = $(event.currentTarget),
type = $figure.data('type') || 'default',
$toolbar = this.getToolbar(type).data('figure', $figure).prependTo($figure)
$toolbar = this.getToolbar(type).data('figure', $figure).prependTo($figure).show()
if (this.redactor[type] && this.redactor[type].onShow) {
this.redactor[type].onShow($figure, $toolbar)
@ -86,7 +86,7 @@
},
hideToolbar: function (event) {
$(event.currentTarget).find('.oc-figure-controls').appendTo(this.redactor.$box)
$(event.currentTarget).find('.oc-figure-controls').appendTo(this.redactor.$box).hide()
},
observeToolbars: function () {
@ -94,9 +94,9 @@
/*
* Before clicking a command, make sure we save the current node within the editor
*/
this.redactor.$editor.on('mousedown', '.oc-figure-controls', $.proxy(function () {
this.redactor.$editor.on('mousedown', '.oc-figure-controls', $.proxy(function (event) {
event.preventDefault()
this.current = this.redactor.getCurrent()
this.current = this.redactor.selection.getCurrent()
}, this))
this.redactor.$editor.on('click', '.oc-figure-controls span, .oc-figure-controls a', $.proxy(function (event) {
@ -116,7 +116,7 @@
/*
* Mobile
*/
if (this.redactor.isMobile()) {
if (this.redactor.utils.isMobile()) {
/*
* If $editor is focused, click doesn't seem to fire
@ -244,7 +244,7 @@
/*
* Maintain undo history
*/
this.redactor.bufferSet(this.redactor.$editor.html())
this.redactor.buffer.set(this.redactor.$editor.html())
/*
* Shared functions
@ -269,7 +269,7 @@
break
}
this.redactor.sync()
this.redactor.code.sync()
},
@ -279,21 +279,28 @@
/*
* Node at cursor
*/
var currentNode = redactor.getBlock()
var currentNode = redactor.selection.getBlock()
/*
* Delete key
*/
if (event.keyCode === 8 && !redactor.getCaretOffset(currentNode) && currentNode.previousSibling && currentNode.previousSibling.nodeName === 'FIGURE') {
if (
event.keyCode === 8
&& !redactor.caret.getOffset(currentNode)
&& currentNode.previousSibling
&& currentNode.previousSibling.nodeName === 'FIGURE'
) {
event.preventDefault()
}
})
}
}
window.RedactorPlugins.figure = {
init: function () {
this.figure = new Figure(this)
window.RedactorPlugins.figure = function() {
return {
init: function () {
this.figure = new Figure(this)
}
}
}

View File

@ -3,182 +3,127 @@
window.RedactorPlugins = window.RedactorPlugins || {};
window.RedactorPlugins.fullscreen = {
window.RedactorPlugins.fullscreen = function() {
return {
init: function() {
init: function() {
this.fullscreen.isOpen = false
this.fullscreen = false
var button = this.button.add('fullscreen', 'FullScreen')
this.button.addCallback(button, $.proxy(this.fullscreen.toggle, this))
button.addClass('redactor_btn_fullscreen').removeClass('redactor-btn-image')
button.parent().addClass('redactor-btn-right')
this.buttonAdd('fullscreen', 'Fullscreen', $.proxy(this.toggleFullscreen, this))
this.buttonGet('fullscreen').addClass('redactor_btn_fullscreen').removeClass('redactor-btn-image')
this.buttonGet('fullscreen').parent().addClass('redactor_btn_right')
if (this.opts.fullscreen)
this.fullscreen.toggle()
},
if (this.opts.fullscreen)
this.toggleFullscreen()
toggle: function() {
if (!this.fullscreen.isOpen)
this.fullscreen.enable()
else
this.fullscreen.disable()
},
},
enable: function() {
this.button.changeIcon('fullscreen', 'normalscreen')
this.button.setActive('fullscreen')
this.fullscreen.isOpen = true
toggleFullscreen: function() {
if (!this.fullscreen)
this.enableFullScreen()
else
this.disableFullScreen()
},
if (this.opts.toolbarExternal) {
this.fullscreen.toolcss = {}
this.fullscreen.boxcss = {}
this.fullscreen.toolcss.width = this.$toolbar.css('width')
this.fullscreen.toolcss.top = this.$toolbar.css('top')
this.fullscreen.toolcss.position = this.$toolbar.css('position')
this.fullscreen.boxcss.top = this.$box.css('top')
}
enableFullScreen: function() {
var html
this.fullscreen.height = this.$editor.height()
this.buttonChangeIcon('fullscreen', 'normalscreen')
this.buttonActive('fullscreen')
this.fullscreen = true
if (this.opts.maxHeight) this.$editor.css('max-height', '')
if (this.opts.minHeight) this.$editor.css('min-height', '')
if (this.opts.toolbarExternal) {
this.toolcss = {}
this.boxcss = {}
this.toolcss.width = this.$toolbar.css('width')
this.toolcss.top = this.$toolbar.css('top')
this.toolcss.position = this.$toolbar.css('position')
this.boxcss.top = this.$box.css('top')
if (!this.$fullscreenPlaceholder) this.$fullscreenPlaceholder = $('<div/>')
this.$fullscreenPlaceholder.insertAfter(this.$box)
this.$box.appendTo(document.body)
this.$box.addClass('redactor-box-fullscreen')
$('body, html').css('overflow', 'hidden')
this.fullscreen.resize()
$(window).on('resize.redactor.fullscreen', $.proxy(this.fullscreen.resize, this))
$(document).scrollTop(0, 0)
this.$editor.focus()
this.observe.load()
},
disable: function() {
this.button.removeIcon('fullscreen', 'normalscreen')
this.button.setInactive('fullscreen')
this.fullscreen.isOpen = false
$(window).off('resize.redactor.fullscreen')
$('body, html').css('overflow', '')
this.$box.insertBefore(this.$fullscreenPlaceholder)
this.$fullscreenPlaceholder.remove()
this.$box.removeClass('redactor-box-fullscreen').css({ width: 'auto', height: 'auto' })
this.code.sync()
if (this.opts.toolbarExternal) {
this.$box.css('top', this.fullscreen.boxcss.top)
this.$toolbar.css({
'width': this.fullscreen.toolcss.width,
'top': this.fullscreen.toolcss.top,
'position': this.fullscreen.toolcss.position
})
}
if (this.opts.minHeight) this.$editor.css('minHeight', this.opts.minHeight)
if (this.opts.maxHeight) this.$editor.css('maxHeight', this.opts.maxHeight)
this.$editor.css('height', 'auto')
this.$editor.focus()
this.observe.load()
},
resize: function() {
if (!this.fullscreen.isOpen)
return false
var pad = this.$editor.css('padding-top').replace('px', '')
var toolbarHeight = this.$toolbar.height(),
height = $(window).height() - toolbarHeight
this.$box.width($(window).width() - 2).height(height + toolbarHeight)
if (this.opts.toolbarExternal) {
this.$toolbar.css({
top: '0px',
position: 'absolute',
width: '100%'
})
this.$box.css('top', toolbarHeight + 'px')
}
// if (!this.opts.iframe) {
// this.$editor.height(height - (pad * 2))
// }
// else {
// setTimeout($.proxy(function() {
// this.$frame.height(height)
// }, this), 1)
// }
// this.$editor.height(height)
}
this.fsheight = this.$editor.height()
if (this.opts.iframe)
this.fsheight = this.$frame.height()
if (this.opts.maxHeight)
this.$editor.css('max-height', '')
if (this.opts.iframe)
html = this.get()
if (!this.$fullscreenPlaceholder)
this.$fullscreenPlaceholder = $('<div/>')
this.$fullscreenPlaceholder.insertAfter(this.$box)
this.$box.appendTo(document.body)
this.$box.addClass('redactor_box_fullscreen')
$('body, html').css('overflow', 'hidden')
if (this.opts.iframe)
this.fullscreenIframe(html)
this.fullScreenResize()
$(window).resize($.proxy(this.fullScreenResize, this))
$(document).scrollTop(0, 0)
this.focus()
this.observeStart()
},
disableFullScreen: function() {
var height
this.buttonRemoveIcon('fullscreen', 'normalscreen')
this.buttonInactive('fullscreen')
this.fullscreen = false
$(window).off('resize', $.proxy(this.fullScreenResize, this))
$('body, html').css('overflow', '')
this.$box.insertBefore(this.$fullscreenPlaceholder)
this.$fullscreenPlaceholder.remove()
this.$box.removeClass('redactor_box_fullscreen').css({ width: 'auto', height: 'auto' })
if (this.opts.iframe)
html = this.$editor.html()
if (this.opts.iframe)
this.fullscreenIframe(html)
else
this.sync()
height = this.fsheight
if (this.opts.autoresize)
height = 'auto'
if (this.opts.maxHeight)
this.$editor.css('max-height', this.opts.maxHeight)
if (this.opts.toolbarExternal) {
this.$box.css('top', this.boxcss.top)
this.$toolbar.css({
width: this.toolcss.width,
top: this.toolcss.top,
position: this.toolcss.position
})
}
if (!this.opts.iframe)
this.$editor.css('height', height)
else
this.$frame.css('height', height)
this.$editor.css('height', height)
this.focus()
this.observeStart()
},
fullscreenIframe: function(html) {
this.$editor = this.$frame.contents().find('body')
this.$editor.attr({
contenteditable: true,
dir: this.opts.direction
});
// Set document & window
if (this.$editor.get(0)) {
this.document = this.$editor.get(0).ownerDocument
this.window = this.document.defaultView || window
}
// Iframe css
this.iframeAddCss()
if (this.opts.fullpage)
this.setFullpageOnInit(html)
else
this.set(html)
if (this.opts.wym)
this.$editor.addClass('redactor_editor_wym')
},
fullScreenResize: function() {
if (!this.fullscreen)
return false
var pad = this.$editor.css('padding-top').replace('px', '')
var toolbarHeight = this.$toolbar.height(),
height = $(window).height() - toolbarHeight
this.$box.width($(window).width() - 2).height(height + toolbarHeight)
if (this.opts.toolbarExternal) {
this.$toolbar.css({
top: '0px',
position: 'absolute',
width: '100%'
})
this.$box.css('top', toolbarHeight + 'px')
}
// if (!this.opts.iframe) {
// this.$editor.height(height - (pad * 2))
// }
// else {
// setTimeout($.proxy(function() {
// this.$frame.height(height)
// }, this), 1)
// }
// this.$editor.height(height)
}
};
}
}(jQuery));

View File

@ -114,71 +114,73 @@
}
}
window.RedactorPlugins.image = {
init: function () {
this.image = new Image(this)
window.RedactorPlugins.image = function() {
return {
init: function () {
this.image = new Image(this)
// This is a work in progress
this.buttonAddBefore('video', 'image', 'Image', $.proxy(function () {
// This is a work in progress
var button = this.button.addBefore('video', 'image', 'Image')
this.button.addCallback(button, $.proxy(function () {
/*
* Maintain undo history
*/
this.buffer.set()
/*
* Remember the cursor pos
*/
var cursor = this.selection.getBlock() || this.selection.getCurrent()
/*
* Display the image upload modal
*/
/*
* Add button
*/
var url = 'http://placehold.it/100x100'
var data = '<figure data-type="image"><a href="' + url + '"><img src="' + url + '"></a><figcaption></figcaption></figure>'
this.selection.restore()
if (cursor) {
$(cursor).after(data)
}
else {
this.insert.html(data)
}
this.selection.restore()
this.code.sync()
}, this))
/*
* Maintain undo history
* Detect resize command, update the image src
*/
this.bufferSet()
this.$editor.on('imageCommand', 'figure', function (event, command) {
var size = null
/*
* Remember the cursor pos
*/
var cursor = this.getBlock() || this.getCurrent()
if (command == 'small')
size = 300
else if (command == 'medium')
size = 600
else if (command == 'large')
size = 900
else
return
/*
* Display the image upload modal
*/
// @todo
var newUrl, $img = $(this).find('img')
$img.attr('src', newUrl)
})
/*
* Add button
*/
var url = 'http://placehold.it/100x100'
var data = '<figure data-type="image"><a href="' + url + '"><img src="' + url + '"></a><figcaption></figcaption></figure>'
this.selectionRestore()
if (cursor) {
$(cursor).after(data)
}
else {
this.insertHtmlAdvanced(data, false);
}
this.selectionRestore()
this.sync()
}, this))
/*
* Detect resize command, update the image src
*/
this.$editor.on('imageCommand', 'figure', function (event, command) {
var size = null
if (command == 'small')
size = 300
else if (command == 'medium')
size = 600
else if (command == 'large')
size = 900
else
return
// @todo
var newUrl, $img = $(this).find('img')
$img.attr('src', newUrl)
})
this.buttonGet('image')
.addClass('redactor_btn_image')
.removeClass('redactor-btn-image')
button.addClass('redactor_btn_image').removeClass('redactor-btn-image')
}
}
}

View File

@ -118,9 +118,9 @@
toggle: function () {
this.redactor.formatQuote()
this.redactor.block.format('blockquote')
var $target = $(this.redactor.getBlock() || this.redactor.getCurrent())
var $target = $(this.redactor.selection.getBlock() || this.redactor.selection.getCurrent())
if ($target.is('blockquote')) {
$target.append($('<cite />'))
@ -131,17 +131,20 @@
$target.closest('figure').before($target).remove()
}
this.redactor.sync()
this.redactor.code.sync()
}
}
window.RedactorPlugins.quote = {
init: function () {
this.quote = new Quote(this)
window.RedactorPlugins.quote = function() {
return {
init: function () {
this.quote = new Quote(this)
this.buttonAddBefore('link', 'quote', 'Quote', $.proxy(this.quote.toggle, this.quote))
this.buttonGet('quote').addClass('redactor_btn_quote').removeClass('redactor-btn-image')
var button = this.button.addBefore('link', 'quote', 'Quote')
this.button.addCallback(button, $.proxy(this.quote.toggle, this.quote))
button.addClass('redactor_btn_quote').removeClass('redactor-btn-image')
}
}
}

View File

@ -34,7 +34,7 @@
insertTable: function (rows, columns) {
this.redactor.bufferSet(false)
this.redactor.buffer.set(false)
var $tableBox = $('<div></div>'),
tableId = Math.floor(Math.random() * 99999),
@ -72,25 +72,25 @@
$('<figure data-type="table">').addClass('oc-table oc-table-bordered-rows').append($table).appendTo($tableBox)
var html = $tableBox.html()
this.redactor.modalClose()
this.redactor.selectionRestore()
this.redactor.modal.close()
this.redactor.selection.restore()
var current = this.redactor.getBlock() || this.redactor.getCurrent()
var current = this.redactor.selection.getBlock() || this.redactor.selection.getCurrent()
if (current) {
$(current).after(html)
}
else {
this.redactor.insertHtmlAdvanced(html, false)
this.redactor.insert.html(html)
}
this.redactor.selectionRestore()
this.redactor.selection.restore()
var table = this.redactor.$editor.find('#table' + tableId)
table.find('span#selection-marker-1').remove()
table.removeAttr('id')
this.redactor.sync()
this.redactor.code.sync()
},
@ -183,52 +183,51 @@
}
}
window.RedactorPlugins.table = {
init: function () {
this.table = new Table(this)
this.buttonAddBefore('link', 'table', 'Table', $.proxy(function () {
window.RedactorPlugins.table = function() {
return {
init: function () {
this.table = new Table(this)
/*
* Save cursor position
*/
this.selectionSave()
var button = this.button.addBefore('link', 'table', 'Table')
this.button.addCallback(button, $.proxy(function () {
var callback = $.proxy(function () {
/*
* Save cursor position
*/
this.selection.save()
$('#redactor_insert_table_btn').on('click', $.proxy(function () {
var callback = $.proxy(function () {
setTimeout(function () {
$('#redactor_table_rows').trigger('focus')
}, 200)
}, this)
var insert = $.proxy(function () {
this.table.insertTable($('#redactor_table_rows').val(), $('#redactor_table_columns').val())
this.buttonInactive('table')
}, this))
this.button.setInactive('table')
}, this)
$('.redactor_btn_modal_close').on('click', $.proxy(function () {
this.buttonInactive('table')
}, this))
var modal = String()
+ '<section id="redactor-modal-table-insert">'
+ '<label>' + this.opts.curLang.rows + '</label>'
+ '<input type="text" size="5" value="2" id="redactor_table_rows" class="redactor_input">'
+ '<label>' + this.opts.curLang.columns + '</label>'
+ '<input type="text" size="5" value="3" id="redactor_table_columns" class="redactor_input">'
+ '</section>'
setTimeout(function () {
$('#redactor_table_rows').trigger('focus')
}, 200)
this.modal.addTemplate('insert-table', modal)
this.modal.addCallback('insert-table', callback)
this.modal.load('insert-table', 'Insert Table', 500)
}, this)
this.modal.createCancelButton()
this.modal.createActionButton(this.lang.get('insert')).on('click', insert)
this.modal.show()
var modal = String() +
'<section>' +
'<label>' + this.opts.curLang.rows + '</label>' +
'<input type="text" size="5" value="2" id="redactor_table_rows" class="redactor_input">' +
'<label>' + this.opts.curLang.columns + '</label>' +
'<input type="text" size="5" value="3" id="redactor_table_columns" class="redactor_input">' +
'</section>' +
'<footer>' +
'<button type="button" class="redactor_modal_btn redactor_btn_modal_close">' + this.opts.curLang.cancel + '</button>' +
'<button type="button" class="redactor_modal_btn redactor_modal_action_btn" id="redactor_insert_table_btn">' + this.opts.curLang.insert + '</button>' +
'</footer>'
}, this))
this.modalInit('Insert Table', modal, 500, callback)
}, this))
this.buttonGet('table')
.addClass('redactor_btn_table')
.removeClass('redactor-btn-image')
button.addClass('redactor_btn_table').removeClass('redactor-btn-image')
}
}
}

View File

@ -54,7 +54,9 @@
* Initialize Redactor editor
*/
var redactorOptions = {
observeImages: false,
imageEditable: false,
imageResizable: false,
buttonSource: true,
focusCallback: function() { self.$el.addClass('editor-focus') },
blurCallback: function() { self.$el.removeClass('editor-focus') },
initCallback: function() { self.build() },
@ -72,8 +74,11 @@
redactorOptions.fullpage = true
}
redactorOptions.plugins = ['cleanup', 'fullscreen', 'figure', 'image', 'quote', 'table']
redactorOptions.buttons = ['formatting', 'bold', 'italic', 'unorderedlist', 'orderedlist', 'link', 'horizontalrule', 'html'],
// redactorOptions.plugins = ['cleanup', 'fullscreen', 'figure', 'image', 'quote', 'table']
// redactorOptions.buttons = ['formatting', 'bold', 'italic', 'unorderedlist', 'orderedlist', 'link', 'horizontalrule', 'html'],
redactorOptions.plugins = ['cleanup', 'fullscreen', 'figure', 'quote', 'table']
redactorOptions.buttons = ['formatting', 'bold', 'italic', 'unorderedlist', 'orderedlist', 'image', 'link', 'horizontalrule', 'html'],
this.$textarea.redactor(redactorOptions)
}
@ -82,12 +87,13 @@
this.updateLayout()
$(window).resize($.proxy(this.updateLayout, this))
$(window).on('oc.updateUi', $.proxy(this.updateLayout, this))
}
RichEditor.prototype.updateLayout = function() {
var $editor = $('.redactor_editor', this.$el),
var $editor = $('.redactor-editor', this.$el),
$codeEditor = $('textarea', this.$el),
$toolbar = $('.redactor_toolbar', this.$el)
$toolbar = $('.redactor-toolbar', this.$el)
if (!$editor.length)
return

View File

@ -2,7 +2,7 @@
// Figures
//
.redactor_editor {
.redactor-editor {
figure {
position: relative;
@ -121,11 +121,7 @@
}
.redactor_box {
figure:hover .oc-figure-controls {
display: block
}
.redactor-box {
figcaption {
&:empty:before {
@ -153,6 +149,10 @@
text-align: center;
}
figure:hover .oc-figure-controls {
display: block;
}
.oc-figure-controls span {
display: inline-block;
border: none;

File diff suppressed because one or more lines are too long

View File

@ -16,10 +16,10 @@
.field-richeditor {
border: 1px solid @color-form-field-border;
&, .redactor_box {
&, .redactor-box {
.border-radius(5px);
}
.redactor_toolbar {
.redactor-toolbar {
.border-top-radius(3px);
}
@ -27,11 +27,80 @@
border-color: @color-form-field-border-focus;
}
&.size-tiny .redactor_editor { height: (@size-tiny - @richeditor-toolbar-size) !important; }
&.size-small .redactor_editor { height: (@size-small - @richeditor-toolbar-size) !important; }
&.size-large .redactor_editor { height: (@size-large - @richeditor-toolbar-size) !important; }
&.size-huge .redactor_editor { height: (@size-huge - @richeditor-toolbar-size) !important; }
&.size-giant .redactor_editor { height: (@size-giant - @richeditor-toolbar-size) !important; }
&.size-tiny .redactor-editor { height: (@size-tiny - @richeditor-toolbar-size) !important; }
&.size-small .redactor-editor { height: (@size-small - @richeditor-toolbar-size) !important; }
&.size-large .redactor-editor { height: (@size-large - @richeditor-toolbar-size) !important; }
&.size-huge .redactor-editor { height: (@size-huge - @richeditor-toolbar-size) !important; }
&.size-giant .redactor-editor { height: (@size-giant - @richeditor-toolbar-size) !important; }
}
//
// Override redactor defaults
//
.redactor-box {
margin-bottom: 0;
& iframe {
border: none; // Oc
}
}
.redactor-box-fullscreen {
z-index: @richeditor-zindex + 99 !important;
}
.redactor-toolbar,
.redactor-dropdown {
z-index: @richeditor-zindex + 1050 !important;
}
#redactor-modal-overlay,
#redactor-modal-box,
#redactor-modal {
z-index: @richeditor-zindex + 1051 !important;
}
.redactor-toolbar {
background: @color-richeditor-toolbar;
.box-shadow(none);
& li.redactor-btn-right {
float: right;
margin-right: 2px;
}
& li a {
color: @color-richeditor-toolbar-btn-color;
font-size: 14px;
width: 20px;
line-height: 20px;
&:hover {
background-color: @color-richeditor-toolbar-btn-bg-hover;
color: @color-richeditor-toolbar-btn-color-hover;
}
&:active,
&.redactor-act {
background-color: @color-richeditor-toolbar-btn-bg-active;
color: @color-richeditor-toolbar-btn-color-hover;
}
}
}
.redactor-editor {
border: none;
}
body .redactor-box-fullscreen {
background: @color-body-bg;
overflow-y: scroll !important;
width: 100%!important;
.redactor-editor {
background: #fff;
max-width: 960px;
margin: @richeditor-gutter auto !important;
padding: @richeditor-gutter;
}
}
//
@ -39,14 +108,17 @@
//
.field-richeditor.stretch {
.redactor_box {
.redactor-box {
display: block;
position: relative;
height: 100%!important;
width: 100%!important;
height: 100% !important;
width: 100% !important;
.border-radius(0)!important;
overflow: hidden;
.redactor_toolbar {
.redactor-toolbar {
.border-radius(0)!important;
display: block;
border-bottom: none;
position: absolute;
@ -54,23 +126,20 @@
width: 100%;
}
.redactor_editor, textarea {
height: auto !important;
width: 100%!important;
.redactor-editor, textarea {
width: 100% !important;
left: 0;
top: 0;
bottom: 0;
position: absolute;
}
.redactor-editor {
height: auto !important;
}
textarea {
padding: 10px;
}
iframe {
display: block;
position: absolute;
height: 100% !important;
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,4 @@
<!-- Rich Editor -->
<?php if ($this->previewMode): ?>
<div class="form-control"><?= $value ?></div>
<?php else: ?>

View File

@ -5,6 +5,9 @@ use Request;
/**
* Model for logging access to the back-end
*
* @package october\backend
* @author Alexey Bobkov, Samuel Georges
*/
class AccessLog extends Model
{

View File

@ -6,6 +6,12 @@ use Model;
use Session;
use DirectoryIterator;
/**
* Backend preferences for the backend user
*
* @package october\backend
* @author Alexey Bobkov, Samuel Georges
*/
class BackendPreferences extends Model
{
public $implement = ['Backend.Behaviors.UserPreferencesModel'];

View File

@ -4,6 +4,12 @@ use App;
use Model;
use DirectoryIterator;
/**
* Code editor preferences for the backend user\
*
* @package october\backend
* @author Alexey Bobkov, Samuel Georges
*/
class EditorPreferences extends Model
{
public $implement = ['Backend.Behaviors.UserPreferencesModel'];

View File

@ -6,6 +6,12 @@ use October\Rain\Database\Model;
use System\Classes\SystemException;
use October\Rain\Auth\Models\Preferences as PreferencesBase;
/**
* All preferences for the backend user
*
* @package october\backend
* @author Alexey Bobkov, Samuel Georges
*/
class UserPreferences extends PreferencesBase
{
/**

View File

@ -9,6 +9,7 @@ use Config;
use RecursiveIteratorIterator;
use RecursiveDirectoryIterator;
use Illuminate\Container\Container;
use ApplicationException;
/**
* Plugin manager
@ -105,34 +106,6 @@ class PluginManager
return $this->plugins;
}
/**
* Cross checks all plugins and their dependancies, if not met plugins
* are disabled and vice versa.
*/
protected function loadDependencies()
{
foreach ($this->plugins as $id => $plugin) {
if (!isset($plugin->require) || !$plugin->require)
continue;
$required = is_array($plugin->require) ? $plugin->require : [$plugin->require];
$disable = false;
foreach ($required as $require) {
if (!$this->hasPlugin($require))
$disable = true;
elseif (($pluginObj = $this->findByIdentifier($require)) && $pluginObj->disabled)
$disable = true;
}
if ($disable)
$this->disablePlugin($id);
else
$this->enablePlugin($id);
}
}
/**
* Runs the register() method on all plugins. Can only be called once.
*/
@ -227,6 +200,18 @@ class PluginManager
return $this->pathMap[$classId];
}
/**
* Check if a plugin exists and is enabled.
* @param string $id Plugin identifier, eg: Namespace.PluginName
* @return boolean
*/
public function exists($id)
{
return (!$this->findByIdentifier($id) || $this->isDisabled($id))
? false
: true;
}
/**
* Returns an array with all registered plugins
* The index is the plugin namespace, the value is the plugin information object.
@ -446,4 +431,108 @@ class PluginManager
return true;
}
//
// Dependencies
//
/**
* Cross checks all plugins and their dependancies, if not met plugins
* are disabled and vice versa.
*/
protected function loadDependencies()
{
foreach ($this->plugins as $id => $plugin) {
if (!$required = $this->getDependencies($plugin))
continue;
$disable = false;
foreach ($required as $require) {
if (!$this->hasPlugin($require))
$disable = true;
elseif (($pluginObj = $this->findByIdentifier($require)) && $pluginObj->disabled)
$disable = true;
}
if ($disable)
$this->disablePlugin($id);
else
$this->enablePlugin($id);
}
}
/**
* Returns the plugin identifiers that are required by the supplied plugin.
* @param string $plugin Plugin identifier, object or class
* @return array
*/
public function getDependencies($plugin)
{
if (is_string($plugin) && (!$plugin = $this->findByIdentifier($identifer)))
return false;
if (!isset($plugin->require) || !$plugin->require)
return null;
return is_array($plugin->require) ? $plugin->require : [$plugin->require];
}
/**
* Sorts a collection of plugins, in the order that they should be actioned,
* according to their given dependencies. Least dependent come first.
* @param array $plugins Object collection to sort, or null to sort all.
* @return array Collection of sorted plugin identifiers
*/
public function sortByDependencies($plugins = null)
{
if (!is_array($plugins))
$plugins = $this->getPlugins();
$result = [];
$checklist = $plugins;
$loopCount = 0;
while (count($checklist)) {
if (++$loopCount > 999)
throw new ApplicationException('Too much recursion');
foreach ($checklist as $code => $plugin) {
/*
* Get dependencies and remove any aliens
*/
$depends = $this->getDependencies($plugin) ?: [];
$depends = array_filter($depends, function($pluginCode) use ($plugins) {
return isset($plugins[$pluginCode]);
});
/*
* No dependencies
*/
if (!$depends) {
array_push($result, $code);
unset($checklist[$code]);
continue;
}
/*
* Find dependencies that have not been checked
*/
$depends = array_diff($depends, $result);
if (count($depends) > 0)
continue;
/*
* All dependencies are checked
*/
array_push($result, $code);
unset($checklist[$code]);
}
}
return $result;
}
}

View File

@ -104,9 +104,9 @@ class UpdateManager
/*
* Update plugins
*/
$plugins = $this->pluginManager->getPlugins();
foreach ($plugins as $name => $plugin) {
$this->updatePlugin($name);
$plugins = $this->pluginManager->sortByDependencies();
foreach ($plugins as $plugin) {
$this->updatePlugin($plugin);
}
Parameters::set('system::update.count', 0);

View File

@ -67,21 +67,6 @@ class VersionManager
$this->pluginManager = PluginManager::instance();
}
/**
* Performs the update for all plugins
*/
public function updateAll()
{
$plugins = $this->pluginManager->getPlugins();
foreach ($plugins as $code => $plugin) {
if (!$this->hasVersionFile($code))
continue;
$this->updatePlugin($code);
}
}
/**
* Updates a single plugin by its code or object with it's latest changes.
*/

View File

@ -5,6 +5,9 @@ use Model;
/**
* Model for logging system errors and debug trace messages
*
* @package october\system
* @author Alexey Bobkov, Samuel Georges
*/
class EventLog extends Model
{

View File

@ -3,6 +3,12 @@
use Model;
use System\Classes\ApplicationException;
/**
* Mail layout
*
* @package october\system
* @author Alexey Bobkov, Samuel Georges
*/
class MailLayout extends Model
{
use \October\Rain\Database\Traits\Validation;

View File

@ -3,6 +3,12 @@
use App;
use Model;
/**
* Mail settings
*
* @package october\system
* @author Alexey Bobkov, Samuel Georges
*/
class MailSettings extends Model
{
public $implement = ['System.Behaviors.SettingsModel'];

View File

@ -7,6 +7,12 @@ use Model;
use October\Rain\Mail\MailParser;
use System\Classes\PluginManager;
/**
* Mail template
*
* @package october\system
* @author Alexey Bobkov, Samuel Georges
*/
class MailTemplate extends Model
{
use \October\Rain\Database\Traits\Validation;

View File

@ -6,6 +6,9 @@ use October\Rain\Database\Model;
/**
* Parameters model
* Used for storing internal application parameters.
*
* @package october\system
* @author Alexey Bobkov, Samuel Georges
*/
class Parameters extends Model
{

View File

@ -5,6 +5,12 @@ use Model;
use Config;
use System\Classes\PluginManager;
/**
* Stores information about current plugin versions.
*
* @package october\system
* @author Alexey Bobkov, Samuel Georges
*/
class PluginVersion extends Model
{
use \October\Rain\Database\Traits\Purgeable;

View File

@ -5,6 +5,9 @@ use Request;
/**
* Model for logging 404 errors
*
* @package october\system
* @author Alexey Bobkov, Samuel Georges
*/
class RequestLog extends Model
{