diff --git a/ajax/backend/independent/getItemTypes.php b/ajax/backend/independent/getItemTypes.php index 5441758cc65898060edcafbc97303c621c1313cb..d11ecfe08db0fedd4befc260e5ddc898ee2ad912 100644 --- a/ajax/backend/independent/getItemTypes.php +++ b/ajax/backend/independent/getItemTypes.php @@ -18,6 +18,7 @@ function () { foreach ($list as $class) { $result[] = [ 'title' => call_user_func([$class, 'itemTitle']), + 'desc' => call_user_func([$class, 'itemShort']), 'icon' => call_user_func([$class, 'itemIcon']), 'jsControl' => call_user_func([$class, 'itemJsControl']), 'class' => $class diff --git a/bin/Controls/Independent/MenuManagement.js b/bin/Controls/Independent/MenuManagement.js index dbbf53b3c77c0ca15168f9ac38dc7eb51286c1ad..a0238a1cc40dc066f4a5d295e0afb681ebd87d16 100644 --- a/bin/Controls/Independent/MenuManagement.js +++ b/bin/Controls/Independent/MenuManagement.js @@ -110,10 +110,16 @@ define('package/quiqqer/menu/bin/Controls/Independent/MenuManagement', [ width : 50 }, { - header : QUILocale.get(lg, 'grid.menuTitle'), + header : QUILocale.get(lg, 'menu.title'), dataIndex: 'title', dataType : 'string', - width : 150 + width : 250 + }, + { + header : QUILocale.get(lg, 'menu.workingTitle'), + dataIndex: 'workingTitle', + dataType : 'string', + width : 350 } ] }); diff --git a/bin/Controls/Independent/MenuPanel.Create.html b/bin/Controls/Independent/MenuPanel.Create.html deleted file mode 100644 index 8390321ce89b1b84163525abc3f102291920c516..0000000000000000000000000000000000000000 --- a/bin/Controls/Independent/MenuPanel.Create.html +++ /dev/null @@ -1,20 +0,0 @@ -<form> - <p>{{text}}</p> - <table class="data-table data-table-flexbox" style="margin-top: 20px"> - <tbody> - <tr> - <td> - <label class="field-container"> - <span class="field-container-item" title="{{textType}}"> - {{textType}} - </span> - <select type="text" - class="field-container-field" - name="itemType" - ></select> - </label> - </td> - </tr> - </tbody> - </table> -</form> \ No newline at end of file diff --git a/bin/Controls/Independent/MenuPanel.ItemCard.html b/bin/Controls/Independent/MenuPanel.ItemCard.html new file mode 100644 index 0000000000000000000000000000000000000000..49efe9c0e3074a00bf2e851d92c4613e64aafadf --- /dev/null +++ b/bin/Controls/Independent/MenuPanel.ItemCard.html @@ -0,0 +1,10 @@ +<div class="qui-menuPanel-optionList__option-image"> + <span class="{{icon}}"></span> +</div> +<div class="qui-menuPanel-optionList__option-content"> + <div class="qui-menuPanel-optionList__option-title"> + <input type="radio" name="itemType" data-icon="{{icon}}" value="{{value}}" style="display: none;"> + <span>{{title}}</span> + </div> + <div class="qui-menuPanel-optionList__option-desc">{{desc}}</div> +</div> \ No newline at end of file diff --git a/bin/Controls/Independent/MenuPanel.css b/bin/Controls/Independent/MenuPanel.css index 598ea85e2922d7494f73fd328bdcf72175b48b04..fb31d44bec02cb529dd0c7f0a5ede1d74c9833c9 100644 --- a/bin/Controls/Independent/MenuPanel.css +++ b/bin/Controls/Independent/MenuPanel.css @@ -20,3 +20,51 @@ .quiqqer-menu-menuPanel-innerContainer > div { width: 100%; } + +/****************************************/ +/* Options list: create and edit window */ +/****************************************/ +.qui-menuPanel-optionList { + display: grid; + gap: 1rem; + grid-template-columns: 1fr 1fr; + grid-template-rows: auto; + margin-top: 3rem; +} + +.qui-menuPanel-optionList__option { + background: #f5f5f5; + padding: 1rem 1.5rem; + border-radius: 1rem; + cursor: pointer; + display: flex; + gap: 0.5rem 1.5rem; +} + +.qui-menuPanel-optionList__option-image { + font-size: 3rem; + width: 4rem; + flex-shrink: 0; + text-align: center; + align-self: flex-start; + opacity: 0.5; +} + +.qui-menuPanel-optionList__option-title { + margin-bottom: 0.25rem; + font-weight: bold; +} + +.qui-menuPanel-optionList__option-desc { + opacity: 0.75; +} + +/* checked */ +.qui-menuPanel-optionList__option.checked { + outline: 2px solid; + outline-offset: -2px; +} + +.qui-menuPanel-optionList__option.checked .qui-menuPanel-optionList__option-image { + opacity: 1; +} \ No newline at end of file diff --git a/bin/Controls/Independent/MenuPanel.js b/bin/Controls/Independent/MenuPanel.js index 01b3ca3d5554a45b7f69b09a9bad1f941bd3b130..0f3ecc57ab63866a12fd919555773ed6388ac385 100644 --- a/bin/Controls/Independent/MenuPanel.js +++ b/bin/Controls/Independent/MenuPanel.js @@ -18,13 +18,13 @@ define('package/quiqqer/menu/bin/Controls/Independent/MenuPanel', [ 'package/quiqqer/menu/bin/classes/IndependentHandler', 'Mustache', - 'text!package/quiqqer/menu/bin/Controls/Independent/MenuPanel.Create.html', + 'text!package/quiqqer/menu/bin/Controls/Independent/MenuPanel.ItemCard.html', 'text!package/quiqqer/menu/bin/Controls/Independent/MenuPanel.Settings.html', 'css!package/quiqqer/menu/bin/Controls/Independent/MenuPanel.css' ], function (QUI, QUIPanel, QUIMap, QUIMapItem, QUIConfirm, QUIContextMenu, QUIContextMenuItem, QUIContextSeparator, InputMultiLang, - QUIAjax, QUILocale, IndependentHandler, Mustache, templateCreate, templateSettings) { + QUIAjax, QUILocale, IndependentHandler, Mustache, templateItemCard, templateSettings) { "use strict"; const lg = 'quiqqer/menu'; @@ -232,7 +232,7 @@ define('package/quiqqer/menu/bin/Controls/Independent/MenuPanel', [ if (text === '' || text === '###') { text = '?'; } - + Item = new QUIMapItem({ text : text, icon : data.typeIcon, @@ -303,6 +303,8 @@ define('package/quiqqer/menu/bin/Controls/Independent/MenuPanel', [ }; }; + this.setMenuTitle(); + let result = toArray(this.$Map.firstChild()); return this.$refreshItemDisplay().then(() => { @@ -317,6 +319,42 @@ define('package/quiqqer/menu/bin/Controls/Independent/MenuPanel', [ }); }, + /** + * Set the title of this.$Map, so the title changes in the left panel. + * Also set menu title and working title to the variables: + * this.$title + * this.$workingTitle + * + * This function is a small workaround for this user flow: + * "User change the menu title (and working title) and save directly the menu by clicking save-button". + */ + setMenuTitle: function() { + const selected = this.$Map.getSelectedChildren(); + + if (selected.length === 1 && selected[0].getAttribute('value') !== 'start') { + return; + } + + const Title = this.$InnerContainer.getElement('[name="title"]'); + const WorkingTitle = this.$InnerContainer.getElement('[name="workingTitle"]'); + + if (!Title) { + return; + } + + selected[0].setAttribute('itemTitle', Title.value); + + this.$title = JSON.decode(Title.value); + this.$workingTitle = JSON.decode(WorkingTitle.value); + + let current = QUILocale.getCurrent(); + + if (current in this.$title) { + selected[0].setAttribute('text', this.$title[current]); + selected[0].setAttribute('title', this.$title[current]); + } + }, + addItem: function (Parent, where) { if (typeof where === 'undefined') { where = 'bottom'; @@ -335,8 +373,8 @@ define('package/quiqqer/menu/bin/Controls/Independent/MenuPanel', [ new QUIConfirm({ icon : 'fa fa-plus', title : QUILocale.get(lg, 'quiqqer.menu.independent.addItem.title'), - maxHeight: 400, - maxWidth : 500, + maxHeight: 550, + maxWidth : 700, autoclose: false, events : { onOpen: (Win) => { @@ -344,25 +382,18 @@ define('package/quiqqer/menu/bin/Controls/Independent/MenuPanel', [ Win.Loader.show(); - Content.set('html', Mustache.render(templateCreate, { - text : QUILocale.get(lg, 'create.window.text'), - textTitle: QUILocale.get('quiqqer/quiqqer', 'title'), - textName : QUILocale.get('quiqqer/quiqqer', 'name'), - textType : QUILocale.get('quiqqer/quiqqer', 'type') - })); + Content.set( + 'html', - IndependentHandler.getItemTypes().then((list) => { - const Types = Content.getElement('[name="itemType"]'); - - for (let i = 0, len = list.length; i < len; i++) { - new Element('option', { - html : list[i].title, - value : list[i].class, - 'data-icon': list[i].icon - }).inject(Types); - } + `<p>`+ QUILocale.get(lg, 'create.window.text') + + '</p>' + + '<form style="width: 100%;">' + + ' <div class="qui-menuPanel-optionList"></div>' + + '</form>' + ); - Types.value = 'QUI\\Menu\\Independent\\Items\\Site'; + IndependentHandler.getItemTypes().then((list) => { + this.$createOptionList(list, Content); return QUI.parse(Win.getContent()); }).then(function () { @@ -376,8 +407,8 @@ define('package/quiqqer/menu/bin/Controls/Independent/MenuPanel', [ let type = Form.elements.itemType.value; - const Option = Form.elements.itemType.getElement( - 'option[value="' + CSS.escape(type) + '"]' + const Option = Form.getElement( + '[value="' + CSS.escape(type) + '"]' ); let itemAttributes = { @@ -429,11 +460,13 @@ define('package/quiqqer/menu/bin/Controls/Independent/MenuPanel', [ return; } + const itemType = Item.getAttribute('itemType'); + new QUIConfirm({ icon : 'fa fa-edit', title : QUILocale.get(lg, 'quiqqer.menu.independent.changeItemType.title'), - maxHeight: 400, - maxWidth : 500, + maxHeight: 550, + maxWidth : 700, autoclose: false, events : { onOpen: (Win) => { @@ -442,27 +475,17 @@ define('package/quiqqer/menu/bin/Controls/Independent/MenuPanel', [ Content.set( 'html', - QUILocale.get(lg, 'quiqqer.menu.independent.changeItemType.message') + - '' + - '<form style="width: 100%; text-align: center; margin-top: 20px">' + - ' <select name="itemType"></select>' + + `<p>`+ QUILocale.get(lg, 'quiqqer.menu.independent.changeItemType.message') + + '</p>' + + '<form style="width: 100%;">' + + ' <div class="qui-menuPanel-optionList"></div>' + '</form>' ); Win.Loader.show(); IndependentHandler.getItemTypes().then((list) => { - const Types = Content.getElement('[name="itemType"]'); - - for (let i = 0, len = list.length; i < len; i++) { - new Element('option', { - html : list[i].title, - value : list[i].class, - 'data-icon': list[i].icon - }).inject(Types); - } - - Types.value = Item.getAttribute('itemType'); + this.$createOptionList(list, Content, itemType); return QUI.parse(Win.getContent()); }).then(function () { @@ -477,8 +500,8 @@ define('package/quiqqer/menu/bin/Controls/Independent/MenuPanel', [ const Form = Content.getElement('form'); const type = Form.elements.itemType.value; - const Option = Form.elements.itemType.getElement( - 'option[value="' + CSS.escape(type) + '"]' + const Option = Form.getElement( + '[value="' + CSS.escape(type) + '"]' ); Item.setAttribute('itemType', type); @@ -496,6 +519,47 @@ define('package/quiqqer/menu/bin/Controls/Independent/MenuPanel', [ }).open(); }, + /** + * Create custom option list based on passed list of menu types + * + * @param list + * @param Content + * @param selected + */ + $createOptionList: function(list, Content, selected = false) { + const OptionsList = Content.getElement('.qui-menuPanel-optionList'), + selectedItem = selected ? selected : 'QUI\\Menu\\Independent\\Items\\Site'; + + const toggleSelected = function(event) { + OptionsList.getElements('label').forEach(function(Label) { + Label.classList.remove('checked'); + }); + + event.target.getParent('label').classList.add('checked'); + }; + + for (let i = 0, len = list.length; i < len; i++) { + const Item = list[i]; + const Label = new Element('label', { + 'class': 'qui-menuPanel-optionList__option', + html: Mustache.render(templateItemCard, { + title: Item.title, + desc: Item.desc, + icon: Item.icon, + value: Item.class + }) + }); + + if (Item.class === selectedItem) { + Label.querySelector('input').checked = true; + Label.classList.add('checked'); + } + + Label.inject(OptionsList); + Label.getElement('input').addEventListener('change', toggleSelected); + } + }, + /** * @param Item */ @@ -580,12 +644,15 @@ define('package/quiqqer/menu/bin/Controls/Independent/MenuPanel', [ this.$ActiveItem = null; this.$ActiveMapItem = null; this.$InnerContainer.set('html', Mustache.render(templateSettings, { - settingsTitle: QUILocale.get('quiqqer/quiqqer', 'settings'), - title : QUILocale.get('quiqqer/quiqqer', 'title') + title : QUILocale.get('quiqqer/menu', 'menu.title'), + workingTitle: QUILocale.get('quiqqer/menu', 'menu.workingTitle') })); - this.$InnerContainer.getElement('[name="title"]').set('value', JSON.stringify(this.$title)); - this.$InnerContainer.getElement('[name="workingTitle"]').set('value', JSON.stringify(this.$workingTitle)); + const TitleNode = this.$InnerContainer.getElement('[name="title"]'), + WorkingTitleNode = this.$InnerContainer.getElement('[name="workingTitle"]'); + + TitleNode.set('value', JSON.stringify(this.$title)); + WorkingTitleNode.set('value', JSON.stringify(this.$workingTitle)); }).then(() => { return QUI.parse(this.$InnerContainer); }).then(() => { diff --git a/locale.xml b/locale.xml index 9ca23ccf52d5a65773d698db848a21b1af449d3c..ceb83ae4cf43ba7993832a6779134efb4dfc2e21 100644 --- a/locale.xml +++ b/locale.xml @@ -527,18 +527,34 @@ <de><![CDATA[Menu Eintrag: Zu einem Anker]]></de> <en><![CDATA[Menu entry: To an anchor]]></en> </locale> + <locale name="item.anchor.short"> + <de><![CDATA[Mit diesem Menütyp ist es möglich, eine interne QUIQQER-Seite auszuwählen und einen Anker festzulegen.]]></de> + <en><![CDATA[With this menu type it is possible to select an internal QUIQQER page and define an anchor.]]></en> + </locale> <locale name="item.custom.title"> <de><![CDATA[Menu Eintrag: Custom Event]]></de> <en><![CDATA[Menu entry: Custom Event]]></en> </locale> + <locale name="item.custom.short"> + <de><![CDATA[Individuelle Anpassung des Menüpunktes. Man kann eine Seite auswählen, eine benutzerdefinierte JavaScript-Funktion aufrufen und vieles mehr.]]></de> + <en><![CDATA[Customisation of the menu item. You can select a page, call up a customised JavaScript function and much more.]]></en> + </locale> <locale name="item.site.title"> <de><![CDATA[Menu Eintrag: Zu einer internen Seite von einem Projekt]]></de> <en><![CDATA[Menu entry: To an internal page from a project]]></en> </locale> + <locale name="item.site.short"> + <de><![CDATA[Erlaubt die Auswahl eines interner QUIQQER Seite.]]></de> + <en><![CDATA[Allows selection of an internal QUIQQER page.Klicken, um Alternative zu verwenden]]></en> + </locale> <locale name="item.url.title"> <de><![CDATA[Menu Eintrag: Zu einer anderen URL]]></de> <en><![CDATA[Menu entry: To another URL]]></en> </locale> + <locale name="item.url.short"> + <de><![CDATA[Es ist möglich, sowohl eine interne QUIQQER Seite auszuwählen als auch den Link zu einer externen Seiten zu setzen.]]></de> + <en><![CDATA[It is possible to select both an internal QUIQQER page and a link to an external page.]]></en> + </locale> <locale name="menu.saved.successfully"> <de><![CDATA[Das Menü wurde erfolgreich gespeichert.]]></de> <en><![CDATA[The menu has been saved successfully.]]></en> @@ -554,10 +570,14 @@ <de><![CDATA[ID]]></de> <en><![CDATA[ID]]></en> </locale> - <locale name="grid.menuTitle"> + <locale name="menu.title"> <de><![CDATA[Titel]]></de> <en><![CDATA[Title]]></en> </locale> + <locale name="menu.workingTitle"> + <de><![CDATA[Arbeitstitel]]></de> + <en><![CDATA[Working title]]></en> + </locale> <locale name="creation.window.title"> <de><![CDATA[Neues Menü anlegen]]></de> diff --git a/src/QUI/Menu/Independent/Handler.php b/src/QUI/Menu/Independent/Handler.php index fc4f29aa30e0ddfe7ef8e455eee09daa10b9d651..e1b357bf2223af561e92f38a6b45300fa70c6dfa 100644 --- a/src/QUI/Menu/Independent/Handler.php +++ b/src/QUI/Menu/Independent/Handler.php @@ -115,10 +115,10 @@ public static function getList(): array public static function getItemList(): array { return [ - QUI\Menu\Independent\Items\Anchor::class, - QUI\Menu\Independent\Items\Custom::class, QUI\Menu\Independent\Items\Site::class, + QUI\Menu\Independent\Items\Anchor::class, QUI\Menu\Independent\Items\Url::class, + QUI\Menu\Independent\Items\Custom::class, ]; } } diff --git a/src/QUI/Menu/Independent/Items/AbstractMenuItem.php b/src/QUI/Menu/Independent/Items/AbstractMenuItem.php index f28254a3d10023b2f897f0b8fe006232a0307e62..ae5d311978fbb883914dd897099fec64c532ff91 100644 --- a/src/QUI/Menu/Independent/Items/AbstractMenuItem.php +++ b/src/QUI/Menu/Independent/Items/AbstractMenuItem.php @@ -270,6 +270,16 @@ public function getStatus(): bool abstract public static function itemTitle(); + /** + * Short description of the menu types + * + * @return string + */ + public static function itemShort(): string + { + return ''; + } + /** * @return string */ diff --git a/src/QUI/Menu/Independent/Items/Anchor.php b/src/QUI/Menu/Independent/Items/Anchor.php index 9f1ffc769f9a9f3086a4044e352afe177c72a3cd..79dac31f3f4c2107ac303c09e82e6c10ad41d296 100644 --- a/src/QUI/Menu/Independent/Items/Anchor.php +++ b/src/QUI/Menu/Independent/Items/Anchor.php @@ -103,6 +103,16 @@ public static function itemTitle(): string return QUI::getLocale()->get('quiqqer/menu', 'item.anchor.title'); } + /** + * Short description of the menu types + * + * @return string + */ + public static function itemShort(): string + { + return QUI::getLocale()->get('quiqqer/menu', 'item.anchor.short'); + } + /** * @return string */ diff --git a/src/QUI/Menu/Independent/Items/Custom.php b/src/QUI/Menu/Independent/Items/Custom.php index 60f0ffe8ea408bea9ceab719ed5b1e4c1fa58c62..c6d696235eee7b55abf727c2cf05b164c3554701 100644 --- a/src/QUI/Menu/Independent/Items/Custom.php +++ b/src/QUI/Menu/Independent/Items/Custom.php @@ -42,6 +42,16 @@ public static function itemTitle(): string return QUI::getLocale()->get('quiqqer/menu', 'item.custom.title'); } + /** + * Short description of the menu types + * + * @return string + */ + public static function itemShort(): string + { + return QUI::getLocale()->get('quiqqer/menu', 'item.custom.short'); + } + /** * return the item type icon * diff --git a/src/QUI/Menu/Independent/Items/Site.php b/src/QUI/Menu/Independent/Items/Site.php index fd143b4b9959a250a9e62c264d680384194bb2b6..884fa312460ae272d59dc6f2e58e2bbc545fa2a1 100644 --- a/src/QUI/Menu/Independent/Items/Site.php +++ b/src/QUI/Menu/Independent/Items/Site.php @@ -22,6 +22,16 @@ public static function itemTitle(): string return QUI::getLocale()->get('quiqqer/menu', 'item.site.title'); } + /** + * Short description of the menu types + * + * @return string + */ + public static function itemShort(): string + { + return QUI::getLocale()->get('quiqqer/menu', 'item.site.short'); + } + /** * @return string */ diff --git a/src/QUI/Menu/Independent/Items/Url.php b/src/QUI/Menu/Independent/Items/Url.php index 52eef4297d0035b782c662acd27b41e96bc23dfd..a9af047d444d7c1ada94aff07cd8ab7dd64f6453 100644 --- a/src/QUI/Menu/Independent/Items/Url.php +++ b/src/QUI/Menu/Independent/Items/Url.php @@ -35,6 +35,16 @@ public static function itemTitle(): string return QUI::getLocale()->get('quiqqer/menu', 'item.url.title'); } + /** + * Short description of the menu types + * + * @return string + */ + public static function itemShort(): string + { + return QUI::getLocale()->get('quiqqer/menu', 'item.url.short'); + } + /** * @return string */