Browse Source

HUE-8330 [metastore] Add source type and namespace to the Table Browser URL

Johan Ahlen 7 years ago
parent
commit
036befb24e

+ 2 - 4
apps/beeswax/src/beeswax/templates/create_database.mako

@@ -235,13 +235,11 @@ ${ assist.assistPanel() }
       self.apiHelper.withTotalStorage('assist', 'assist_panel_visible', self.isLeftPanelVisible, true);
 
       huePubSub.subscribe("assist.table.selected", function (tableDef) {
-        // TODO: Handle namespaces
-        location.href = '/metastore/table/' + tableDef.database + '/' + tableDef.name;
+        location.href = '/metastore/table/' + tableDef.database + '/' + tableDef.name + '?source=' + tableDef.sourceType + '&namespace=' + tableDef.namespace.id;
       });
 
       huePubSub.subscribe("assist.database.selected", function (databaseDef) {
-        // TODO: Handle namespaces
-        location.href = '/metastore/tables/' + databaseDef.name;
+        location.href = '/metastore/tables/' + databaseDef.name + '?source=' + databaseDef.sourceType + '&namespace=' + databaseDef.namespace.id;
       });
     }
 

+ 2 - 4
apps/beeswax/src/beeswax/templates/create_table_manually.mako

@@ -557,13 +557,11 @@ ${ assist.assistPanel() }
       self.apiHelper.withTotalStorage('assist', 'assist_panel_visible', self.isLeftPanelVisible, true);
 
       huePubSub.subscribe("assist.table.selected", function (tableDef) {
-        // TODO: Handle namespaces
-        location.href = '/metastore/table/' + tableDef.database + '/' + tableDef.name;
+        location.href = '/metastore/table/' + tableDef.database + '/' + tableDef.name  + '?source=' + tableDef.sourceType + '&namespace=' + tableDef.namespace.id;
       });
 
       huePubSub.subscribe("assist.database.selected", function (databaseDef) {
-        // TODO: Handle namespaces
-        location.href = '/metastore/tables/' + databaseDef.name;
+        location.href = '/metastore/tables/' + databaseDef.name + '?source=' + databaseDef.sourceType + '&namespace=' + databaseDef.namespace.id;
       });
     }
 

+ 2 - 4
apps/beeswax/src/beeswax/templates/import_wizard_choose_delimiter.mako

@@ -197,13 +197,11 @@ ${ assist.assistPanel() }
 
 
       huePubSub.subscribe("assist.table.selected", function (tableDef) {
-        // TODO: Handle namespaces
-        location.href = '/metastore/table/' + tableDef.database + '/' + tableDef.name;
+        location.href = '/metastore/table/' + tableDef.database + '/' + tableDef.name + '?source=' + tableDef.sourceType + '&namespace=' + tableDef.namespace.id;
       });
 
       huePubSub.subscribe("assist.database.selected", function (databaseDef) {
-        // TODO: Handle namespaces
-        location.href = '/metastore/tables/' + databaseDef.name;
+        location.href = '/metastore/tables/' + databaseDef.name + '?source=' + databaseDef.sourceType + '&namespace=' + databaseDef.namespace.id;
       });
     }
 

+ 2 - 4
apps/beeswax/src/beeswax/templates/import_wizard_choose_file.mako

@@ -204,13 +204,11 @@ ${ assist.assistPanel() }
 
 
       huePubSub.subscribe("assist.table.selected", function (tableDef) {
-        // TODO: Handle namespaces
-        location.href = '/metastore/table/' + tableDef.database + '/' + tableDef.name;
+        location.href = '/metastore/table/' + tableDef.database + '/' + tableDef.name  + '?source=' + tableDef.sourceType + '&namespace=' + tableDef.namespace.id;
       });
 
       huePubSub.subscribe("assist.database.selected", function (databaseDef) {
-        // TODO: Handle namespaces
-        location.href = '/metastore/tables/' + databaseDef.name;
+        location.href = '/metastore/tables/' + databaseDef.name + '?source=' + databaseDef.sourceType + '&namespace=' + databaseDef.namespace.id;
       });
     }
 

+ 2 - 4
apps/beeswax/src/beeswax/templates/import_wizard_define_columns.mako

@@ -232,13 +232,11 @@ ${ assist.assistPanel() }
 
 
       huePubSub.subscribe("assist.table.selected", function (tableDef) {
-        // TODO: Handle namespaces
-        location.href = '/metastore/table/' + tableDef.database + '/' + tableDef.name;
+        location.href = '/metastore/table/' + tableDef.database + '/' + tableDef.name + '?source=' + tableDef.sourceType + '&namespace=' + tableDef.namespace.id;
       });
 
       huePubSub.subscribe("assist.database.selected", function (databaseDef) {
-        // TODO: Handle namespaces
-        location.href = '/metastore/tables/' + databaseDef.name;
+        location.href = '/metastore/tables/' + databaseDef.name + '?source=' + databaseDef.sourceType + '&namespace=' + databaseDef.namespace.id;
       });
     }
 

+ 105 - 31
apps/metastore/src/metastore/static/metastore/js/metastore.ko.js

@@ -46,6 +46,11 @@ var MetastoreViewModel = (function () {
       });
     });
 
+    // When manually changed through dropdown
+    self.sourceChanged = function () {
+      huePubSub.publish('metastore.url.change')
+    };
+
     self.loading = ko.pureComputed(function () {
       if (!self.source()) {
         return true;
@@ -142,12 +147,18 @@ var MetastoreViewModel = (function () {
         prefix = '/hue' + prefix;
       }
       if (self.source() && self.source().namespace()) {
+        var params = {
+          source: self.source().type
+        };
+        if (self.source().namespaces().length > 1) {
+          params.namespace = self.source().namespace().id
+        }
         if (self.source().namespace().database() && self.source().namespace().database().table()) {
-          hueUtils.changeURL(prefix + 'table/' + self.source().namespace().database().table().catalogEntry.path.join('/'));
+          hueUtils.changeURL(prefix + 'table/' + self.source().namespace().database().table().catalogEntry.path.join('/'), params);
         } else if (self.source().namespace().database()) {
-          hueUtils.changeURL(prefix + 'tables/' + self.source().namespace().database().catalogEntry.name);
+          hueUtils.changeURL(prefix + 'tables/' + self.source().namespace().database().catalogEntry.name, params);
         } else {
-          hueUtils.changeURL(prefix + 'databases');
+          hueUtils.changeURL(prefix + 'databases', params);
         }
       }
     });
@@ -246,37 +257,100 @@ var MetastoreViewModel = (function () {
     if (path[0] === 'metastore') {
       path.shift();
     }
-    var namespace = self.source().namespace();
-    switch (path[0]) {
-      case 'databases':
-        if (namespace.database()) {
-          namespace.database().table(null);
-          namespace.database(null);
-        }
-        break;
-      case 'tables':
-        if (namespace.database()) {
-          namespace.database().table(null);
+    var loadedDeferred = $.Deferred();
+
+    if (!self.loading()) {
+      loadedDeferred.resolve();
+    } else {
+      var loadSub = self.loading.subscribe(function () {
+        loadSub.dispose();
+        loadedDeferred.resolve();
+      })
+    }
+
+    var sourceAndNamespaceDeferred = $.Deferred();
+
+    loadedDeferred.done(function () {
+      var search = location.search;
+      if (search) {
+        search = search.replace('?', '');
+        var namespaceId;
+        var sourceType;
+        search.split('&').forEach(function (param) {
+          if (param.indexOf('namespace=') === 0) {
+            namespaceId = param.replace('namespace=', '');
+          }
+          if (param.indexOf('source=') === 0) {
+            sourceType = param.replace('source=', '');
+          }
+        });
+
+        if (sourceType && sourceType !== self.source().type) {
+          var found = self.sources().some(function (source) {
+            if (source.type === sourceType) {
+              self.source(source);
+              return true;
+            }
+          });
+          if (!found) {
+            sourceAndNamespaceDeferred.reject();
+            return;
+          }
         }
-        namespace.setDatabaseByName(path[1]);
-        break;
-      case 'table':
-        huePubSub.subscribe('metastore.loaded.table', function() {
-          self.currentTab('overview');
-        }, 'metastore');
-        self.loadTableDef({
-          name: path[2],
-          database: path[1],
-          sourceType: self.source().type,
-          namespace: namespace
-        }, function(){
-          if (path.length > 3 && path[3] === 'partitions'){
-            huePubSub.subscribe('metastore.loaded.partitions', function() {
-              self.currentTab('partitions');
-            }, 'metastore');
+
+        self.source().lastLoadNamespacesDeferred.done(function () {
+          if (namespaceId && namespaceId !== self.source().namespace().id) {
+            var found = self.source().namespaces().some(function (namespace) {
+              if (namespace.id === namespaceId) {
+                self.source().namespace(namespace);
+                return true;
+              }
+            });
+            if (!found) {
+              sourceAndNamespaceDeferred.reject();
+              return;
+            } else {
+              sourceAndNamespaceDeferred.resolve();
+            }
           }
         });
-    }
+      }
+    });
+
+
+    sourceAndNamespaceDeferred.done(function () {
+      var namespace = self.source().namespace();
+      switch (path[0]) {
+        case 'databases':
+          if (namespace.database()) {
+            namespace.database().table(null);
+            namespace.database(null);
+          }
+          break;
+        case 'tables':
+          if (namespace.database()) {
+            namespace.database().table(null);
+          }
+          namespace.setDatabaseByName(path[1]);
+          break;
+        case 'table':
+          huePubSub.subscribe('metastore.loaded.table', function() {
+            self.currentTab('overview');
+          }, 'metastore');
+          self.loadTableDef({
+            name: path[2],
+            database: path[1],
+            sourceType: self.source().type,
+            namespace: namespace
+          }, function(){
+            if (path.length > 3 && path[3] === 'partitions'){
+              huePubSub.subscribe('metastore.loaded.partitions', function() {
+                self.currentTab('partitions');
+              }, 'metastore');
+            }
+          });
+      }
+    })
   };
 
   return MetastoreViewModel;

+ 5 - 0
apps/metastore/src/metastore/static/metastore/js/metastore.model.js

@@ -38,6 +38,11 @@ var MetastoreSource = (function () {
       }
     });
 
+    // When manually changed through dropdown
+    self.namespaceChanged = function () {
+      huePubSub.publish('metastore.url.change')
+    };
+
     huePubSub.subscribe("assist.db.panel.ready", function () {
       self.lastLoadNamespacesDeferred.done(function () {
         huePubSub.publish('assist.set.database', {

+ 4 - 4
apps/metastore/src/metastore/templates/metastore.mako

@@ -83,10 +83,10 @@ ${ components.menubar(is_embeddable) }
 
 <script type="text/html" id="metastore-breadcrumbs">
   <div style="font-size: 14px; margin: 0 12px; line-height: 27px;">
-    <div data-bind="component: { name: 'hue-drop-down', params: { value: source, entries: sources, labelAttribute: 'name', searchable: true, linkTitle: '${ _ko('Source') }' } }" style="display: inline-block"></div>
+    <div data-bind="component: { name: 'hue-drop-down', params: { value: source, entries: sources, onChanged: sourceChanged, labelAttribute: 'name', searchable: true, linkTitle: '${ _ko('Source') }' } }" style="display: inline-block"></div>
     <!-- ko with: source -->
     <!-- ko if: namespaces().length > 1 -->
-    <div class="margin-left-10" data-bind="component: { name: 'hue-drop-down', params: { value: namespace, entries: namespaces, labelAttribute: 'name', searchable: true, linkTitle: '${ _ko('Namespace') }' } }" style="display: inline-block"></div>
+    <div class="margin-left-10" data-bind="component: { name: 'hue-drop-down', params: { value: namespace, entries: namespaces, onChanged: namespaceChanged, labelAttribute: 'name', searchable: true, linkTitle: '${ _ko('Namespace') }' } }" style="display: inline-block"></div>
     <!-- /ko -->
     <!-- /ko -->
   </div>
@@ -1032,10 +1032,10 @@ ${ components.menubar(is_embeddable) }
 
           <!-- ko with: source -->
           <!-- ko with: namespace -->
-          <!-- ko template: { if: !loading() && database() === null, name: 'metastore-databases' } --><!-- /ko -->
+          <!-- ko template: { if: !loading() && !database(), name: 'metastore-databases' } --><!-- /ko -->
           <!-- ko with: database -->
           <i data-bind="visible: loading" class="fa fa-spinner fa-spin fa-2x margin-left-10" style="color: #999; display: none;"></i>
-          <!-- ko template: { if: !loading() && table() === null, name: 'metastore-tables' } --><!-- /ko -->
+          <!-- ko template: { if: !loading() && !table(), name: 'metastore-tables' } --><!-- /ko -->
           <!-- ko with: table -->
             <!-- ko template: 'metastore-describe-table' --><!-- /ko -->
           <!-- /ko -->

+ 2 - 2
desktop/core/src/desktop/static/desktop/js/assist/assistDbEntry.js

@@ -411,9 +411,9 @@ var AssistDbEntry = (function () {
     var self = this;
     var url;
     if (self.catalogEntry.isDatabase()) {
-      url = '/metastore/tables/' + self.catalogEntry.name;
+      url = '/metastore/tables/' + self.catalogEntry.name + '?source=' + self.catalogEntry.getSourceType() + '&namespace=' + self.catalogEntry.namespace.id;
     } else if (self.catalogEntry.isTableOrView()) {
-      url = '/metastore/table/' + self.parent.catalogEntry.name + '/' + self.catalogEntry.name;
+      url = '/metastore/table/' + self.parent.catalogEntry.name + '/' + self.catalogEntry.name + '?source=' + self.catalogEntry.getSourceType() + '&namespace=' + self.catalogEntry.namespace.id;
     } else {
       return;
     }

+ 33 - 6
desktop/core/src/desktop/static/desktop/js/hue.utils.js

@@ -223,15 +223,42 @@ window.hueUtils = window.hueUtils || (function () {
     }
   };
 
-  hueUtils.changeURL = function (newURL) {
+  hueUtils.changeURL = function (newURL, params) {
+    var extraSearch = '';
+    if (params) {
+      var newSearchKeys = Object.keys(params);
+      if (newSearchKeys.length) {
+        while (newSearchKeys.length) {
+          var newKey = newSearchKeys.pop();
+          extraSearch += newKey + '=' + params[newKey];
+          if (newSearchKeys.length) {
+            extraSearch += '&';
+          }
+        }
+      }
+    }
+
     if (typeof IS_EMBEDDED !== 'undefined' && IS_EMBEDDED) {
-      newURL = window.location.pathname + window.location.search + '#!' + newURL.replace('/hue', '');
-    } else {
-      if (window.location.hash !== '' && newURL.indexOf('#') === -1){
-        newURL = newURL + window.location.hash;
+      var search = window.locations.search;
+      if (extraSearch) {
+        search += (search ? '&' : '?') + extraSearch
       }
+      newURL = window.location.pathname + search + '#!' + newURL.replace('/hue', '');
+      window.history.pushState(null, null, newURL);
+      return;
+    }
+
+    var hashSplit = newURL.split('#');
+    var url = hashSplit[0];
+    if (extraSearch) {
+      url += (url.indexOf('?') === -1 ? '?' : '&') + extraSearch;
+    }
+    if (hashSplit.length > 1) {
+      url += '#' + hashSplit[1];
+    } else if (window.location.hash) {
+      url += window.location.hash;
     }
-    window.history.pushState(null, null, newURL);
+    window.history.pushState(null, null, url);
   };
 
   hueUtils.replaceURL = function (newURL) {

+ 2 - 1
desktop/core/src/desktop/templates/ko_components/ko_context_popover.mako

@@ -633,7 +633,8 @@ from metadata.conf import has_navigator
 
       DataCatalogContext.prototype.openInTableBrowser = function () {
         var self = this;
-        huePubSub.publish('open.link', '/metastore/table' + (self.catalogEntry().isTableOrView() ? '/' : 's/') + self.catalogEntry().path.join('/'));
+        huePubSub.publish('open.link', '/metastore/table' + (self.catalogEntry().isTableOrView() ? '/' : 's/') + self.catalogEntry().path.join('/')
+                + '?source=' + self.catalogEntry().getSourceType() + '&namespace=' + self.catalogEntry().namespace.id);
         huePubSub.publish('context.popover.hide');
         huePubSub.publish('global.search.close');
       };

+ 4 - 2
desktop/core/src/desktop/templates/ko_components/ko_drop_down.mako

@@ -46,7 +46,7 @@ from desktop.views import _ko
           <li class="divider"></li>
           <!-- /ko -->
           <!-- ko if: typeof $data.divider === 'undefined' || !$data.divider -->
-          <li><a href="javascript:void(0)" data-bind="text: $data && typeof $data[$parent.labelAttribute] !== 'undefined' ? $data[$parent.labelAttribute] : $data, click: function () { $parent.value($data); }"></a></li>
+          <li><a href="javascript:void(0)" data-bind="text: $data && typeof $data[$parent.labelAttribute] !== 'undefined' ? $data[$parent.labelAttribute] : $data, click: function () { $parent.value($data); $parent.onChanged($data); }"></a></li>
           <!-- /ko -->
         </ul>
         <!-- /ko -->
@@ -56,7 +56,7 @@ from desktop.views import _ko
           <li class="divider"></li>
           <!-- /ko -->
           <!-- ko if: typeof $data.divider === 'undefined' || !$data.divider -->
-          <li><a href="javascript:void(0)" data-bind="text: $data && typeof $data[$parent.labelAttribute] !== 'undefined' ? $data[$parent.labelAttribute] : $data, click: function () { $parent.value($data); }"></a></li>
+          <li><a href="javascript:void(0)" data-bind="text: $data && typeof $data[$parent.labelAttribute] !== 'undefined' ? $data[$parent.labelAttribute] : $data, click: function () { $parent.value($data); $parent.onChanged($data); }"></a></li>
           <!-- /ko -->
         </ul>
         <!-- /ko -->
@@ -166,6 +166,7 @@ from desktop.views import _ko
         self.foreachVisible = params.foreachVisible || false;
         self.linkTitle = params.linkTitle || '${ _('Selected entry') }';
         self.fixedPosition = !!params.fixedPosition;
+        self.onChanged = params.onChanged || function () {};
 
         self.inputPlaceHolder = ko.pureComputed(function () {
           return self.value() && typeof self.value() === 'object' ? self.value()[self.labelAttribute] : self.value();
@@ -184,6 +185,7 @@ from desktop.views import _ko
 
         self.onEnter = function (value) {
           self.value(value);
+          self.onChanged(value);
           self.dropDownVisible(false);
         };