From 8ef3981f6437f25e182d046527fb68cf8c21bbb4 Mon Sep 17 00:00:00 2001
From: diosmosis <benakamoorthi@fastmail.fm>
Date: Sat, 8 Feb 2014 12:17:31 +0000
Subject: [PATCH] Fix infinite recursion issue w/ {% render %}-ing UIControl
 instances, move dashboard settings HTML rendering to new UIControl object,
 and slight improvement to error message in screenshot capture script.

---
 core/View.php                                 |  3 +-
 core/View/UIControl.php                       | 60 +++++++-----
 plugins/CoreHome/Controller.php               |  2 +
 plugins/CoreHome/javascripts/broadcast.js     |  2 +-
 plugins/CoreHome/templates/_indexContent.twig |  2 +-
 plugins/Dashboard/Controller.php              |  7 ++
 .../Dashboard/DashboardSettingsControl.php    | 30 ++++++
 plugins/Dashboard/javascripts/dashboard.js    | 35 ++++---
 plugins/Dashboard/stylesheets/dashboard.less  | 40 ++++----
 plugins/Dashboard/stylesheets/standalone.css  |  2 +-
 .../templates/_dashboardSettings.twig         | 54 ++++++-----
 plugins/Dashboard/templates/index.twig        |  2 +-
 plugins/Morpheus/stylesheets/theme.less       | 91 +++++++++----------
 .../SegmentEditor/SegmentSelectorControl.php  |  1 -
 tests/resources/screenshot-capture/capture.js |  9 +-
 .../screenshot-override/override.css          |  4 +-
 16 files changed, 206 insertions(+), 138 deletions(-)
 create mode 100644 plugins/Dashboard/DashboardSettingsControl.php

diff --git a/core/View.php b/core/View.php
index b0d8e5562f..3b5dd03985 100644
--- a/core/View.php
+++ b/core/View.php
@@ -112,7 +112,7 @@ class View implements ViewInterface
      * @var Twig_Environment
      */
     private $twig;
-    private $templateVars = array();
+    protected $templateVars = array();
     private $contentType = 'text/html; charset=utf-8';
     private $xFrameOptions = null;
 
@@ -202,6 +202,7 @@ class View implements ViewInterface
             $this->currentAction = Piwik::getAction();
             $userLogin = Piwik::getCurrentUserLogin();
             $this->userLogin = $userLogin;
+            $this->isSuperUser = Access::getInstance()->hasSuperUserAccess();
 
             $count = SettingsPiwik::getWebsitesCountToDisplay();
 
diff --git a/core/View/UIControl.php b/core/View/UIControl.php
index 39994aa828..0590fe2552 100644
--- a/core/View/UIControl.php
+++ b/core/View/UIControl.php
@@ -72,21 +72,41 @@ class UIControl extends \Piwik\View
     public $cssClass = "";
 
     /**
-     * Whether we are currently rendering the containing div or not.
+     * The inner view that renders the actual control content.
+     *
+     * @var View
      */
-    private $renderingContainer = false;
+    private $innerView = null;
 
     /**
      * Constructor.
      */
     public function __construct()
     {
-        parent::__construct(static::TEMPLATE);
+        $this->innerView = new View(static::TEMPLATE);
+
+        parent::__construct("@CoreHome\_uiControl");
 
         $this->clientSideProperties = array();
         $this->clientSideParameters = array();
     }
 
+    /**
+     * Sets a variable. See {@link View::__set()}.
+     */
+    public function __set($key, $val)
+    {
+        $this->innerView->__set($key, $val);
+    }
+
+    /**
+     * Gets a view variable. See {@link View::__get()}.
+     */
+    public function &__get($key)
+    {
+        return $this->innerView->__get($key);
+    }
+
     /**
      * Renders the control view within a containing <div> that is used by the UIControl JavaScript
      * class.
@@ -103,24 +123,22 @@ class UIControl extends \Piwik\View
             throw new Exception("All UIControls must set a jsClass property");
         }
 
-        if ($this->renderingContainer) {
-            return parent::render();
-        } else {
-            $this->renderingContainer = true;
-
-            $surroundingDivView = new View("@CoreHome\_uiControl");
-            $surroundingDivView->clientSideProperties = $this->clientSideProperties;
-            $surroundingDivView->clientSideParameters = $this->clientSideParameters;
-            $surroundingDivView->implView = $this;
-            $surroundingDivView->cssIdentifier = $this->cssIdentifier;
-            $surroundingDivView->cssClass = $this->cssClass;
-            $surroundingDivView->jsClass = $this->jsClass;
-
-            $result = $surroundingDivView->render();
-
-            $this->renderingContainer = false;
+        $this->getTemplateVars();
+        return parent::render();
+    }
 
-            return $result;
-        }
+    /**
+     * See {@link View::getTemplateVars()}.
+     */
+    public function getTemplateVars($override = array())
+    {
+        $this->templateVars['implView'] = $this->innerView;
+        $this->templateVars['clientSideProperties'] = $this->clientSideProperties;
+        $this->templateVars['clientSideParameters'] = $this->clientSideParameters;
+        $this->templateVars['cssIdentifier'] = $this->cssIdentifier;
+        $this->templateVars['cssClass'] = $this->cssClass;
+        $this->templateVars['jsClass'] = $this->jsClass;
+
+        return parent::getTemplateVars($override);
     }
 }
\ No newline at end of file
diff --git a/plugins/CoreHome/Controller.php b/plugins/CoreHome/Controller.php
index 476cb0e80f..6e6f40168d 100644
--- a/plugins/CoreHome/Controller.php
+++ b/plugins/CoreHome/Controller.php
@@ -19,6 +19,7 @@ use Piwik\Piwik;
 use Piwik\Plugins\CoreHome\DataTableRowAction\MultiRowEvolution;
 use Piwik\Plugins\CoreHome\DataTableRowAction\RowEvolution;
 use Piwik\Plugins\CorePluginsAdmin\MarketplaceApiClient;
+use Piwik\Plugins\Dashboard\DashboardSettingsControl;
 use Piwik\Plugins\UsersManager\API;
 use Piwik\Site;
 use Piwik\UpdateCheck;
@@ -77,6 +78,7 @@ class Controller extends \Piwik\Plugin\Controller
         $view = new View('@CoreHome/getDefaultIndexView');
         $this->setGeneralVariablesView($view);
         $view->menu = MenuMain::getInstance()->getMenu();
+        $view->dashboardSettingsControl = new DashboardSettingsControl();
         $view->content = '';
         return $view;
     }
diff --git a/plugins/CoreHome/javascripts/broadcast.js b/plugins/CoreHome/javascripts/broadcast.js
index b771f3dcda..b18f53319a 100644
--- a/plugins/CoreHome/javascripts/broadcast.js
+++ b/plugins/CoreHome/javascripts/broadcast.js
@@ -128,7 +128,7 @@ var broadcast = {
                     broadcast.loadAjaxContent(hashUrl);
 
                     // make sure the "Widgets & Dashboard" is deleted on reload
-                    $('#dashboardSettings').hide();
+                    $('.top_controls .dashboardSettings').hide();
                     $('#dashboardWidgetsArea').dashboard('destroy');
 
                     // remove unused controls
diff --git a/plugins/CoreHome/templates/_indexContent.twig b/plugins/CoreHome/templates/_indexContent.twig
index b2c79f4cc4..e115513a6d 100644
--- a/plugins/CoreHome/templates/_indexContent.twig
+++ b/plugins/CoreHome/templates/_indexContent.twig
@@ -4,7 +4,7 @@
     <div class="top_controls">
         {% include "@CoreHome/_periodSelect.twig" %}
         {{ postEvent("Template.nextToCalendar") }}
-        {% include "@Dashboard/_dashboardSettings.twig" %}
+        {% render dashboardSettingsControl %}
         {% include "@CoreHome/_headerMessage.twig" %}
         {{ ajax.requestErrorDiv }}
     </div>
diff --git a/plugins/Dashboard/Controller.php b/plugins/Dashboard/Controller.php
index 8c907d3f05..bdabfd881f 100644
--- a/plugins/Dashboard/Controller.php
+++ b/plugins/Dashboard/Controller.php
@@ -57,6 +57,7 @@ class Controller extends \Piwik\Plugin\Controller
     public function index()
     {
         $view = $this->_getDashboardView('@Dashboard/index');
+        $view->dashboardSettingsControl = new DashboardSettingsControl();
         $view->dashboards = array();
         if (!Piwik::isUserIsAnonymous()) {
             $login = Piwik::getCurrentUserLogin();
@@ -66,6 +67,12 @@ class Controller extends \Piwik\Plugin\Controller
         return $view->render();
     }
 
+    public function getDashboardSettingsControl()
+    {
+        $view = new DashboardSettingsControl();
+        return $view->render();
+    }
+
     public function getAvailableWidgets()
     {
         $this->checkTokenInUrl();
diff --git a/plugins/Dashboard/DashboardSettingsControl.php b/plugins/Dashboard/DashboardSettingsControl.php
new file mode 100644
index 0000000000..7fd877a959
--- /dev/null
+++ b/plugins/Dashboard/DashboardSettingsControl.php
@@ -0,0 +1,30 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link     http://piwik.org
+ * @license  http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+namespace Piwik\Plugins\Dashboard;
+
+use Piwik\View\UIControl;
+
+/**
+ * Generates the HTML for the dashboard manager control.
+ */
+class DashboardSettingsControl extends UIControl
+{
+    const TEMPLATE = "@Dashboard/_dashboardSettings";
+
+    /**
+     * Constructor.
+     */
+    public function __construct()
+    {
+        parent::__construct();
+        
+        $this->jsClass = "DashboardSettingsControl";
+        $this->cssIdentifier = "dashboardSettings";
+        $this->cssClass = "js-autoLeftPanel";
+    }
+}
\ No newline at end of file
diff --git a/plugins/Dashboard/javascripts/dashboard.js b/plugins/Dashboard/javascripts/dashboard.js
index 71da9c9c27..08ec0bfcc1 100644
--- a/plugins/Dashboard/javascripts/dashboard.js
+++ b/plugins/Dashboard/javascripts/dashboard.js
@@ -7,31 +7,31 @@
 
 function initDashboard(dashboardId, dashboardLayout) {
 
-    $('#dashboardSettings').show();
+    $('.dashboardSettings').show();
     initTopControls();
 
     // Embed dashboard
     if (!$('#topBars').length) {
-        $('#dashboardSettings').after($('#Dashboard'));
+        $('.dashboardSettings').after($('#Dashboard'));
         $('#Dashboard_embeddedIndex_' + dashboardId).addClass('sfHover');
     }
 
-    $('#dashboardSettings').on('click', function (e) {
-        if ($(e.target).is('#dashboardSettings') || $(e.target).is('#dashboardSettings>span')) {
-            $('#dashboardSettings').toggleClass('visible');
+    $('.dashboardSettings').on('click', function (e) {
+        if ($(e.target).is('.dashboardSettings') || $(e.target).is('.dashboardSettings>span')) {
+            $('.dashboardSettings').toggleClass('visible');
             if ($('#dashboardWidgetsArea').dashboard('isDefaultDashboard')) {
                 $('#removeDashboardLink').hide();
             } else {
                 $('#removeDashboardLink').show();
             }
             // fix position
-            $('#dashboardSettings').find('.widgetpreview-widgetlist').css('paddingTop', $('#dashboardSettings').find('.widgetpreview-categorylist').parent('li').position().top);
+            $('.dashboardSettings').find('.widgetpreview-widgetlist').css('paddingTop', $('.dashboardSettings').find('.widgetpreview-categorylist').parent('li').position().top);
         }
     });
     $('body').on('mouseup', function (e) {
-        if (!$(e.target).parents('#dashboardSettings').length && !$(e.target).is('#dashboardSettings')) {
-            $('#dashboardSettings').widgetPreview('reset');
-            $('#dashboardSettings').removeClass('visible');
+        if (!$(e.target).parents('.dashboardSettings').length && !$(e.target).is('.dashboardSettings')) {
+            $('.dashboardSettings').widgetPreview('reset');
+            $('.dashboardSettings').removeClass('visible');
         }
     });
 
@@ -44,14 +44,14 @@ function initDashboard(dashboardId, dashboardLayout) {
             layout: dashboardLayout
         });
 
-    $('#dashboardSettings').widgetPreview({
+    $('.dashboardSettings').widgetPreview({
         isWidgetAvailable: function (widgetUniqueId) {
             return !$('#dashboardWidgetsArea').find('[widgetId=' + widgetUniqueId + ']').length;
         },
         onSelect: function (widgetUniqueId) {
             var widget = widgetsHelper.getWidgetObjectFromUniqueId(widgetUniqueId);
             $('#dashboardWidgetsArea').dashboard('addWidget', widget.uniqueId, 1, widget.parameters, true, false);
-            $('#dashboardSettings').removeClass('visible');
+            $('.dashboardSettings').removeClass('visible');
         },
         resetOnSelect: true
     });
@@ -71,7 +71,7 @@ function initDashboard(dashboardId, dashboardLayout) {
 
     $('.submenu > li').on('mouseenter', function (event) {
         if (!$('.widgetpreview-categorylist', event.target).length) {
-            $('#dashboardSettings').widgetPreview('reset');
+            $('.dashboardSettings').widgetPreview('reset');
         }
     });
 
@@ -127,7 +127,7 @@ function showChangeDashboardLayoutDialog() {
 function showEmptyDashboardNotification() {
     piwikHelper.modalConfirm('#dashboardEmptyNotification', {
         resetDashboard: function () { $('#dashboardWidgetsArea').dashboard('resetLayout'); },
-        addWidget: function () { $('#dashboardSettings').trigger('click'); }
+        addWidget: function () { $('.dashboardSettings').trigger('click'); }
     });
 }
 
@@ -187,3 +187,12 @@ function copyDashboardToUser() {
         }
     });
 }
+
+// TODO: remove when control JS finished
+(function () {
+    var exports = window.require('piwik/UI');
+    exports.DashboardSettingsControl = function () {
+    };
+    exports.DashboardSettingsControl.initElements = function () {
+    };
+}());
\ No newline at end of file
diff --git a/plugins/Dashboard/stylesheets/dashboard.less b/plugins/Dashboard/stylesheets/dashboard.less
index ea67e3137b..15a5a28f70 100644
--- a/plugins/Dashboard/stylesheets/dashboard.less
+++ b/plugins/Dashboard/stylesheets/dashboard.less
@@ -18,7 +18,7 @@
   }
 
   .top_controls #periodString,
-  .top_controls #dashboardSettings,
+  .top_controls .dashboardSettings,
   .top_controls #segmentEditorPanel {
     position: static;
     margin: 0 0 10px;
@@ -230,7 +230,7 @@
   height: 30px;
 }
 
-#dashboardSettings {
+.dashboardSettings {
   position: absolute;
   z-index: 120;
   background: #f7f7f7;
@@ -243,39 +243,39 @@
   overflow: hidden;
 }
 
-#dashboardSettings:hover {
+.dashboardSettings:hover {
   background: #f1f0eb;
   border-color: #a9a399;
 }
 
-#dashboardSettings.visible {
+.dashboardSettings.visible {
   z-index: 1020; /* More than .jqplot-seriespicker-popover (1010) */
 }
 
-#dashboardSettings > span {
+.dashboardSettings > span {
   background: url(plugins/Zeitgeist/images/sort_subtable_desc.png) right center no-repeat;
   padding-right: 20px;
   display: block;
 }
 
-#dashboardSettings ul.submenu {
+.dashboardSettings ul.submenu {
   padding-top: 5px;
   display: none;
   float: left;
 }
 
-#dashboardSettings.visible ul.submenu {
+.dashboardSettings.visible ul.submenu {
   display: block;
   list-style: square outside none;
   margin-left: 15px;
 }
 
-#dashboardSettings > ul.submenu > li {
+.dashboardSettings > ul.submenu > li {
   padding: 5px 0;
   clear: both;
 }
 
-#dashboardSettings > ul.submenu > li:hover {
+.dashboardSettings > ul.submenu > li:hover {
   color: #e87500;
 }
 
@@ -413,18 +413,18 @@ div.widgetpreview-preview {
   width: 500px;
 }
 
-#dashboardSettings {
+.dashboardSettings {
   min-height: 0;
   height: auto;
   margin-right: 10px;
 }
 
-#dashboardSettings .submenu {
+.dashboardSettings .submenu {
   font-weight: bold;
   color: #255792;
 }
 
-#dashboardSettings .submenu ul {
+.dashboardSettings .submenu ul {
   float: none;
   font-weight: normal;
   padding-top: 10px;
@@ -436,32 +436,32 @@ div.widgetpreview-preview {
   margin-right: 20px;
 }
 
-#dashboardSettings .submenu ul li {
+.dashboardSettings .submenu ul li {
   line-height: 20px;
   padding: 0 25px 0 5px;
   color: #444;
 }
 
-#dashboardSettings .submenu ul li:hover {
+.dashboardSettings .submenu ul li:hover {
   color: #e87500;
 }
 
-#dashboardSettings .widgetpreview-widgetlist {
+.dashboardSettings .widgetpreview-widgetlist {
   width: 228px;
   font-weight: normal;
 }
 
-#dashboardSettings .widgetTop {
+.dashboardSettings .widgetTop {
   cursor: pointer;
 }
 
-#dashboardSettings .widgetpreview-widgetlist,
-#dashboardSettings .widgetpreview-preview {
+.dashboardSettings .widgetpreview-widgetlist,
+.dashboardSettings .widgetpreview-preview {
   display: none;
 }
 
-#dashboardSettings.visible .widgetpreview-widgetlist,
-#dashboardSettings.visible .widgetpreview-preview {
+.dashboardSettings.visible .widgetpreview-widgetlist,
+.dashboardSettings.visible .widgetpreview-preview {
   display: block;
 }
 
diff --git a/plugins/Dashboard/stylesheets/standalone.css b/plugins/Dashboard/stylesheets/standalone.css
index 6b0915ec68..5a2b0d90d9 100644
--- a/plugins/Dashboard/stylesheets/standalone.css
+++ b/plugins/Dashboard/stylesheets/standalone.css
@@ -58,7 +58,7 @@ body {
 
 .top_controls > #Dashboard,
 .top_controls > #periodString,
-.top_controls > #dashboardSettings {
+.top_controls > .dashboardSettings {
     margin-left: 0;
     margin-right: 10px;
 }
diff --git a/plugins/Dashboard/templates/_dashboardSettings.twig b/plugins/Dashboard/templates/_dashboardSettings.twig
index 3e0681ec6e..a13acb6edf 100644
--- a/plugins/Dashboard/templates/_dashboardSettings.twig
+++ b/plugins/Dashboard/templates/_dashboardSettings.twig
@@ -1,29 +1,27 @@
-<div id="dashboardSettings" class="js-autoLeftPanel">
-    <span>{{ 'Dashboard_WidgetsAndDashboard'|translate }}</span>
-    <ul class="submenu">
-        <li>
-            <div id="addWidget">{{ 'Dashboard_AddAWidget'|translate }} &darr;</div>
-            <ul class="widgetpreview-categorylist"></ul>
-        </li>
-        <li>
-            <div id="manageDashboard">{{ 'Dashboard_ManageDashboard'|translate }} &darr;</div>
-            <ul>
-                <li onclick="resetDashboard();">{{ 'Dashboard_ResetDashboard'|translate }}</li>
-                <li onclick="showChangeDashboardLayoutDialog();">{{ 'Dashboard_ChangeDashboardLayout'|translate }}</li>
-                {% if userLogin and userLogin != 'anonymous' %}
-                    <li onclick="renameDashboard();">{{ 'Dashboard_RenameDashboard'|translate }}</li>
-                    <li onclick="removeDashboard();" id="removeDashboardLink">{{ 'Dashboard_RemoveDashboard'|translate }}</li>
-                    {% if isSuperUser %}
-                        <li onclick="setAsDefaultWidgets();">{{ 'Dashboard_SetAsDefaultWidgets'|translate }}</li>
-                        <li onclick="copyDashboardToUser();">{{ 'Dashboard_CopyDashboardToUser'|translate }}</li>
-                    {% endif %}
+<span>{{ 'Dashboard_WidgetsAndDashboard'|translate }}</span>
+<ul class="submenu">
+    <li>
+        <div id="addWidget">{{ 'Dashboard_AddAWidget'|translate }} &darr;</div>
+        <ul class="widgetpreview-categorylist"></ul>
+    </li>
+    <li>
+        <div id="manageDashboard">{{ 'Dashboard_ManageDashboard'|translate }} &darr;</div>
+        <ul>
+            <li onclick="resetDashboard();">{{ 'Dashboard_ResetDashboard'|translate }}</li>
+            <li onclick="showChangeDashboardLayoutDialog();">{{ 'Dashboard_ChangeDashboardLayout'|translate }}</li>
+            {% if userLogin and userLogin != 'anonymous' %}
+                <li onclick="renameDashboard();">{{ 'Dashboard_RenameDashboard'|translate }}</li>
+                <li onclick="removeDashboard();" id="removeDashboardLink">{{ 'Dashboard_RemoveDashboard'|translate }}</li>
+                {% if isSuperUser %}
+                    <li onclick="setAsDefaultWidgets();">{{ 'Dashboard_SetAsDefaultWidgets'|translate }}</li>
+                    <li onclick="copyDashboardToUser();">{{ 'Dashboard_CopyDashboardToUser'|translate }}</li>
                 {% endif %}
-            </ul>
-        </li>
-        {% if (userLogin and 'anonymous' != userLogin) %}
-            <li onclick="createDashboard();">{{ 'Dashboard_CreateNewDashboard'|translate }}</li>
-        {% endif %}
-    </ul>
-    <ul class="widgetpreview-widgetlist"></ul>
-    <div class="widgetpreview-preview"></div>
-</div>
\ No newline at end of file
+            {% endif %}
+        </ul>
+    </li>
+    {% if (userLogin and 'anonymous' != userLogin) %}
+        <li onclick="createDashboard();">{{ 'Dashboard_CreateNewDashboard'|translate }}</li>
+    {% endif %}
+</ul>
+<ul class="widgetpreview-widgetlist"></ul>
+<div class="widgetpreview-preview"></div>
\ No newline at end of file
diff --git a/plugins/Dashboard/templates/index.twig b/plugins/Dashboard/templates/index.twig
index c86bbf5aac..5d34202044 100644
--- a/plugins/Dashboard/templates/index.twig
+++ b/plugins/Dashboard/templates/index.twig
@@ -2,7 +2,7 @@
 <div class="top_controls">
     {% include "@CoreHome/_periodSelect.twig" %}
     {{ postEvent("Template.nextToCalendar") }}
-    {% include "@Dashboard/_dashboardSettings.twig" %}
+    {% render dashboardSettingsControl %}
     <div id="Dashboard" class="js-autoLeftPanel">
         <ul>
             {% for dashboard in dashboards %}
diff --git a/plugins/Morpheus/stylesheets/theme.less b/plugins/Morpheus/stylesheets/theme.less
index 87a418534a..ef19e20763 100644
--- a/plugins/Morpheus/stylesheets/theme.less
+++ b/plugins/Morpheus/stylesheets/theme.less
@@ -200,54 +200,51 @@ table.entityTable tr td a:hover {
     }
 }
 
-.top_controls {
-  #dashboardSettings {
-    border: 1px solid @silver-80;
-    background: #fff;
-    z-index: 10;
-    padding: 8px 10px 8px 10px;
-    .border-radius(0px);
-    .font-default(10px, 12px);
-    > span {
-      position: relative;
-      background: none;
-      text-transform: uppercase;
-      &:after {
-        content: '';
-        border-left: 4px solid transparent;
-        border-right: 4px solid transparent;
-        border-top: 5px solid @brand-red;
-        position: absolute;
-        top: 3px;
-        right: 0;
-      }
+.dashboardSettings {
+  border: 1px solid @silver-80;
+  background: #fff;
+  z-index: 10;
+  padding: 8px 10px 8px 10px;
+  .border-radius(0px);
+  .font-default(10px, 12px);
+  > span {
+    position: relative;
+    background: none;
+    text-transform: uppercase;
+    &:after {
+      content: '';
+      border-left: 4px solid transparent;
+      border-right: 4px solid transparent;
+      border-top: 5px solid @brand-red;
+      position: absolute;
+      top: 3px;
+      right: 0;
     }
+  }
 
-    ul.submenu {
-      margin-left: 0;
-      li {
-        list-style-type: none;
-        > div {
-          .font-default(11px, 14px);
-          color: @brand-black;
-        }
-        text-transform: none;
-        color: @silver-20;
-        &.widgetpreview-choosen {
-          color: @brand-black;
-          font-weight: normal;
-          background: @silver-95;
-          position: relative;
-          &:after {
-            position: absolute;
-            content: '';
-            top: 6px;
-            right: 10px;
-            border-top: 4px solid transparent;
-            border-bottom: 4px solid transparent;
-            border-left: 5px solid @brand-red;
-
-          }
+  ul.submenu {
+    margin-left: 0;
+    li {
+      list-style-type: none;
+      > div {
+        .font-default(11px, 14px);
+        color: @brand-black;
+      }
+      text-transform: none;
+      color: @silver-20;
+      &.widgetpreview-choosen {
+        color: @brand-black;
+        font-weight: normal;
+        background: @silver-95;
+        position: relative;
+        &:after {
+          position: absolute;
+          content: '';
+          top: 6px;
+          right: 10px;
+          border-top: 4px solid transparent;
+          border-bottom: 4px solid transparent;
+          border-left: 5px solid @brand-red;
         }
       }
     }
@@ -318,7 +315,7 @@ table.entityTable tr td a:hover {
   }
 }
 
-.segmentEditorPanel:hover {
+.segmentEditorPanel:hover, .dashboardSettings:hover {
   background: #fff;
   border: 1px solid @silver-80;
 }
diff --git a/plugins/SegmentEditor/SegmentSelectorControl.php b/plugins/SegmentEditor/SegmentSelectorControl.php
index 9225b4d27d..fd4253f151 100644
--- a/plugins/SegmentEditor/SegmentSelectorControl.php
+++ b/plugins/SegmentEditor/SegmentSelectorControl.php
@@ -33,7 +33,6 @@ class SegmentSelectorControl extends UIControl
         $this->cssIdentifier = "segmentEditorPanel";
         $this->cssClass = "js-autoLeftPanel";
 
-        $this->isSuperUser = Access::getInstance()->hasSuperUserAccess();
         $this->idSite = Common::getRequestVar('idSite', false, 'int');
 
         $this->selectedSegment = Common::getRequestVar('segment', false, 'string');
diff --git a/tests/resources/screenshot-capture/capture.js b/tests/resources/screenshot-capture/capture.js
index c6715e8b79..0906de4649 100644
--- a/tests/resources/screenshot-capture/capture.js
+++ b/tests/resources/screenshot-capture/capture.js
@@ -30,7 +30,7 @@ PageFacade.prototype = {
     },
 
     _getPosition: function (selector) {
-        return this.webpage.evaluate(function (selector) {
+        var pos = this.webpage.evaluate(function (selector) {
             var element = window.jQuery(selector),
                 offset = element.offset();
             return {
@@ -38,6 +38,13 @@ PageFacade.prototype = {
                 y: offset.top + element.height() / 2
             };
         }, selector);
+
+        if (!pos) {
+            console.log("ERROR: Cannot find element: " + selector);
+            app.exit(1);
+        }
+
+        return pos;
     },
 
     evaluate: function (impl) {
diff --git a/tests/resources/screenshot-override/override.css b/tests/resources/screenshot-override/override.css
index 4dcb133f19..71c0eac4b3 100644
--- a/tests/resources/screenshot-override/override.css
+++ b/tests/resources/screenshot-override/override.css
@@ -14,7 +14,7 @@ span.plugin-version {
     visibility:hidden;
 }
 
-/* add some space to the top of the segment editor so screenshots are clearer */
-.widget .segmentEditorPanel {
+/* add some space to the top of the segment editor & other widgets so screenshots are clearer */
+.widget .segmentEditorPanel, .widget .dashboardSettings {
     margin-top:1em;
 }
\ No newline at end of file
-- 
GitLab