Browse Source

HUE-8542 [frontend] Add a custom left nav for multi cluster mode

Johan Ahlen 7 years ago
parent
commit
cd95f637b4

File diff suppressed because it is too large
+ 0 - 0
desktop/core/src/desktop/static/desktop/css/hue.css


File diff suppressed because it is too large
+ 9 - 0
desktop/core/src/desktop/static/desktop/ext/fonts/altus.svg


BIN
desktop/core/src/desktop/static/desktop/ext/fonts/altus.ttf


BIN
desktop/core/src/desktop/static/desktop/ext/fonts/altus.woff


+ 128 - 0
desktop/core/src/desktop/static/desktop/less/components/hue-multi-cluster-sidebar.less

@@ -0,0 +1,128 @@
+/*
+ Licensed to Cloudera, Inc. under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  Cloudera, Inc. licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+@sidebar-width: 180px;
+@collapsed-sidebar-width: 48px;
+@sidebar-animation-duration: 250ms;
+@sidebar-category-font-size: 13px;
+@sidebar-left-spacing: 16px;
+
+.hue-sidebar {
+
+  .sidebar-content {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    right: 0;
+    left: 0;
+    padding-top: 20px;
+    background-color: @cui-white;
+
+    overflow-y: auto;
+    overflow-x: hidden;
+
+    .sidebar-submenu {
+      position: fixed;
+      left: 182px;
+      min-width: 110px;
+      background-color: @cui-white;
+      border: 1px solid @cui-default-border-color;
+      .hue-box-shadow-right();
+
+      .sidebar-submenu-item {
+        display: block;
+        padding: 0 20px;
+        line-height: 36px;
+        color: @text-color;
+        white-space: nowrap;
+        position: relative;
+
+        &:hover {
+          color: @cui-blue-500;
+        }
+      }
+    }
+
+    .sidebar-item {
+      display: block;
+      line-height: 36px;
+      color: @text-color;
+      white-space: nowrap;
+      position: relative;
+
+
+      .sidebar-icon {
+        float: left;
+        padding: 0 14px 0 @sidebar-left-spacing;
+        &.with-tooltip {
+          display: none;
+        }
+      }
+
+      .fa,
+      .altus-icon {
+        width: 18px;
+        font-size: 16px;
+        text-align: center;
+        vertical-align: middle;
+      }
+
+      .submenu-icon {
+        position: absolute;
+        right: 3px;
+        top: 14px;
+        font-size: 11px;
+      }
+    }
+
+    .sidebar-item.active {
+      background: @cui-blue-050;
+      color: @cui-blue-500;
+
+      .fa:before {
+        color: @cui-blue-500;
+      }
+    }
+
+    .sidebar-item:hover {
+      color: @cui-blue-500;
+      .fa:before {
+        color: @cui-blue-500;
+      }
+    }
+
+    .sidebar-item:active {
+      background: @cui-blue-050;
+    }
+
+    .sidebar-category-item {
+      margin: 20px 0 4px @sidebar-left-spacing;
+      font-size: @sidebar-category-font-size;
+      font-weight: bold;
+      color: @cui-gray-600;
+      transition: opacity @sidebar-animation-duration;
+      white-space: nowrap;
+    }
+
+    .sidebar-item-name {
+      transition: opacity @sidebar-animation-duration;
+      opacity: 1;
+      vertical-align: middle;
+    }
+  }
+}

+ 125 - 0
desktop/core/src/desktop/static/desktop/less/hue-multi-cluster-icons.less

@@ -0,0 +1,125 @@
+/*
+ Licensed to Cloudera, Inc. under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  Cloudera, Inc. licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+@font-face {
+  font-family: 'altus';
+  src: url('../ext/fonts/altus.ttf') format('truetype'), url('../ext/fonts/altus.woff') format('woff'), url('../ext/fonts/altus.svg') format('svg');
+  font-weight: normal;
+  font-style: normal;
+}
+
+&.altus-icon {
+  display: inline-block;
+  font: normal normal normal 16px/1 altus;
+  font-size: inherit;
+  font-style: normal;
+  font-weight: normal;
+  font-variant: normal;
+  text-align: center;
+  text-transform: none;
+
+  text-rendering: auto;
+  /* Better Font Rendering =========== */
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+
+  @altus-adb-cluster: '\e900';
+  @altus-environment: '\e901';
+  @altus-dashboard: '\e902';
+  @altus-iam: '\e903';
+  @altus-user-group: '\e903';
+  @altus-de-cluster: '\e904';
+  @altus-de-job: '\e905';
+  @altus-adb: '\e906';
+  @altus-de: '\e907';
+  @altus-ds: '\e908';
+  @altus-sdx: '\e909';
+  @altus-na: '\e910';
+  @altus-no-access: '\e911';
+  @altus-user-access: '\e90a';
+  @altus-adb-query: '\e90b';
+  @altus-workload: '\e90c';
+  @altus-azure: '\e90d';
+  @altus-aws: '\e90e';
+  @altus-user: '\e90f';
+  @altus-sql-editor: '\e912';
+  @altus-feedback: '\e913';
+
+  &.altus-adb-cluster:before {
+    content: @altus-adb-cluster;
+  }
+  &.altus-environment:before {
+    content: @altus-environment;
+  }
+  &.altus-dashboard:before {
+    content: @altus-dashboard;
+  }
+  &.altus-iam:before {
+    content: @altus-iam;
+  }
+  &.altus-user-group:before {
+    content: @altus-user-group;
+  }
+  &.altus-de-cluster:before {
+    content: @altus-de-cluster;
+  }
+  &.altus-de-job:before {
+    content: @altus-de-job;
+  }
+  &.altus-adb:before {
+    content: @altus-adb;
+  }
+  &.altus-de:before {
+    content: @altus-de;
+  }
+  &.altus-ds:before {
+    content: @altus-ds;
+  }
+  &.altus-sdx:before {
+    content: @altus-sdx;
+  }
+  &.altus-na:before {
+    content: @altus-na;
+  }
+  &.altus-no-access:before {
+    content: @altus-no-access;
+  }
+  &.altus-user-access:before {
+    content: @altus-user-access;
+  }
+  &.altus-adb-query:before {
+    content: @altus-adb-query;
+  }
+  &.altus-workload:before {
+    content: @altus-workload;
+  }
+  &.altus-azure:before {
+    content: @altus-azure;
+  }
+  &.altus-aws:before {
+    content: @altus-aws;
+  }
+  &.altus-user:before {
+    content: @altus-user;
+  }
+  &.altus-sql-editor:before {
+    content: @altus-sql-editor;
+  }
+  &.altus-feedback:before {
+    content: @altus-feedback;
+  }
+}

+ 2 - 0
desktop/core/src/desktop/static/desktop/less/hue.less

@@ -22,10 +22,12 @@
 @import "hue-autocomplete";
 @import "hue-cui-overrides.less";
 @import "hue-cross-version.less";
+@import "hue-multi-cluster-icons.less";
 
 @import "components/hue-clearable.less";
 @import "components/hue-sidebar.less";
 @import "components/hue-hamburger.less";
+@import "components/hue-multi-cluster-sidebar.less";
 @import "hue4.less";
 
 html {

+ 15 - 11
desktop/core/src/desktop/templates/hue.mako

@@ -316,19 +316,22 @@ ${ hueIcons.symbols() }
     </script>
 
     <div class="hue-sidebar hue-sidebar-below-top-bar" data-bind="visible: leftNavVisible" style="display:none;">
-      <div class="hue-sidebar-content">
-        <!-- ko foreach: {data: items, as: 'item'} -->
+      % if IS_MULTICLUSTER_ONLY.get():
+        <!-- ko component: { name: 'hue-multi-cluster-sidebar' } --><!-- /ko -->
+      % else:
+        <div class="hue-sidebar-content">
+          <!-- ko foreach: {data: items, as: 'item'} -->
           <!-- ko if: item.isCategory -->
-             <h4 class="hue-sidebar-category-item" data-bind="text: item.displayName"></h4>
-             <!-- ko template: {name: 'hue-tmpl-sidebar-link', foreach: item.children, as: 'item'} --><!-- /ko -->
+          <h4 class="hue-sidebar-category-item" data-bind="text: item.displayName"></h4>
+          <!-- ko template: {name: 'hue-tmpl-sidebar-link', foreach: item.children, as: 'item'} --><!-- /ko -->
           <!-- /ko -->
           <!-- ko ifnot: item.isCategory -->
-             <!-- ko template: { name: 'hue-tmpl-sidebar-link' } --><!-- /ko -->
+          <!-- ko template: { name: 'hue-tmpl-sidebar-link' } --><!-- /ko -->
           <!-- /ko -->
-        <!-- /ko -->
-      </div>
-      <div class="hue-sidebar-footer-panel">
-        <div data-bind="dropzone: {
+          <!-- /ko -->
+        </div>
+        <div class="hue-sidebar-footer-panel">
+          <div data-bind="dropzone: {
             clickable: false,
             url: '/filebrowser/upload/file?dest=' + DROPZONE_HOME_DIR,
             params: { dest: DROPZONE_HOME_DIR },
@@ -336,9 +339,10 @@ ${ hueIcons.symbols() }
             onError: onePageViewModel.dropzoneError,
             onComplete: onePageViewModel.dropzoneComplete },
             click: function(){ page('/indexer/importer/') }" class="pointer" title="${ _('Import data wizard') }">
-          <div class="dz-message" data-dz-message><i class="fa fa-fw fa-cloud-upload"></i> ${ _('Click or Drop files here') }</div>
+            <div class="dz-message" data-dz-message><i class="fa fa-fw fa-cloud-upload"></i> ${ _('Click or Drop files here') }</div>
+          </div>
         </div>
-      </div>
+      % endif
     </div>
 
     <div class="left-panel" data-bind="css: { 'side-panel-closed': !leftAssistVisible() }, visibleOnHover: { selector: '.hide-left-side-panel' }">

+ 2 - 0
desktop/core/src/desktop/templates/ko_components.mako

@@ -25,6 +25,7 @@
 <%namespace name="koHistoryPanel" file="/ko_components/ko_history_panel.mako" />
 <%namespace name="koInlineAutocomplete" file="/ko_components/ko_inline_autocomplete.mako" />
 <%namespace name="koJobBrowserLinks" file="/ko_components/ko_job_browser_links.mako" />
+<%namespace name="koMultiClusterSidebar" file="/ko_components/ko_multi_cluster_sidebar.mako" />
 <%namespace name="koNavProperties" file="/ko_components/ko_nav_properties.mako" />
 <%namespace name="koNavTags" file="/ko_components/ko_nav_tags.mako" />
 <%namespace name="koSimpleAceEditor" file="/ko_components/ko_simple_ace_editor.mako" />
@@ -45,6 +46,7 @@
   ${ koHistoryPanel.historyPanel() }
   ${ koInlineAutocomplete.inlineAutocomplete() }
   ${ koJobBrowserLinks.jobBrowserLinks() }
+  ${ koMultiClusterSidebar.multiClusterSidebar() }
   ${ koNavProperties.navProperties() }
   ${ koNavTags.navTags() }
   ${ koSimpleAceEditor.simpleAceEditor() }

+ 215 - 0
desktop/core/src/desktop/templates/ko_components/ko_multi_cluster_sidebar.mako

@@ -0,0 +1,215 @@
+## Licensed to Cloudera, Inc. under one
+## or more contributor license agreements.  See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership.  Cloudera, Inc. licenses this file
+## to you under the Apache License, Version 2.0 (the
+## "License"); you may not use this file except in compliance
+## with the License.  You may obtain a copy of the License at
+##
+##     http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+
+<%!
+from desktop import conf
+from desktop.lib.i18n import smart_unicode
+
+from django.utils.translation import ugettext as _
+from desktop.views import _ko
+%>
+
+<%def name="multiClusterSidebar()">
+
+  <script type="text/html" id="hue-multi-cluster-sidebar-template">
+    <div class="sidebar-content" data-bind="foreach: categories">
+      <!-- ko if: typeof label !== 'undefined' -->
+      <h4 class="sidebar-category-item" data-bind="text: label"></h4>
+      <!-- /ko -->
+      <!-- ko foreach: items -->
+      <!-- ko if: typeof items == 'undefined' -->
+      <a role="button" class="sidebar-item" data-bind="css: { 'active': false }, hueLink: url, attr: { 'title': label">
+        <span class="sidebar-icon without-tooltip">
+          <span data-bind="css: icon"></span>
+        </span>
+        <span class="sidebar-item-name" data-bind="text: label"></span>
+      </a>
+      <!-- /ko -->
+      <!-- ko if: typeof items !== 'undefined' -->
+      <a role="button" class="sidebar-item" href="javascript: void(0);" data-bind="sidebarSubmenuActivator, css: { 'active': false }, attr: {'title': label">
+        <span class="sidebar-icon without-tooltip">
+          <span data-bind="css: icon"></span>
+        </span>
+        <span class="sidebar-item-name" data-bind="text: label"></span>
+        <i class="submenu-icon fa fa-chevron-right"></i>
+      </a>
+      <div class="sidebar-submenu" style="display:none;" data-bind="foreach: items">
+        <a role="button" class="sidebar-submenu-item" data-bind="hueLink: url, attr: { 'title': label }, text: label"></a>
+      </div>
+      <!-- /ko -->
+      <!-- /ko -->
+    </div>
+  </script>
+
+  <script type="text/javascript">
+    (function () {
+
+      ko.bindingHandlers.sidebarSubmenuActivator = {
+        init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
+          var $element = $(element);
+          var $menu = $element.next();
+          var visible = false;
+          var hideTimeout = -1;
+
+          var show = function () {
+            window.clearTimeout(hideTimeout);
+            if (!visible) {
+              $menu.css({ 'top': $element.offset().top + 'px' });
+              huePubSub.publish('hue.sidebar.hide.submenus');
+              $menu.show();
+              visible = true;
+            }
+          };
+
+          var hide = function () {
+            hideTimeout = window.setTimeout(function () {
+              if (visible) {
+                $menu.hide();
+                visible = false;
+              }
+            }, 300);
+          };
+
+          var hideSub = huePubSub.subscribe('hue.sidebar.hide.submenus', function () {
+            window.clearTimeout(hideTimeout);
+            $menu.hide();
+            visible = false;
+          });
+
+          $element.on('click', show);
+          $element.on('mouseover', show);
+          $element.on('mouseout', hide);
+          $menu.on('mouseover', show);
+          $menu.on('mouseout', hide);
+
+          ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
+            $menu.hide();
+            hideSub.remove();
+            $element.off('click');
+            $element.off('mouseover');
+            $element.off('mouseout');
+            $menu.off('mouseover');
+            $menu.off('mouseout');
+          });
+        }
+      };
+
+      // TODO: Fetch menu from the backend
+      var FIXED_CATEGORIES = [{
+        items: [{
+          label: '${ _('Home') }',
+          url: '/',
+          icon: 'fa fa-home'
+        }, {
+          label: '${ _('Data Assistant') }',
+          icon: 'altus-icon altus-adb-query',
+          items: [{
+            label: '${ _('Editor') }',
+            url: '/editor?type=impala'
+          },{
+            label: '${ _('Catalog') }',
+            url: '/metastore/tables'
+          },{
+            label: '${ _('Dashboard') }',
+            url: '/dashboard/new_search'
+          },{
+            label: '${ _('Scheduler') }',
+            url: '/oozie/editor/workflow/new/'
+          }]
+        }, {
+          label: '${ _('Data Science') }',
+          url: '/',
+          icon: 'altus-icon altus-ds'
+        }]
+      }, {
+        label: '${ _('Compute') }',
+        items: [{
+          label: '${ _('Data Warehouse') }',
+          icon: 'altus-icon altus-dashboard',
+          items: [{
+            label: '${ _('Clusters') }',
+            url: '/'
+          }]
+        },{
+          label: '${ _('Data Engineering') }',
+          icon: 'altus-icon altus-de',
+          items: [{
+            label: '${ _('Clusters') }',
+            url: '/'
+          },{
+            label: '${ _('Jobs') }',
+            url: '/'
+          }]
+        }]
+      },
+        {
+        label: '${ _('Admin') }',
+        items: [{
+          label: '${ _('Environments') }',
+          url: '/',
+          icon: 'altus-icon altus-environment'
+        },{
+          label: '${ _('SDX Namespaces') }',
+          url: '/',
+          icon: 'altus-icon altus-sdx'
+        },{
+          label: '${ _('IAM') }',
+          url: '/',
+          icon: 'altus-icon altus-iam'
+        },{
+          label: '${ _('Support') }',
+          url: '/',
+          icon: 'fa fa-question'
+        }]
+      }
+        ##  , {
+        ##    label: '${ _('Icons') }',
+        ##    items: [{label: 'altus-adb-cluster', url: '/', icon: 'altus-icon altus-adb-cluster'},
+        ##      {label: 'altus-environment', url: '/', icon: 'altus-icon altus-environment'},
+        ##      {label: 'altus-dashboard', url: '/', icon: 'altus-icon altus-dashboard'},
+        ##      {label: 'altus-iam', url: '/', icon: 'altus-icon altus-iam'},
+        ##      {label: 'altus-user-group', url: '/', icon: 'altus-icon altus-user-group'},
+        ##      {label: 'altus-de-cluster', url: '/', icon: 'altus-icon altus-de-cluster'},
+        ##      {label: 'altus-de-job', url: '/', icon: 'altus-icon altus-de-job'},
+        ##      {label: 'altus-adb', url: '/', icon: 'altus-icon altus-adb'},
+        ##      {label: 'altus-de', url: '/', icon: 'altus-icon altus-de'},
+        ##      {label: 'altus-ds', url: '/', icon: 'altus-icon altus-ds'},
+        ##      {label: 'altus-sdx', url: '/', icon: 'altus-icon altus-sdx'},
+        ##      {label: 'altus-na', url: '/', icon: 'altus-icon altus-na'},
+        ##      {label: 'altus-no-access', url: '/', icon: 'altus-icon altus-no-access'},
+        ##      {label: 'altus-user-access', url: '/', icon: 'altus-icon altus-user-access'},
+        ##      {label: 'altus-adb-query', url: '/', icon: 'altus-icon altus-adb-query'},
+        ##      {label: 'altus-workload', url: '/', icon: 'altus-icon altus-workload'},
+        ##      {label: 'altus-azure', url: '/', icon: 'altus-icon altus-azure'},
+        ##      {label: 'altus-aws', url: '/', icon: 'altus-icon altus-aws'},
+        ##      {label: 'altus-user', url: '/', icon: 'altus-icon altus-user'},
+        ##      {label: 'altus-sql-editor', url: '/', icon: 'altus-icon altus-sql-editor'},
+        ##      {label: 'altus-feedback', url: '/', icon: 'altus-icon altus-feedback'}]
+        ##  }
+      ];
+
+      var MultiClusterSidebar = function MultiClusterSidebar() {
+        var self = this;
+        self.categories = ko.observableArray(FIXED_CATEGORIES);
+      };
+
+      ko.components.register('hue-multi-cluster-sidebar', {
+        viewModel: MultiClusterSidebar,
+        template: { element: 'hue-multi-cluster-sidebar-template' }
+      });
+    })();
+  </script>
+</%def>

Some files were not shown because too many files changed in this diff