Kaynağa Gözat

HUE-3294 [core] Add right side panel and a split draggable binding for flex layout

Johan Ahlen 9 yıl önce
ebeveyn
işleme
c486023

+ 60 - 50
desktop/core/src/desktop/static/desktop/css/responsive.css

@@ -43,6 +43,15 @@ body {
   overflow-y: hidden;
 }
 
+.content-wrapper {
+  flex: 1 1 100%;
+  position: relative;
+  display: flex;
+  width: 100%;
+  flex-direction: row;
+  background-color: #FFF;
+}
+
 .top-nav {
   position: relative;
   flex: 1;
@@ -52,12 +61,37 @@ body {
   padding: 1em 0;
 }
 
-.content-wrapper {
-  position: relative;
-  display: flex;
-  flex: 1 1 100%;
+.left-panel,
+.right-panel {
   background-color: #FFF;
-  flex-direction: row;
+  flex: 0;
+  position: relative;
+  padding-top: 10px;
+  min-width: 250px;
+}
+
+.side-panel-closed {
+  min-width: 0;
+}
+
+.resizer {
+  flex: 0;
+  height: 100%;
+  min-width: 4px;
+  cursor: col-resize;
+}
+
+.resize-bar {
+  position: absolute;
+  height: 100%;
+  width: 2px;
+  background-color: #F1F1F1;
+}
+
+.page-content {
+  flex: 1;
+  padding: 1em;
+  position: relative;
 }
 
 .left-nav {
@@ -82,7 +116,6 @@ body {
   transition: 0.4s flex;
 }
 
-
 .inactive-action,
 .inactive-action a {
   -webkit-transition: color 0.2s ease;
@@ -114,8 +147,6 @@ body {
   color: #338BB8 !important;
 }
 
-/* Assist panel */
-
 .assist-hidden {
   flex: 0;
 }
@@ -128,51 +159,38 @@ body {
   bottom: 0;
 }
 
-.resizer {
-  height: 100%;
-  position: absolute;
-  width: 4px;
-  cursor: col-resize;
-}
-
-.resize-bar {
-  position: absolute;
-  height: 100%;
-  width: 2px;
-  background-color: #F1F1F1;
-}
-
-.hide-assist {
+.side-panel-toggle {
   position: absolute;
   top: 2px;
-  right: 4px;
+  margin: 0;
   z-index: 1000;
   color: #D1D1D1;
   font-size: 12px;
-  -webkit-transition: margin-right 0.2s linear, color 0.5s ease;
-  -moz-transition: margin-right 0.2s linear, color 0.5s ease;
-  -ms-transition: margin-right 0.2s linear, color 0.5s ease;
-  transition: margin-right 0.2s linear, color 0.5s ease;
+  -webkit-transition: margin 0.2s linear, color 0.5s ease;
+  -moz-transition: margin 0.2s linear, color 0.5s ease;
+  -ms-transition: margin 0.2s linear, color 0.5s ease;
+  transition: margin 0.2s linear, color 0.5s ease;
 }
 
-.show-assist {
-  position: absolute;
-  top: 2px;
-  left: 8px;
-  font-size: 12px;
-  margin-left: 0;
-  -webkit-transition: margin-left 0.2s linear;
-  -moz-transition: margin-left 0.2s linear;
-  -ms-transition: margin-left 0.2s linear;
-  transition: margin-left 0.2s linear;
+.show-right-side-panel,
+.hide-left-side-panel {
+  right: 4px;
 }
 
-.show-assist:hover {
-  margin-left: 2px;
+.show-right-side-panel:hover,
+.hide-left-side-panel:hover {
+  margin-right: 2px;
+  color: #338bb8;
 }
 
-.hide-assist:hover {
-  margin-right: 2px;
+.hide-right-side-panel,
+.show-left-side-panel {
+  left: 4px;
+}
+
+.hide-right-side-panel:hover,
+.show-left-side-panel:hover {
+  margin-left: 2px;
   color: #338bb8;
 }
 
@@ -181,14 +199,6 @@ body {
   background-color: lightgrey;
 }
 
-/* Main page */
-
-.page-content {
-  flex: 2;
-  padding: 1em;
-  position: relative;
-}
-
 h1 {
   font-size: 3rem;
 }

+ 68 - 0
desktop/core/src/desktop/static/desktop/js/ko.hue-bindings.js

@@ -1894,6 +1894,74 @@
     }
   };
 
+  ko.bindingHandlers.splitFlexDraggable = {
+    init: function (element, valueAccessor) {
+      var options = ko.unwrap(valueAccessor());
+      var sidePanelWidth = $.totalStorage(options.appName + '_' + options.orientation + '_panel_width') != null ? $.totalStorage(options.appName + '_' + options.orientation + '_panel_width') : 250;
+
+      var $resizer = $(element);
+      var $sidePanel = $(options.sidePanelSelector);
+      var $container = $(options.containerSelector);
+
+      var isLeft = options.orientation === 'left';
+
+      var onPosition = options.onPosition || function() {};
+
+      var panelStartWidth = $sidePanel.width();
+      $resizer.draggable({
+        axis: "x",
+        containment: $container,
+        start: function () {
+          panelStartWidth = $sidePanel.width();
+        },
+        drag: function (event, ui) {
+          if (isLeft) {
+            $sidePanel.css("flex-basis", Math.max(panelStartWidth + ui.position.left, 200) + "px");
+          } else {
+            $sidePanel.css("flex-basis", Math.max(panelStartWidth - ui.position.left, 200) + "px");
+          }
+          onPosition();
+          ui.position.left = 0;
+        },
+        stop: function (event, ui) {
+          sidePanelWidth = $sidePanel.width();
+          $.totalStorage(options.appName + '_' + options.orientation + '_panel_width', sidePanelWidth);
+          window.setTimeout(positionPanels, 100);
+          huePubSub.publish('split.panel.resized');
+        }
+      });
+
+      var positionPanels = function () {
+        if (options.sidePanelVisible()) {
+          $sidePanel.css('width',  Math.max(sidePanelWidth, 200) + 'px');
+          onPosition();
+        }
+      };
+
+      options.sidePanelVisible.subscribe(positionPanels);
+
+      var positionTimeout = -1;
+      $(window).resize(function() {
+        window.clearTimeout(positionTimeout);
+        positionTimeout = window.setTimeout(function () {
+          positionPanels()
+        }, 1);
+      });
+
+      function initialPositioning() {
+        if(! $container.is(":visible") && ! $sidePanel.is(":visible")) {
+          window.setTimeout(initialPositioning, 50);
+        } else {
+          positionPanels();
+          // Even though the container is visible some slow browsers might not
+          // have rendered the panels
+          window.setTimeout(positionPanels, 50);
+        }
+      }
+      initialPositioning();
+    }
+  };
+
   ko.bindingHandlers.splitDraggable = {
     init: function (element, valueAccessor) {
       var options = ko.unwrap(valueAccessor());

+ 28 - 11
desktop/core/src/desktop/templates/responsive.mako

@@ -258,9 +258,9 @@ ${ hueIcons.symbols() }
       [+]
     </div>
 
-    <div id="leftAssistContainer" class="assist-container left-panel" style="position: relative; padding-top: 10px;">
-      <a href="javascript:void(0);" style="z-index: 1000;" title="${_('Show Assist')}" class="pointer show-assist" data-bind="visible: ! leftAssistVisible(), toggle: leftAssistVisible"><i class="fa fa-chevron-right"></i></a>
-      <a href="javascript:void(0);" title="${_('Hide Assist')}" class="pointer hide-assist" data-bind="visible: leftAssistVisible, toggle: leftAssistVisible"><i class="fa fa-chevron-left"></i></a>
+    <div class="left-panel" data-bind="css: { 'side-panel-closed': !leftAssistVisible() }">
+      <a href="javascript:void(0);" style="z-index: 1000;" title="${_('Show Assist')}" class="pointer side-panel-toggle show-left-side-panel" data-bind="visible: ! leftAssistVisible(), toggle: leftAssistVisible"><i class="fa fa-chevron-right"></i></a>
+      <a href="javascript:void(0);" title="${_('Hide Assist')}" class="pointer side-panel-toggle hide-left-side-panel" data-bind="visible: leftAssistVisible, toggle: leftAssistVisible"><i class="fa fa-chevron-left"></i></a>
       <!-- ko if: leftAssistVisible -->
       <div class="assist" data-bind="component: {
           name: 'assist-panel',
@@ -282,11 +282,11 @@ ${ hueIcons.symbols() }
       <!-- /ko -->
     </div>
 
-    <div id="leftPanelResizer" class="resizer" data-bind="splitDraggable : {
+    <div id="leftResizer" class="resizer" data-bind="visible: leftAssistVisible(), splitFlexDraggable : {
       containerSelector: '.content-wrapper',
-      rightPanelSelector: '.page-content',
-      appName: 'hue',
-      leftPanelVisible: leftAssistVisible,
+      sidePanelSelector: '.left-panel',
+      sidePanelVisible: leftAssistVisible,
+      orientation: 'left',
       onPosition: function() { huePubSub.publish('split.draggable.position') }
     }"><div class="resize-bar">&nbsp;</div></div>
 
@@ -298,6 +298,19 @@ ${ hueIcons.symbols() }
       <!-- /ko -->
       <div id="embeddable"></div>
     </div>
+
+    <div id="rightResizer" class="resizer" data-bind="visible: rightAssistVisible(), splitFlexDraggable : {
+      containerSelector: '.content-wrapper',
+      sidePanelSelector: '.right-panel',
+      sidePanelVisible: rightAssistVisible,
+      orientation: 'right',
+      onPosition: function() { huePubSub.publish('split.draggable.position') }
+    }"><div class="resize-bar">&nbsp;</div></div>
+
+    <div class="right-panel" data-bind="css: { 'side-panel-closed': !rightAssistVisible() }">
+      <a href="javascript:void(0);" style="z-index: 1000;" title="${_('Show Assist')}" class="pointer side-panel-toggle show-right-side-panel" data-bind="visible: ! rightAssistVisible(), toggle: rightAssistVisible"><i class="fa fa-chevron-left"></i></a>
+      <a href="javascript:void(0);" title="${_('Hide Assist')}" class="pointer side-panel-toggle hide-right-side-panel" data-bind="visible: rightAssistVisible, toggle: rightAssistVisible"><i class="fa fa-chevron-right"></i></a>
+    </div>
   </div>
 </div>
 
@@ -379,11 +392,13 @@ ${ assist.assistPanel() }
     });
   };
 
-  var LeftAssistViewModel = function () {
+  var SidePanelViewModel = function () {
     var self = this;
     self.apiHelper = ApiHelper.getInstance();
     self.leftAssistVisible = ko.observable();
+    self.rightAssistVisible = ko.observable();
     self.apiHelper.withTotalStorage('assist', 'left_assist_panel_visible', self.leftAssistVisible, true);
+    self.apiHelper.withTotalStorage('assist', 'right_assist_panel_visible', self.rightAssistVisible, true);
   };
 
   $(document).ready(function () {
@@ -397,9 +412,11 @@ ${ assist.assistPanel() }
     var opvm = new OnePageViewModel();
     ko.applyBindings(opvm, $('.page-content')[0]);
 
-    var leftAssistViewModel = new LeftAssistViewModel();
-    ko.applyBindings(leftAssistViewModel, $('#leftAssistContainer')[0]);
-    ko.applyBindings(leftAssistViewModel, $('#leftPanelResizer')[0]);
+    var sidePanelViewModel = new SidePanelViewModel();
+    ko.applyBindings(sidePanelViewModel, $('.left-panel')[0]);
+    ko.applyBindings(sidePanelViewModel, $('#leftResizer')[0]);
+    ko.applyBindings(sidePanelViewModel, $('#rightResizer')[0]);
+    ko.applyBindings(sidePanelViewModel, $('.right-panel')[0]);
 
     if (window.location.getParameter('editor') !== '' || window.location.getParameter('type') !== ''){
       opvm.currentApp('editor');