From 0c7c2da9b40b0cdb7dc3ebf7f33ba8853e7c0cc8 Mon Sep 17 00:00:00 2001 From: Henning Leutz <leutz@pcsg.de> Date: Tue, 23 Dec 2014 18:23:20 +0100 Subject: [PATCH] blocks --- ajax/block/save.php | 28 ++++ ajax/getAvailableBlocks.php | 23 ++++ ajax/getBlock.php | 25 ++++ ajax/project/createBlock.php | 28 ++++ ajax/project/getAreas.php | 25 ++++ ajax/project/getBlocks.php | 9 +- bin/Area.css | 32 +++++ bin/Area.js | 131 +++++++++++++++++++ bin/AreaWindow.js | 114 ++++++++++++++++ bin/BlockAreas.css | 31 +++++ bin/BlockAreas.js | 146 +++++++++++++++++++++ bin/BlockEdit.css | 43 ++++++ bin/BlockEdit.js | 245 +++++++++++++++++++++++++++++++++++ bin/Manager.css | 20 +++ bin/Manager.js | 230 ++++++++++++++++++++++++++++++-- database.xml | 2 + lib/QUI/Blocks/Block.php | 78 ++++++++--- lib/QUI/Blocks/Manager.php | 175 ++++++++++++++++++++++++- lib/QUI/Blocks/Utils.php | 112 ++++++++++++---- 19 files changed, 1438 insertions(+), 59 deletions(-) create mode 100644 ajax/block/save.php create mode 100644 ajax/getAvailableBlocks.php create mode 100644 ajax/getBlock.php create mode 100644 ajax/project/createBlock.php create mode 100644 ajax/project/getAreas.php create mode 100644 bin/Area.css create mode 100644 bin/Area.js create mode 100644 bin/AreaWindow.js create mode 100644 bin/BlockAreas.css create mode 100644 bin/BlockAreas.js create mode 100644 bin/BlockEdit.css create mode 100644 bin/BlockEdit.js create mode 100644 bin/Manager.css diff --git a/ajax/block/save.php b/ajax/block/save.php new file mode 100644 index 0000000..530f13a --- /dev/null +++ b/ajax/block/save.php @@ -0,0 +1,28 @@ +<?php + +/** + * This file contains package_quiqqer_blocks_ajax_getBlock + */ + +/** + * saves the block + * + * @param {String|Integer} $blockId - Block-ID + * @param + * @return array + */ +function package_quiqqer_blocks_ajax_block_save($blockId, $data) +{ + $BlockManager = new \QUI\Blocks\Manager(); + $BlockManager->saveBlock( $blockId, json_decode( $data, true ) ); + + $Block = $BlockManager->getBlockById( $blockId ); + + return $Block->getAttributes(); +} + +\QUI::$Ajax->register( + 'package_quiqqer_blocks_ajax_block_save', + array('blockId', 'data'), + 'Permission::checkAdminUser' +); diff --git a/ajax/getAvailableBlocks.php b/ajax/getAvailableBlocks.php new file mode 100644 index 0000000..dd50a4c --- /dev/null +++ b/ajax/getAvailableBlocks.php @@ -0,0 +1,23 @@ +<?php + +/** + * This file contains package_quiqqer_blocks_ajax_getAvailableBlocks + */ + +/** + * Returns the available blocks in the system + * + * @return array + */ +function package_quiqqer_blocks_ajax_getAvailableBlocks() +{ + $BlockManager = new \QUI\Blocks\Manager(); + + return $BlockManager->getAvailableBlocks(); +} + +\QUI::$Ajax->register( + 'package_quiqqer_blocks_ajax_getAvailableBlocks', + false, + 'Permission::checkAdminUser' +); diff --git a/ajax/getBlock.php b/ajax/getBlock.php new file mode 100644 index 0000000..d54026e --- /dev/null +++ b/ajax/getBlock.php @@ -0,0 +1,25 @@ +<?php + +/** + * This file contains package_quiqqer_blocks_ajax_getBlock + */ + +/** + * Returns the Block data + * + * @param {String|Integer} $blockId - Block-ID + * @return array + */ +function package_quiqqer_blocks_ajax_getBlock($blockId) +{ + $BlockManager = new \QUI\Blocks\Manager(); + $Block = $BlockManager->getBlockById( $blockId ); + + return $Block->getAttributes(); +} + +\QUI::$Ajax->register( + 'package_quiqqer_blocks_ajax_getBlock', + array('blockId'), + 'Permission::checkAdminUser' +); diff --git a/ajax/project/createBlock.php b/ajax/project/createBlock.php new file mode 100644 index 0000000..d64d794 --- /dev/null +++ b/ajax/project/createBlock.php @@ -0,0 +1,28 @@ +<?php + +/** + * This file contains package_quiqqer_blocks_ajax_project_createBlock + */ + +/** + * Returns the feed list + * + * @param string $project - json array, Project Data + * @param string $data - json array, Block Data + * @return array + */ +function package_quiqqer_blocks_ajax_project_createBlock($project, $data) +{ + $Project = QUI::getProjectManager()->decode( $project ); + $Block = new QUI\Blocks\Block( json_decode( $data, true ) ); + + $BlockManager = new QUI\Blocks\Manager(); + + return $BlockManager->createBlockForProject( $Project, $Block ); +} + +QUI::$Ajax->register( + 'package_quiqqer_blocks_ajax_project_createBlock', + array( 'project', 'data' ), + 'Permission::checkAdminUser' +); diff --git a/ajax/project/getAreas.php b/ajax/project/getAreas.php new file mode 100644 index 0000000..798396e --- /dev/null +++ b/ajax/project/getAreas.php @@ -0,0 +1,25 @@ +<?php + +/** + * This file contains package_quiqqer_blocks_ajax_project_getBlocks + */ + +/** + * Returns the feed list + * + * @param string $project - json array, Project Data + * @return array + */ +function package_quiqqer_blocks_ajax_project_getAreas($project) +{ + $Project = QUI::getProjectManager()->decode( $project ); + $BlockManager = new QUI\Blocks\Manager(); + + return $BlockManager->getAreasByProject( $Project ); +} + +QUI::$Ajax->register( + 'package_quiqqer_blocks_ajax_project_getAreas', + array( 'project' ), + 'Permission::checkAdminUser' +); diff --git a/ajax/project/getBlocks.php b/ajax/project/getBlocks.php index 925a295..9a20aca 100644 --- a/ajax/project/getBlocks.php +++ b/ajax/project/getBlocks.php @@ -1,32 +1,31 @@ <?php /** - * This file contains package_quiqqer_feed_ajax_getList + * This file contains package_quiqqer_blocks_ajax_project_getBlocks */ /** * Returns the feed list * - * @author www.pcsg.de (Henning Leutz) * @param string $project - json array, Project Data * @return array */ function package_quiqqer_blocks_ajax_project_getBlocks($project) { $Project = QUI::getProjectManager()->decode( $project ); - $BlockManager = new \QUI\Blocks\Manager(); + $BlockManager = new QUI\Blocks\Manager(); $blocks = $BlockManager->getBlocksFromProject( $Project ); $result = array(); foreach ( $blocks as $Block ) { - $result = $Block->getAttributes(); + $result[] = $Block->getAttributes(); } return $result; } -\QUI::$Ajax->register( +QUI::$Ajax->register( 'package_quiqqer_blocks_ajax_project_getBlocks', array( 'project' ), 'Permission::checkAdminUser' diff --git a/bin/Area.css b/bin/Area.css new file mode 100644 index 0000000..6ee539b --- /dev/null +++ b/bin/Area.css @@ -0,0 +1,32 @@ + +.quiqqer-blocks-area { + border: 1px solid #ddd; + cursor: pointer; + float: left; + margin-bottom: 10px; + padding: 10px; + width: 100%; +} + +.quiqqer-blocks-area:hover { + background: #2F8FC6; + color: #FFFFFF; +} + +.quiqqer-blocks-area-icon { + float: left; + font-size: 22px; + text-align: center; + width: 40px; +} + +.quiqqer-blocks-area-content { + float: left; + padding: 0 0 0 10px; + width: calc( 100% - 40px ) +} + +.quiqqer-blocks-area-selected { + background-color: #0069b4; + color: #FFFFFF; +} \ No newline at end of file diff --git a/bin/Area.js b/bin/Area.js new file mode 100644 index 0000000..4235a1e --- /dev/null +++ b/bin/Area.js @@ -0,0 +1,131 @@ + +/** + * BlockAreas Control + * Edit and change the areas for the block + * + * @module package/quiqqer/blocks/bin/BlockAreas + * @author www.pcsg.de (Henning Leutz) + * + * @event onLoaded [ this ] + */ + +define('package/quiqqer/blocks/bin/Area', [ + + 'qui/QUI', + 'qui/controls/Control', + 'qui/controls/buttons/Button', + 'package/quiqqer/blocks/bin/AreaWindow', + 'Ajax', + 'Locale', + + 'css!package/quiqqer/blocks/bin/Area.css' + +], function(QUI, QUIControl) +{ + "use strict"; + + return new Class({ + + Extends : QUIControl, + Type : 'package/quiqqer/blocks/bin/Area', + + Binds : [ + 'toggle' + ], + + options : { + area : false, + title : false, + description : false + }, + + initialize : function(options) + { + this.parent( options ); + + this.$Title = false; + this.$Desc = false; + this.$selected = false; + }, + + /** + * Return the HTML Node Element + * + * @return {HTMLElement} + */ + create : function() + { + this.$Elm = new Element('div', { + 'class' : 'quiqqer-blocks-area smooth', + html : '<div class="quiqqer-blocks-area-icon">' + + '<span class="icon-list-alt"></span>' + + '</div>' + + '<div class="quiqqer-blocks-area-content">' + + '<div class="quiqqer-blocks-area-content-title"></div>' + + '<div class="quiqqer-blocks-area-content-description"></div>' + + '</div>', + events : { + click : this.toggle + } + }); + + this.$Title = this.$Elm.getElement( '.quiqqer-blocks-area-content-title' ); + this.$Desc = this.$Elm.getElement( '.quiqqer-blocks-area-content-description' ); + + if ( this.getAttribute( 'area' ) ) { + this.$Elm.set( 'data-area', this.getAttribute( 'area' ) ); + } + + if ( this.getAttribute( 'title' ) ) { + this.$Title.set( 'html', this.getAttribute( 'title' ) ); + } + + if ( this.getAttribute( 'description' ) ) { + this.$Desc.set( 'html', this.getAttribute( 'description' ) ); + } + + + return this.$Elm; + }, + + /** + * toggle the select status + */ + toggle : function() + { + if ( this.$selected ) + { + this.unselect(); + return; + } + + this.select(); + }, + + /** + * Select the area + */ + select : function() + { + if ( this.$selected ) { + return; + } + + this.$selected = true; + this.$Elm.addClass( 'quiqqer-blocks-area-selected' ); + }, + + /** + * Unselect the area + */ + unselect : function() + { + if ( this.$selected === false ) { + return; + } + + this.$selected = false; + this.$Elm.removeClass( 'quiqqer-blocks-area-selected' ); + } + }); +}); diff --git a/bin/AreaWindow.js b/bin/AreaWindow.js new file mode 100644 index 0000000..e13c0c4 --- /dev/null +++ b/bin/AreaWindow.js @@ -0,0 +1,114 @@ + +/** + * AreaWindow Control + * List of the areas which are available + * + * @module package/quiqqer/blocks/bin/AreaWindow + * @author www.pcsg.de (Henning Leutz) + * + * @event onSubmit [ this, areas ] + */ + +define('package/quiqqer/blocks/bin/AreaWindow', [ + + 'qui/QUI', + 'qui/controls/windows/Confirm', + 'package/quiqqer/blocks/bin/Area', + 'Ajax', + 'Locale' + +], function(QUI, QUIConfirm, Area, Ajax, QUILocale) +{ + "use strict"; + + return new Class({ + + Extends : QUIConfirm, + Type : 'package/quiqqer/blocks/bin/AreaWindow', + + Binds : [ + '$onOpen' + ], + + options : { + title : 'Projekt Blockbereiche', + project : false, + maxHeight : 500, + maxWidth : 400 + }, + + initialize : function(options) + { + this.parent( options ); + + this.addEvents({ + onOpen : this.$onOpen + }); + }, + + /** + * event : on open + */ + $onOpen : function() + { + var self = this; + + this.Loader.show(); + + this.getList(function(result) + { + var i, len, desc, title; + var Content = self.getContent(); + + for ( i = 0, len = result.length; i < len; i++ ) + { + title = result[ i ].title; + desc = result[ i ].description; + + new Area({ + title : QUILocale.get( title.group, title['var'] ), + description : QUILocale.get( desc.group, desc['var'] ), + area : result[ i ].name + }).inject( Content ); + } + + self.Loader.hide(); + }); + }, + + /** + * Return the areas of the project + * + * @param {Function} callback + */ + getList : function(callback) + { + Ajax.get('package_quiqqer_blocks_ajax_project_getAreas', callback, { + 'package' : 'quiqqer/block', + project : JSON.encode({ + name : this.getAttribute( 'project' ) + }) + }); + }, + + /** + * Submit the window + */ + submit : function() + { + var Content = this.getContent(); + + var areas = Content.getElements( + '.quiqqer-blocks-area-selected' + ).map(function(Elm) { + return Elm.get( 'data-area' ); + }); + + this.fireEvent( 'submit', [ this, areas ] ); + + if ( this.getAttribute( 'autoclose' ) ) { + this.close(); + } + } + }); +}); diff --git a/bin/BlockAreas.css b/bin/BlockAreas.css new file mode 100644 index 0000000..5a3d777 --- /dev/null +++ b/bin/BlockAreas.css @@ -0,0 +1,31 @@ + +.quiqqer-blocks-blockareas { + border: 2px solid #dedede; + border-radius: 3px; + float: left; + height: 100%; + width: 100%; +} + +.quiqqer-blocks-blockareas-container { + background: #fff; + height: calc(100% - 30px); + overflow: auto; + padding: 10px; +} + +.quiqqer-blocks-blockareas-buttons { + height: 30px; +} + +.quiqqer-blocks-blockareas-area { + background-color: #eff0f0; + border: 1px solid #d6d9d9; + border-radius: 3px; + color: #555; + float: left; + margin: 0 5px 5px 0; + padding: 3px 10px; + position: relative; + text-decoration: none; +} \ No newline at end of file diff --git a/bin/BlockAreas.js b/bin/BlockAreas.js new file mode 100644 index 0000000..8c3e05d --- /dev/null +++ b/bin/BlockAreas.js @@ -0,0 +1,146 @@ + +/** + * BlockAreas Control + * Edit and change the areas for the block + * + * @module package/quiqqer/blocks/bin/BlockAreas + * @author www.pcsg.de (Henning Leutz) + * + * @event onLoaded [ this ] + */ + +define('package/quiqqer/blocks/bin/BlockAreas', [ + + 'qui/QUI', + 'qui/controls/Control', + 'qui/controls/buttons/Button', + 'package/quiqqer/blocks/bin/AreaWindow', + 'Ajax', + 'Locale', + + 'css!package/quiqqer/blocks/bin/BlockAreas.css' + +], function(QUI, QUIControl, QUIButton, AreaWindow, Ajax, QUILocale) +{ + "use strict"; + + return new Class({ + + Extends : QUIControl, + Type : 'package/quiqqer/blocks/bin/BlockAreas', + + Binds : [ + '$onDestroy' + ], + + options : { + blockId : false, // blockId + styles : false, + project : false, + areas : false + }, + + initialize : function(options) + { + this.parent( options ); + + this.$areas = {}; + }, + + /** + * Return the HTML Node Element + * + * @return {HTMLElement} + */ + create : function() + { + var self = this; + + this.$Elm = new Element('div', { + 'class' : 'quiqqer-blocks-blockareas', + html : '<div class="quiqqer-blocks-blockareas-container"></div>' + + '<div class="quiqqer-blocks-blockareas-buttons"></div>' + }); + + if ( this.getAttribute( 'styles' ) ) { + this.$Elm.setStyles( this.getAttribute( 'styles' ) ); + } + + this.$Container = this.$Elm.getElement( '.quiqqer-blocks-blockareas-container' ); + this.$Buttons = this.$Elm.getElement( '.quiqqer-blocks-blockareas-buttons' ); + + new QUIButton({ + text : 'Blockbereich hinzufügen', + styles : { + width : '100%' + }, + events : + { + onClick : function() + { + new AreaWindow({ + project : self.getAttribute( 'project' ), + events : + { + onSubmit : function(Win, areas) + { + for ( var i = 0, len = areas.length; i < len; i++ ) { + self.addArea( areas[ i ] ); + } + } + } + }).open(); + } + } + }).inject( this.$Buttons ); + + var areas = this.getAttribute( 'areas' ); + + if ( areas ) + { + areas.map(function(area) { + self.addArea( area ); + }); + } + + return this.$Elm; + }, + + /** + * Add an area + * @param {String} area - name of the area + */ + addArea : function(area) + { + if ( area in this.$areas ) { + return; + } + + this.$areas[ area ] = true; + + new Element('div', { + 'class' : 'quiqqer-blocks-blockareas-area', + html : area + }).inject( this.$Container ); + }, + + /** + * Return the areas + * + * @return {Array} + */ + getAreas : function() + { + var result = []; + + for ( var area in this.$areas ) + { + if ( this.$areas.hasOwnProperty( area ) ) { + result.push( area ); + } + } + + return result; + } + }); +}); diff --git a/bin/BlockEdit.css b/bin/BlockEdit.css new file mode 100644 index 0000000..98f57fb --- /dev/null +++ b/bin/BlockEdit.css @@ -0,0 +1,43 @@ + +.quiqqer-blocks-blockedit { + float: left; + height: 100%; + padding: 20px; + width: 100%; +} + + +.quiqqer-blocks-blockedit label { + clear: both; + float: left; + margin-bottom: 20px; + width: 100%; +} + +.quiqqer-blocks-blockedit input, +.quiqqer-blocks-blockedit select, +.quiqqer-blocks-blockedit-label-text, +.quiqqer-blocks-blockedit-label-editor{ + clear: both; + float: left; + max-width: 300px; + width: 100%; +} + +.quiqqer-blocks-blockedit-label-text { + cursor: pointer; + margin-bottom: 10px; +} + +.quiqqer-blocks-blockedit-label-editor { + cursor: pointer; + margin-bottom: 0; +} + +.quiqqer-blocks-areas { + margin-bottom: 0 !important; +} + +.quiqqer-blocks-blockareas { + margin-bottom: 20px; +} \ No newline at end of file diff --git a/bin/BlockEdit.js b/bin/BlockEdit.js new file mode 100644 index 0000000..0bba86a --- /dev/null +++ b/bin/BlockEdit.js @@ -0,0 +1,245 @@ + +/** + * BlockEdit Control + * Edit and change a Block + * + * @module package/quiqqer/blocks/bin/BlockEdit + * @author www.pcsg.de (Henning Leutz) + * + * @event onLoaded [ this ] + */ + +define('package/quiqqer/blocks/bin/BlockEdit', [ + + 'qui/QUI', + 'qui/controls/Control', + 'package/quiqqer/blocks/bin/BlockAreas', + 'Ajax', + 'Locale', + + 'css!package/quiqqer/blocks/bin/BlockEdit.css' + +], function(QUI, QUIControl, BlockAreas, Ajax, QUILocale) +{ + "use strict"; + + return new Class({ + + Extends : QUIControl, + Type : 'package/quiqqer/blocks/bin/BlockEdit', + + Binds : [ + '$onInject', + '$onDestroy' + ], + + options : { + id : false, + project : false + }, + + initialize : function(options) + { + this.parent( options ); + + this.$availableBlocks = []; + + this.$Editor = false; + this.$Areas = false; + + this.addEvents({ + onInject : this.$onInject, + onDestroy : this.$onDestroy + }); + }, + + /** + * Return the HTML Node Element + * + * @return {HTMLElement} + */ + create : function() + { + this.$Elm = new Element('div', { + 'class' : 'quiqqer-blocks-blockedit' + }); + + return this.$Elm; + }, + + /** + * event : on inject + */ + $onInject : function() + { + var self = this; + + Ajax.get([ + 'package_quiqqer_blocks_ajax_getBlock', + 'package_quiqqer_blocks_ajax_getAvailableBlocks' + ], function(data, blocks) + { + self.$availableBlocks = blocks; + + self.setAttributes( data ); + self.$createData(function() { + self.fireEvent( 'loaded', [ self ] ); + }); + + }, { + 'package' : 'quiqqer/block', + blockId : this.getAttribute( 'id' ) + }); + }, + + /** + * event : on destroy + */ + $onDestroy : function() + { + if ( this.$Editor ) { + this.$Editor.destroy(); + } + }, + + /** + * Create the html for the control + * + * @param {Function} [callback] + */ + $createData : function(callback) + { + var self = this; + + new Element('div', { + 'html' : '<label>' + + ' <span class="quiqqer-blocks-blockedit-label-text">' + + ' Title' + + ' </span>' + + ' <input type="text" name="title" />' + + '</label>' + + '<label>' + + ' <span class="quiqqer-blocks-blockedit-label-text">' + + ' Block Typ' + + ' </span>' + + ' <select name="type"></select>' + + '</label>'+ + '<label class="quiqqer-blocks-areas">' + + ' <span class="quiqqer-blocks-blockedit-label-text">' + + ' Erlaubte Blockbereiche' + + ' </span>' + + '</label>' + }).inject( this.$Elm ); + + var i, len, title; + + var Type = this.$Elm.getElement( '[name="type"]'), + Title = this.$Elm.getElement( '[name="title"]' ); + + for ( i = 0, len = this.$availableBlocks.length; i < len; i++ ) + { + title = this.$availableBlocks[ i ].title; + + new Element('option', { + value : this.$availableBlocks[ i ].control, + html : QUILocale.get( title[ 0 ], title[ 1 ] ) + }).inject( Type ); + } + + Title.value = this.getAttribute( 'title' ); + Type.value = this.getAttribute( 'type' ); + + var areas = this.getAttribute( 'areas' ) + .replace( /^,*/, '' ) + .replace( /,*$/, '' ) + .split( ',' ); + + // areas + this.$Areas = new BlockAreas({ + blockId : this.getAttribute( 'id' ), + project : this.getAttribute( 'project' ), + areas : areas, + styles : { + height : 120 + } + }).inject( this.$Elm.getElement( '.quiqqer-blocks-areas' ), 'after' ); + + + // block type + if ( this.getAttribute( 'type' ) == 'content' ) + { + new Element('label', { + html : '<span class="quiqqer-blocks-blockedit-label-editor">' + + 'Block Inhalt' + + '</span>' + }).inject( this.$Elm ); + + + // load ckeditor + require(['classes/editor/Manager'], function(EditorManager) + { + new EditorManager().getEditor(null, function(Editor) + { + self.$Editor = Editor; + + var EditorContainer = new Element('div', { + styles : { + clear : 'both', + height : 300, + width : '100%' + } + }).inject( self.$Elm ); + + self.$Editor.addEvent('onLoaded', function() + { + if ( typeof callback === 'function' ) { + callback(); + } + }); + + self.$Editor.inject( EditorContainer ); + self.$Editor.setHeight( 300 ); + self.$Editor.setContent( self.getAttribute( 'content' ) ); + }); + }); + + return; + } + + // plugin / package blocks + + }, + + /** + * Saves the block + */ + save : function(callback) + { + var Type = this.$Elm.getElement( '[name="type"]'), + Title = this.$Elm.getElement( '[name="title"]' ); + + var data = { + title : Title.value, + type : Type.value, + content : '', + areas : this.$Areas.getAreas().join(',') + }; + + if ( this.$Editor ) { + data.content = this.$Editor.getContent(); + } + + Ajax.post('package_quiqqer_blocks_ajax_block_save', function() + { + if ( typeof callback === 'function' ) { + callback(); + } + }, { + 'package' : 'quiqqer/block', + blockId : this.getAttribute( 'id' ), + data : JSON.encode( data ) + }); + } + + }); +}); diff --git a/bin/Manager.css b/bin/Manager.css new file mode 100644 index 0000000..e98d38a --- /dev/null +++ b/bin/Manager.css @@ -0,0 +1,20 @@ + +.quiqqer-blocks-create label { + clear: both; + float: left; + margin-bottom: 20px; + width: 100%; +} + +.quiqqer-blocks-create input, +.quiqqer-blocks-create select, +.quiqqer-blocks-create-label-text { + clear: both; + float: left; + width: 100%; +} + +.quiqqer-blocks-create-label-text { + cursor: pointer; + margin-bottom: 10px; +} \ No newline at end of file diff --git a/bin/Manager.js b/bin/Manager.js index 109a075..1ba2c3f 100644 --- a/bin/Manager.js +++ b/bin/Manager.js @@ -13,12 +13,15 @@ define('package/quiqqer/blocks/bin/Manager', [ 'qui/controls/buttons/Select', 'qui/controls/buttons/Button', 'qui/controls/buttons/Seperator', + 'qui/controls/windows/Confirm', 'controls/grid/Grid', 'Locale', 'Projects', - 'Ajax' + 'Ajax', -], function(QUI, QUIPanel, QUISelect, QUIButton, QUISeperator, Grid, QUILocale, Projects, Ajax) + 'css!package/quiqqer/blocks/bin/Manager.css' + +], function(QUI, QUIPanel, QUISelect, QUIButton, QUISeperator, QUIConfirm, Grid, QUILocale, Projects, Ajax) { "use strict"; @@ -33,7 +36,9 @@ define('package/quiqqer/blocks/bin/Manager', [ 'loadBlocksFromProject', 'refresh', '$onCreate', - '$onResize' + '$onResize', + '$openCreateDialog', + '$onDblClick' ], options : { @@ -54,8 +59,10 @@ define('package/quiqqer/blocks/bin/Manager', [ /** * Refresh the panel data + * + * @param {Function} [callback] - callback function */ - refresh : function() + refresh : function(callback) { if ( !this.$Elm ) { return; @@ -67,15 +74,18 @@ define('package/quiqqer/blocks/bin/Manager', [ this.getBlocksFromProject(this.$ProjectSelect.getValue(), function(result) { + if ( typeof callback === 'function' ) { + callback(); + } - console.log( result ); + self.$Grid.setData({ + data : result + }); self.Loader.hide(); - }); }, - /** * event : on create */ @@ -96,7 +106,10 @@ define('package/quiqqer/blocks/bin/Manager', [ this.addButton( new QUIButton({ - text : 'Block hinzufügen' + text : 'Block hinzufügen', + events : { + onClick : this.$openCreateDialog + } }) ); @@ -129,6 +142,11 @@ define('package/quiqqer/blocks/bin/Manager', [ }] }); + this.$Grid.addEvents({ + onRefresh : this.refresh, + onDblClick : this.$onDblClick + }); + this.Loader.show(); Projects.getList(function(projects) @@ -172,6 +190,184 @@ define('package/quiqqer/blocks/bin/Manager', [ this.$Grid.setWidth( size.x - 40 ); }, + /** + * event : dbl click + */ + $onDblClick : function() + { + this.editBlock( + this.$Grid.getSelectedData()[0].id + ); + }, + + /** + * + */ + $openCreateDialog : function() + { + var self = this; + + new QUIConfirm({ + title : 'Neuen Block hinzufügen', + icon : 'icon-th', + maxHeight : 300, + maxWidth : 400, + autoclose : false, + events : + { + onOpen : function(Win) + { + var Body = Win.getContent(); + + Win.Loader.show(); + Body.addClass( 'quiqqer-blocks-create' ); + + Body.set( + 'html', + + '<label>' + + ' <span class="quiqqer-blocks-create-label-text">' + + ' Title' + + ' </span>' + + ' <input type="text" name="title" />' + + '</label>' + + '<label>' + + ' <span class="quiqqer-blocks-create-label-text">' + + ' Block Typ' + + ' </span>' + + ' <select name="type"></select>' + + '</label>' + ); + + self.getAvailableBlocks(function(blocklist) + { + if ( !Body ) { + return; + } + + var i, len, title; + var Select = Body.getElement( 'select'), + Title = Body.getElement( '[name="title"]'); + + for ( i = 0, len = blocklist.length; i < len; i++ ) + { + title = blocklist[ i ].title; + + new Element('option', { + value : blocklist[ i ].control, + html : QUILocale.get( title[ 0 ], title[ 1 ] ) + }).inject( Select ); + } + + Title.focus.delay( 500, Title ); + + Win.Loader.hide(); + }); + }, + + onSubmit : function(Win) + { + Win.Loader.show(); + + var Body = Win.getContent(), + Title = Body.getElement( '[name="title"]' ), + Type = Body.getElement( '[name="type"]' ); + + if ( Title.value === '' ) { + return; + } + + self.createBlock(self.$ProjectSelect.getValue(), { + title : Title.value, + type : Type.value + }, function(blockId) + { + Win.close(); + + + self.refresh(function() { + self.editBlock( blockId ); + }); + }); + } + } + }).open(); + }, + + /** + * + * @param {integer} blockId + */ + editBlock : function(blockId) + { + this.Loader.show(); + + var Block; + var self = this, + Sheet = this.createSheet({ + title : 'Block editieren' + }); + + Sheet.addEvents({ + onOpen : function(Sheet) + { + require(['package/quiqqer/blocks/bin/BlockEdit'], function(BlockEdit) + { + Block = new BlockEdit({ + id : blockId, + project : self.$ProjectSelect.getValue(), + events : + { + onLoaded : function() { + self.Loader.hide(); + } + } + }).inject( Sheet.getContent() ); + }); + + Sheet.getContent().setStyle( 'overflow', 'auto' ); + } + }); + + Sheet.addButton({ + textimage : 'icon-save', + text : 'Speichern', + styles : { + width : 200 + }, + events : + { + onClick : function() + { + self.Loader.show(); + + Block.save(function() + { + self.Loader.hide(); + Sheet.hide(); + }); + } + } + }); + + Sheet.show(); + }, + + /** + * Methods / Model + */ + + /** + * Return the available blocks + * @param callback + */ + getAvailableBlocks : function(callback) + { + Ajax.get('package_quiqqer_blocks_ajax_getAvailableBlocks', callback, { + 'package' : 'quiqqer/blocks' + }); + }, + /** * Return the blocksf from a project * @@ -186,6 +382,24 @@ define('package/quiqqer/blocks/bin/Manager', [ name : project }) }); + }, + + /** + * Create a new block + * + * @param {String} project + * @param {Object} data + * @param {Function} callback + */ + createBlock : function(project, data, callback) + { + Ajax.post('package_quiqqer_blocks_ajax_project_createBlock', callback, { + 'package' : 'quiqqer/blocks', + project : JSON.encode({ + name : project + }), + data : JSON.encode( data ) + }); } }); }); diff --git a/database.xml b/database.xml index ea38a7f..23a1388 100644 --- a/database.xml +++ b/database.xml @@ -9,6 +9,8 @@ <field type="TEXT NOT NULL">description</field> <field type="TEXT">settings</field> <field type="VARCHAR( 255 )">type</field> + <field type="TEXT">content</field> + <field type="TEXT">areas</field> </table> </global> diff --git a/lib/QUI/Blocks/Block.php b/lib/QUI/Blocks/Block.php index f8c622b..1adafd1 100644 --- a/lib/QUI/Blocks/Block.php +++ b/lib/QUI/Blocks/Block.php @@ -17,6 +17,12 @@ */ class Block extends QUI\QDOM { + /** + * Block settings + * @var array + */ + protected $_settings = array(); + /** * Constructor * @param array $params - block params @@ -24,38 +30,72 @@ class Block extends QUI\QDOM public function __construct($params=array()) { // default - $this->setAttributes(array( - 'type' => 'content', - 'content' => '', - 'control' => false - )); + $default = array( + 'type' => 'content', + 'content' => '', + 'title' => '', + 'description' => '', + 'project' => '', + 'areas' => '' + ); + + $this->setAttributes( $default ); + + if ( isset( $params['settings'] ) ) + { + $settings = $params['settings']; + + if ( is_string( $settings ) ) { + $settings = json_decode( $settings, true ); + } + + $this->_settings = $settings; + } + + foreach ( $default as $key => $value ) + { + if ( isset( $params[ $key ] ) ) { + $this->setAttribute( $key, $params[ $key ] ); + } + } } /** * Return the HTML of the Block + * + * @throw QUI\Exception */ public function create() { - if ( $this->getAttribute( 'control' ) ) - { - $Ctrl = $this->getAttribute( 'control' ); + if ( $this->getAttribute( 'type' ) == 'content' ) { + return $this->getAttribute( 'content' ); + } - if ( !is_callable( $Ctrl ) ) { - throw new QUI\Exception( 'Control not found. Block could not be create' ); - } - /* @var $Control \QUI\Control */ - $Control = new $Ctrl(); + $Ctrl = $this->getAttribute( 'type' ); - if ( !($Control instanceof QUI\Control) ) { - throw new QUI\Exception( 'Control not found. Block could not be create' ); - } + if ( !is_callable( $Ctrl ) ) { + throw new QUI\Exception( 'Control not found. Block could not be create' ); + } - $Control->setAttributes( $this->getAttributes() ); + /* @var $Control \QUI\Control */ + $Control = new $Ctrl(); - return $Control->create(); + if ( !($Control instanceof QUI\Control) ) { + throw new QUI\Exception( 'Control not found. Block could not be create' ); } - return $this->getAttribute( 'content' ); + $Control->setAttributes( $this->getSettings() ); + + return $Control->create(); + } + + /** + * Return the block settings + * @return array + */ + public function getSettings() + { + return $this->_settings; } } \ No newline at end of file diff --git a/lib/QUI/Blocks/Manager.php b/lib/QUI/Blocks/Manager.php index 00a9b8a..8738505 100644 --- a/lib/QUI/Blocks/Manager.php +++ b/lib/QUI/Blocks/Manager.php @@ -22,6 +22,80 @@ class Manager */ const TABLE = 'blocks'; + /** + * Block temp collector + * @var array + */ + protected $_blocks = array(); + + /** + * Creates a new block for the project + * + * @param Project $Project + * @param Block $Block + * @return integer - Block-ID + */ + public function createBlockForProject(Project $Project, Block $Block) + { + QUI::getDataBase()->insert( + $this->_getTable(), + array( + 'project' => $Project->getName(), + 'title' => $Block->getAttribute('title'), + 'description' => $Block->getAttribute('description'), + 'type' => $Block->getAttribute('type') + ) + ); + + $lastId = QUI::getPDO()->lastInsertId(); + + return $lastId; + } + + /** + * Return the areas which are available in the project + * + * @param Project $Project + * @return array + */ + public function getAreasByProject(Project $Project) + { + $templates = array(); + $blocks = array(); + + $projectName = $Project->getName(); + + // get all vhosts, and the used templates of the project + $vhosts = QUI::getRewrite()->getVHosts(); + + foreach ( $vhosts as $vhost ) + { + if ( !isset( $vhost['template'] ) ) { + continue; + } + + if ( $vhost['project'] != $projectName ) { + continue; + } + + $templates[] = $vhost['template']; + } + + // get blocks + foreach ( $templates as $template ) + { + $blockXML = realpath( OPT_DIR . $template .'/blocks.xml' ); + + if ( !$blockXML ) { + continue; + } + + $blocks = array_merge( $blocks, Utils::getTemplateAreasFromXML( $blockXML ) ); + } + + return $blocks; + } + /** * Returns the available blocks * @@ -44,6 +118,12 @@ public function getAvailableBlocks() $packages = $PKM->getInstalled(); $result = array(); + $result[] = array( + 'title' => array( 'quiqqer/blocks', 'block.content.title' ), + 'description' => array( 'quiqqer/blocks', 'block.content.description' ), + 'control' => 'content' + ); + foreach ( $packages as $package ) { $blocksXML = OPT_DIR . $package['name'] .'/blocks.xml'; @@ -61,6 +141,36 @@ public function getAvailableBlocks() return $result; } + /** + * Get a Block by its Block-ID + * + * @param Integer $id + * @return Block + * @throws QUI\Exception + */ + public function getBlockById($id) + { + if ( isset( $this->_blocks[ $id ] ) ) { + return $this->_blocks[ $id ]; + } + + $data = QUI::getDataBase()->fetch(array( + 'from' => $this->_getTable(), + 'where' => array( + 'id' => (int)$id + ), + 'limit' => 1 + )); + + if ( !isset( $data[0] ) ) { + throw new QUI\Exception( 'Block not found' ); + } + + $this->_blocks[ $id ] = new Block( $data[0] ); + + return $this->_blocks[ $id ]; + } + /** * Return the blocks from the area * @@ -76,7 +186,9 @@ public function getBlocksByArea($blockArea, Site $Site) $blockAreas = $Site->getAttribute( 'quiqqer.blocks.areas' ); - QUI\System\Log::writeRecursive( $blockAreas ); + + + return array(); } @@ -102,6 +214,7 @@ public function getBlocksFromProject(Project $Project) { $Block = new Block(); + $Block->setAttribute( 'id', $entry['id'] ); $Block->setAttribute( 'title', $entry['title'] ); $Block->setAttribute( 'description', $entry['description'] ); @@ -114,6 +227,66 @@ public function getBlocksFromProject(Project $Project) return $result; } + /** + * @param string|integer $blockId - Block-ID + * @param array $blockData - Block data + */ + public function saveBlock($blockId, array $blockData) + { + $Block = $this->getBlockById( $blockId ); + $areas = array(); + $areaString = ''; + + if ( isset( $blockData[ 'id' ] ) ) { + unset( $blockData[ 'id' ] ); + } + + // check areas + $Project = QUI::getProjectManager()->getProject( + $Block->getAttribute( 'project' ) + ); + + $availableAreas = array_map(function($data) + { + if ( isset( $data[ 'name' ] ) ) { + return $data[ 'name' ]; + } + + return ''; + }, $this->getAreasByProject( $Project )); + + + if ( isset( $blockData[ 'areas' ] ) ) + { + $parts = explode( ',', $blockData[ 'areas' ] ); + + foreach ( $parts as $area ) + { + if ( in_array( $area, $availableAreas ) ) { + $areas[] = $area; + } + } + } + + if ( !empty( $areas ) ) { + $areaString = ','. implode( ',', $areas ) .','; + } + + + $Block->setAttributes( $blockData ); + + QUI::getDataBase()->update($this->_getTable(), array( + 'title' => $Block->getAttribute( 'title' ), + 'description' => $Block->getAttribute( 'description' ), + 'content' => $Block->getAttribute( 'content' ), + 'type' => $Block->getAttribute( 'type' ), + 'settings' => json_encode( $Block->getAttribute( 'settings' ) ), + 'areas' => $areaString + ), array( + 'id' => (int)$blockId + )); + } + /** * Returns the blocks table name * @return String diff --git a/lib/QUI/Blocks/Utils.php b/lib/QUI/Blocks/Utils.php index 4bc599c..b4f2961 100644 --- a/lib/QUI/Blocks/Utils.php +++ b/lib/QUI/Blocks/Utils.php @@ -41,39 +41,99 @@ static function getBlocksFromXML($file) return $list; } - foreach ( $blocks as $Block ) + foreach ( $blocks as $Block ) { + $list[] = self::parseBlockToArray( $Block, $Path ); + } + + return $list; + } + + /** + * Return the template blocks from a xml file + * + * @param string $file - path to xm file + * @return array + */ + static function getTemplateAreasFromXML($file) + { + if ( !file_exists( $file ) ) { + return array(); + } + + $Dom = XML::getDomFromXml( $file ); + $Path = new \DOMXPath( $Dom ); + + $globalBlocks = $Path->query( "//quiqqer/blocks/templateAreas/areas/area" ); + $typeBlocks = $Path->query( "//quiqqer/blocks/templateAreas/types/type/area" ); + + $list = array(); + + if ( $globalBlocks->length ) { - /* @var $Block \DOMElement */ - $control = $Block->getAttribute( 'control' ); - $title = array(); - $description = array(); - - $titleLocale = $Path->query( './title/locale', $Block ); - $descLocale = $Path->query( './description/locale', $Block ); - - if ( $titleLocale->length ) - { - $title = array( - 'group' => $titleLocale->item( 0 )->getAttribute( 'group' ), - 'var' => $titleLocale->item( 0 )->getAttribute( 'var' ) - ); + foreach ( $globalBlocks as $Block ) { + $list[] = self::parseBlockToArray( $Block, $Path ); } + } - if ( $descLocale->length ) - { - $description = array( - 'group' => $descLocale->item( 0 )->getAttribute( 'group' ), - 'var' => $descLocale->item( 0 )->getAttribute( 'var' ) - ); + if ( $typeBlocks->length ) + { + foreach ( $typeBlocks as $Block ) { + $list[] = self::parseBlockToArray( $Block, $Path ); } + } - $list[] = array( - 'control' => $control, - 'title' => $title, - 'description' => $description + return $list; + } + + + static function getGlobalTemplateAreasFromXML() + { + + } + + static function getTypeTemplateAreasFromXML($file, $siteType) + { + + } + + /** + * parse a <block> xml node to an array + * + * @param \DOMElement $Block + * @param \DOMXPath $Path + * @return array + */ + static function parseBlockToArray(\DOMElement $Block, \DOMXPath $Path) + { + $control = $Block->getAttribute( 'control' ); + $name = $Block->getAttribute( 'name' ); + $title = array(); + $description = array(); + + $titleLocale = $Path->query( './title/locale', $Block ); + $descLocale = $Path->query( './description/locale', $Block ); + + if ( $titleLocale->length ) + { + $title = array( + 'group' => $titleLocale->item( 0 )->getAttribute( 'group' ), + 'var' => $titleLocale->item( 0 )->getAttribute( 'var' ) ); } - return $list; + if ( $descLocale->length ) + { + $description = array( + 'group' => $descLocale->item( 0 )->getAttribute( 'group' ), + 'var' => $descLocale->item( 0 )->getAttribute( 'var' ) + ); + } + + return array( + 'control' => $control, + 'name' => $name, + 'title' => $title, + 'description' => $description + ); } } -- GitLab