From 690ec1e5dbdfda255001eedd63344c26d927c05a Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Fri, 6 Mar 2015 20:41:14 +1100 Subject: [PATCH] Improvements made to the user menu in the back-end Clicking your avatar will display a popover with settings links from the mysettings context. --- CHANGELOG.md | 1 + modules/backend/assets/js/october-min.js | 91 +++++++++++++--- modules/backend/assets/js/october.js | 1 + modules/backend/assets/js/october.layout.js | 24 ++++- .../backend/assets/less/core/variables.less | 3 + .../backend/assets/less/layout/mainmenu.less | 100 +++++++++++++++--- modules/backend/layouts/_mainmenu.htm | 61 ++++++----- .../system/controllers/settings/update.htm | 2 +- 8 files changed, 222 insertions(+), 61 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 07a9804e2..905b28b99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ * **Build 217** (2015-03-06) + - Improvements made to the user menu in the back-end: clicking your avatar will display a popover with settings links from the `mysettings` context. - Added new form field widget called `repeater` for repeatable fields (see Backend > Forms docs). - Made some UI improvements to the Rich Editor. - Form widget base class no longer takes a model as the 2nd argument, it should be passed as `model` in the configuration instead. diff --git a/modules/backend/assets/js/october-min.js b/modules/backend/assets/js/october-min.js index 3e0844cfa..c96d93792 100644 --- a/modules/backend/assets/js/october-min.js +++ b/modules/backend/assets/js/october-min.js @@ -78,8 +78,8 @@ if(this.options.triggerAction===false) throw new Error('Trigger action is not specified.') this.triggerCondition=this.options.triggerCondition if(this.options.triggerCondition.indexOf('value')==0){var match=this.options.triggerCondition.match(/[^[\]]+(?=])/g) -if(match){this.triggerConditionValue=match -this.triggerCondition='value'}} +this.triggerCondition='value' +this.triggerConditionValue=(match)?match:""} if(this.triggerCondition=='checked'||this.triggerCondition=='value') $(document).on('change',this.options.trigger,$.proxy(this.onConditionChanged,this)) var self=this @@ -223,7 +223,64 @@ methodArgs.push(args[i]) data[option].apply(data,methodArgs)}})} $.fn.dragScroll.Constructor=DragScroll $.fn.dragScroll.noConflict=function(){$.fn.dragScroll=old -return this}}(window.jQuery);+function($){"use strict";var Toolbar=function(element,options){var +return this}}(window.jQuery);+function($){"use strict";var DragValue=function(element,options){this.options=options +this.$el=$(element) +this.init()} +DragValue.DEFAULTS={dragClick:false} +DragValue.prototype.init=function(){this.$el.prop('draggable',true) +this.textValue=this.$el.data('textValue') +this.$el.on('dragstart',$.proxy(this.handleDragStart,this)) +this.$el.on('drop',$.proxy(this.handleDrop,this)) +this.$el.on('dragend',$.proxy(this.handleDragEnd,this)) +if(this.options.dragClick){this.$el.on('click',$.proxy(this.handleClick,this)) +this.$el.on('mouseover',$.proxy(this.handleMouseOver,this))}} +DragValue.prototype.handleDragStart=function(event){var e=event.originalEvent +e.dataTransfer.effectAllowed='all' +e.dataTransfer.setData('text/plain',this.textValue) +this.$el.css({opacity:0.5}).addClass('dragvalue-dragging')} +DragValue.prototype.handleDrop=function(event){event.stopPropagation() +return false} +DragValue.prototype.handleDragEnd=function(event){this.$el.css({opacity:1}).removeClass('dragvalue-dragging')} +DragValue.prototype.handleMouseOver=function(event){var el=document.activeElement +if(!el)return +if(el.isContentEditable||(el.tagName.toLowerCase()=='input'&&el.type=='text'||el.tagName.toLowerCase()=='textarea')){this.lastElement=el}} +DragValue.prototype.handleClick=function(event){if(!this.lastElement)return +var $el=$(this.lastElement) +if($el.hasClass('ace_text-input')) +return this.handleClickCodeEditor(event,$el) +if(this.lastElement.isContentEditable) +return this.handleClickContentEditable() +this.insertAtCaret(this.lastElement,this.textValue)} +DragValue.prototype.handleClickCodeEditor=function(event,$el){var $editorArea=$el.closest('[data-control=codeeditor]') +if(!$editorArea.length)return +$editorArea.codeEditor('getEditorObject').insert(this.textValue)} +DragValue.prototype.handleClickContentEditable=function(){var sel,range,html;if(window.getSelection){sel=window.getSelection();if(sel.getRangeAt&&sel.rangeCount){range=sel.getRangeAt(0);range.deleteContents();range.insertNode(document.createTextNode(this.textValue));}} +else if(document.selection&&document.selection.createRange){document.selection.createRange().text=this.textValue;}} +DragValue.prototype.insertAtCaret=function(el,insertValue){if(document.selection){el.focus() +sel=document.selection.createRange() +sel.text=insertValue +el.focus()} +else if(el.selectionStart||el.selectionStart=='0'){var startPos=el.selectionStart,endPos=el.selectionEnd,scrollTop=el.scrollTop +el.value=el.value.substring(0,startPos)+insertValue+el.value.substring(endPos,el.value.length) +el.focus() +el.selectionStart=startPos+insertValue.length +el.selectionEnd=startPos+insertValue.length +el.scrollTop=scrollTop} +else{el.value+=insertValue +el.focus()}} +var old=$.fn.dragValue +$.fn.dragValue=function(option){var args=Array.prototype.slice.call(arguments,1),result +this.each(function(){var $this=$(this) +var data=$this.data('oc.dragvalue') +var options=$.extend({},DragValue.DEFAULTS,$this.data(),typeof option=='object'&&option) +if(!data)$this.data('oc.dragvalue',(data=new DragValue(this,options))) +if(typeof option=='string')result=data[option].apply(data,args) +if(typeof result!='undefined')return false}) +return result?result:this} +$.fn.dragValue.Constructor=DragValue +$.fn.dragValue.noConflict=function(){$.fn.dragValue=old +return this} +$(document).render(function(){$('[data-control="dragvalue"]').dragValue()});}(window.jQuery);+function($){"use strict";var Toolbar=function(element,options){var $el=this.$el=$(element),$toolbar=$el.closest('.control-toolbar') this.options=options||{};var scrollClassContainer=options.scrollClassContainer!==undefined?options.scrollClassContainer:$el.parent() $el.dragScroll({scrollClassContainer:scrollClassContainer}) @@ -697,6 +754,7 @@ if(!data)$this.data('oc.popup',(data=new Popup(this,options))) else if(typeof option=='string')data[option].apply(data,args) else data.reload()})} $.fn.popup.Constructor=Popup +$.popup=function(option){return $('').popup(option)} $.fn.popup.noConflict=function(){$.fn.popup=old return this} $(document).on('click.oc.popup','[data-control="popup"]',function(){$(this).popup() @@ -1058,7 +1116,7 @@ if(!data)$this.data('oc.inputPreset',(data=new InputPreset(this,options)))})} $.fn.inputPreset.Constructor=InputPreset $.fn.inputPreset.noConflict=function(){$.fn.inputPreset=old return this} -$(document).render(function(){$('[data-input-preset]').inputPreset()})}(window.jQuery);(function($){var OctoberLayout=function(){} +$(document).render(function(){$('[data-input-preset]').inputPreset()})}(window.jQuery);(function($){var OctoberLayout=function(){this.$accountMenuOverlay=null} OctoberLayout.prototype.setPageTitle=function(title){var $title=$('title') if(this.pageTitleTemplate===undefined) this.pageTitleTemplate=$title.data('titleTemplate') @@ -1067,6 +1125,14 @@ OctoberLayout.prototype.updateLayout=function(title){$('.layout-cell.width-fix') $el.data('oc.layoutMargin',margin)} $(this).width($el.get(0).offsetWidth+margin) $(this).trigger('oc.widthFixed')}})} +OctoberLayout.prototype.toggleAccountMenu=function(el){var self=this,$menu=$(el).next() +if($menu.hasClass('active')){self.$accountMenuOverlay.remove() +$menu.removeClass('active')} +else{self.$accountMenuOverlay=$('
').addClass('popover-overlay') +$(document.body).append(self.$accountMenuOverlay) +$menu.addClass('active') +self.$accountMenuOverlay.one('click',function(){self.$accountMenuOverlay.remove() +$menu.removeClass('active')})}} if($.oc===undefined) $.oc={} $.oc.layout=new OctoberLayout() @@ -1121,20 +1187,15 @@ this.$el.css({left:this.sideNavWidth,top:this.mainNavHeight}) this.updatePanelPosition() $(window).trigger('resize')} SidePanelTab.prototype.hideSidePanel=function(){$(document.body).removeClass('display-side-panel') -if(this.$el.next('#layout-body').length==0) -$('#layout-body').before(this.$el) +if(this.$el.next('#layout-body').length==0){$('#layout-body').before(this.$el)} this.panelVisible=false this.updateActiveTab()} -SidePanelTab.prototype.updatePanelPosition=function(){if(!this.panelFixed()||Modernizr.touch) -this.$el.height($(document).height()-this.mainNavHeight) -else -this.$el.css('height','') -if(this.panelVisible&&$(window).width()>this.options.breakpoint&&this.panelFixed()) -this.hideSidePanel()} -SidePanelTab.prototype.updateActiveTab=function(){if(!this.panelVisible&&($(window).width()this.options.breakpoint&&this.panelFixed()){this.hideSidePanel()}} +SidePanelTab.prototype.updateActiveTab=function(){if(!this.panelVisible&&($(window).width()').addClass('popover-overlay') + $(document.body).append(self.$accountMenuOverlay) + $menu.addClass('active') + + self.$accountMenuOverlay.one('click', function(){ + self.$accountMenuOverlay.remove() + $menu.removeClass('active') + }) + } + } + if ($.oc === undefined) $.oc = {} diff --git a/modules/backend/assets/less/core/variables.less b/modules/backend/assets/less/core/variables.less index da9f55e2e..e7b9175e7 100644 --- a/modules/backend/assets/less/core/variables.less +++ b/modules/backend/assets/less/core/variables.less @@ -64,6 +64,9 @@ @color-mainmenu-active: #ffffff; @color-mainmenu-collapsed: #333333; +@color-accountmenu-bg: #3d3d3d; +@color-accountmenu-divider: #343434; + @color-footer: rgba(255,255,255,.8); @color-footer-border: #dfdfdf; @color-footer-text: #666666; diff --git a/modules/backend/assets/less/layout/mainmenu.less b/modules/backend/assets/less/layout/mainmenu.less index 37ba22120..6937f9cdf 100644 --- a/modules/backend/assets/less/layout/mainmenu.less +++ b/modules/backend/assets/less/layout/mainmenu.less @@ -13,7 +13,7 @@ nav#layout-mainmenu.navbar { padding: 0 0 0 20px; line-height: 0; white-space: nowrap; - + a { text-decoration: none; &:focus { @@ -36,7 +36,7 @@ nav#layout-mainmenu.navbar { margin-right: 30px; position: relative; - &:last-child {margin-right: 0;} + &:last-child { margin-right: 0; } &.active { &:after { @@ -50,19 +50,26 @@ nav#layout-mainmenu.navbar { &.icon { margin-right: 0; - i {margin-right: 0;} - a {padding: 14px;} + i { margin-right: 0; } + a { padding: 14px; } } &.power-off, &.preview { - i {font-size: 20px;} - a {padding: 22px 20px 20px 20px;} + i { font-size: 20px; } + a { padding: 22px 20px 20px 20px; } } &.account { margin-right: 0; line-height: 23px; + a { + padding-left: 35px; + padding-right: 5px; + position: relative; + z-index: 900; + } + img { width: 25px; margin-right: 7px; @@ -72,19 +79,78 @@ nav#layout-mainmenu.navbar { } } - &.nav {display: inline-block;} + &.nav { display: inline-block; } } .menu-toggle { display: none; } .toolbar-item { margin-right: 0; - &:before, &:after {margin-top: 0;} - &:before {left: -12px;} - &:after {right: -12px;} + &:before, &:after { margin-top: 0; } + &:before { left: -12px; } + &:after { right: -12px; } - &.scroll-active-before:before {color: @color-mainmenu-active;} - &.scroll-active-after:after {color: @color-mainmenu-active;} + &.scroll-active-before:before { color: @color-mainmenu-active; } + &.scroll-active-after:after { color: @color-mainmenu-active; } + } +} + +nav#layout-mainmenu.navbar ul li .mainmenu-accountmenu { + position: fixed; + top: 63px; + right: 0; + width: 225px; + background: @color-accountmenu-bg; + z-index: 900; + display: none; + + &.active { + display: block; + } + + &:after { + .triangle(up, 22px, 12px, @color-accountmenu-bg); + right: 101px; + top: -12px; + position: absolute; + } + + ul { + padding: 12px 30px; + float: none; + display: block; + } + + li { + padding: 0; + font-weight: 200; + text-align: left; + display: block; + + a { + display: block; + padding: 9px 0; + text-align: left; + opacity: .65; + &:hover { + opacity: 1; + } + } + } + + li.divider { + height: 1px; + width: 100%; + margin: 9px 0; + overflow: hidden; + background-color: transparent; + border-top: 1px solid @color-accountmenu-divider; + } + + @media (max-width: @screen-sm) { + &:after { + right: 71px; + } } } @@ -98,7 +164,7 @@ nav#layout-mainmenu .menu-toggle, outline: none; &:hover { - background-color: transparent!important; + background-color: transparent !important; } &:active, &:focus { @@ -123,7 +189,7 @@ nav#layout-mainmenu.navbar ul li:hover, .mainmenu-collapsed li:hover { a { &:active, &:focus { - color: @color-mainmenu-active!important; + color: @color-mainmenu-active !important; } } } @@ -133,10 +199,10 @@ nav#layout-mainmenu.navbar ul li:hover, nav#layout-mainmenu.navbar ul li, .mainmenu-collapsed li { &.active, &.highlight { - color: @color-mainmenu-active!important; + color: @color-mainmenu-active !important; font-weight: 600; - a {color: @color-mainmenu-active!important;} + a {color: @color-mainmenu-active !important;} } &:hover { @@ -148,7 +214,7 @@ nav#layout-mainmenu.navbar ul li, body.drag { nav#layout-mainmenu.navbar ul.nav, .mainmenu-collapsed ul { - li:hover {color: @color-mainmenu-inactive;} + li:hover { color: @color-mainmenu-inactive; } } } diff --git a/modules/backend/layouts/_mainmenu.htm b/modules/backend/layouts/_mainmenu.htm index 25746406f..b737fc000 100644 --- a/modules/backend/layouts/_mainmenu.htm +++ b/modules/backend/layouts/_mainmenu.htm @@ -1,13 +1,14 @@ +listItems('mysettings'); +?> \ No newline at end of file + diff --git a/modules/system/controllers/settings/update.htm b/modules/system/controllers/settings/update.htm index 65ae3b683..3925c7208 100644 --- a/modules/system/controllers/settings/update.htm +++ b/modules/system/controllers/settings/update.htm @@ -1,6 +1,6 @@ fatalError): ?> - 'layout']) ?> + 'layout']) ?>
formRender() ?>