Browse Source

HUE-9191 [ui] Show foreign key details in a tooltip for entries in the DB assist

Johan Ahlen 5 years ago
parent
commit
5b36ae0ba5

+ 2 - 2
desktop/core/src/desktop/js/catalog/dataCatalogEntry.js

@@ -413,7 +413,7 @@ class DataCatalogEntry {
         const foreignKeys = {};
         if (sourceMeta.foreign_keys) {
           sourceMeta.foreign_keys.forEach(foreignKey => {
-            foreignKeys[foreignKey.name] = true;
+            foreignKeys[foreignKey.name] = foreignKey;
           });
         }
 
@@ -456,7 +456,7 @@ class DataCatalogEntry {
                         definition.primaryKey = !!primaryKeys[entity.name];
                       }
                       if (sourceMeta.foreign_keys) {
-                        definition.foreignKey = !!foreignKeys[entity.name];
+                        definition.foreignKey = foreignKeys[entity.name];
                       }
                       definition.index = index++;
                       catalogEntry.definition = definition;

+ 5 - 3
desktop/core/src/desktop/js/ko/bindings/ko.tooltip.js

@@ -16,10 +16,12 @@
 
 import $ from 'jquery';
 import * as ko from 'knockout';
-
+import { registerBinding } from './bindingUtils';
 import hueUtils from 'utils/hueUtils';
 
-ko.bindingHandlers.tooltip = {
+export const NAME = 'tooltip';
+
+registerBinding(NAME, {
   after: ['attr'],
   update: function(element, valueAccessor) {
     const local = ko.utils.unwrapObservable(valueAccessor());
@@ -44,4 +46,4 @@ ko.bindingHandlers.tooltip = {
       $(element).tooltip('destroy');
     });
   }
-};
+});

+ 16 - 0
desktop/core/src/desktop/js/ko/components/assist/__snapshots__/ko.assistKey.test.js.snap

@@ -0,0 +1,16 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ko.assistKey.js should render component 1`] = `
+"<div data-bind=\\"descendantsComplete: descendantsComplete, component: { name: &quot;hue-assist-key&quot;, params: params }\\"><a class=\\"assist-field-link\\" style=\\"padding: 0 2px;\\" href=\\"javascript: void(0);\\" data-bind=\\"
+          tooltip: {
+            title: foreignKeyTooltipHtml,
+            html: true,
+            placement: 'bottom'
+          },
+          click: highlight
+        \\" data-original-title=\\"\\"><i class=\\"fa fa-key\\"></i></a><i class=\\"fa fa-key\\" style=\\"padding: 0 2px;\\" data-bind=\\"
+        tooltip: {
+          title: 'Primary Key',
+          placement: 'bottom'
+        }\\" data-original-title=\\"\\"></i><i class=\\"fa fa-key\\"></i></div>"
+`;

+ 6 - 4
desktop/core/src/desktop/js/ko/components/assist/ko.assistDbPanel.js

@@ -37,6 +37,8 @@ import {
   SHOW_LEFT_ASSIST_EVENT
 } from './events';
 
+import { NAME as ASSIST_KEY_COMPONENT_NAME } from './ko.assistKey';
+
 const ASSIST_TABLE_TEMPLATES = `
   <script type="text/html" id="assist-no-database-entries">
     <ul class="assist-tables">
@@ -177,12 +179,12 @@ const ASSIST_TABLE_TEMPLATES = `
       </div>
       <!-- ko if: expandable -->
       <a class="assist-entry assist-field-link" href="javascript:void(0)" data-bind="click: toggleOpen, attr: {'title': catalogEntry.getTitle(true) }, css: { 'assist-entry-left-action': navigationSettings.rightAssist }">
-        <span class="highlightable" data-bind="css: { 'highlight': highlight}, attr: {'column': columnName, 'table': tableName, 'database': databaseName }, text: catalogEntry.getDisplayName(), draggableText: { text: editorText, meta: {'type': 'sql', 'column': columnName, 'table': tableName, 'database': databaseName } }"></span><!-- ko if: catalogEntry.isKey() --> <i class="fa fa-key"></i><!-- /ko -->
+        <span class="highlightable" data-bind="css: { 'highlight': highlight}, attr: {'column': columnName, 'table': tableName, 'database': databaseName }, text: catalogEntry.getDisplayName(), draggableText: { text: editorText, meta: {'type': 'sql', 'column': columnName, 'table': tableName, 'database': databaseName } }"></span><!-- ko if: catalogEntry.isKey() --> <!-- ko component: { name: '${ASSIST_KEY_COMPONENT_NAME}', params: catalogEntry } --><!-- /ko --><!-- /ko -->
       </a>
       <!-- /ko -->
       <!-- ko ifnot: expandable -->
       <div class="assist-entry assist-field-link default-cursor" href="javascript:void(0)" data-bind="event: { dblclick: dblClick }, attr: {'title': catalogEntry.getTitle(true) }, css: { 'assist-entry-left-action': navigationSettings.rightAssist }">
-        <span class="highlightable" data-bind="css: { 'highlight': highlight}, attr: {'column': columnName, 'table': tableName, 'database': databaseName}, text: catalogEntry.getDisplayName(), draggableText: { text: editorText, meta: {'type': 'sql', 'column': columnName, 'table': tableName, 'database': databaseName} }"></span><!-- ko if: catalogEntry.isKey()  --> <i class="fa fa-key"></i><!-- /ko -->
+        <span class="highlightable" data-bind="css: { 'highlight': highlight}, attr: {'column': columnName, 'table': tableName, 'database': databaseName}, text: catalogEntry.getDisplayName(), draggableText: { text: editorText, meta: {'type': 'sql', 'column': columnName, 'table': tableName, 'database': databaseName} }"></span><!-- ko if: catalogEntry.isKey() --> <!-- ko component: { name: '${ASSIST_KEY_COMPONENT_NAME}', params: catalogEntry } --><!-- /ko --><!-- /ko -->
       </div>
       <!-- /ko -->
       <div class="center assist-spinner" data-bind="visible: loading"><i class="fa fa-spinner fa-spin"></i></div>
@@ -200,13 +202,13 @@ const ASSIST_TABLE_TEMPLATES = `
       <!-- ko if: expandable -->
       <a class="assist-entry assist-field-link assist-field-link-dark assist-entry-left-action assist-ellipsis" href="javascript:void(0)" data-bind="click: toggleOpen, attr: {'title': catalogEntry.getTitle(true) }">
         <span data-bind="text: catalogEntry.getType()" class="muted pull-right margin-right-20"></span>
-        <span class="highlightable" data-bind="css: { 'highlight': highlight}, attr: {'column': columnName, 'table': tableName, 'database': databaseName }, text: catalogEntry.name, draggableText: { text: editorText, meta: {'type': 'sql', 'column': columnName, 'table': tableName, 'database': databaseName } }"></span><!-- ko if: catalogEntry.isKey() --> <i class="fa fa-key"></i><!-- /ko -->
+        <span class="highlightable" data-bind="css: { 'highlight': highlight}, attr: {'column': columnName, 'table': tableName, 'database': databaseName }, text: catalogEntry.name, draggableText: { text: editorText, meta: {'type': 'sql', 'column': columnName, 'table': tableName, 'database': databaseName } }"></span><!-- ko if: catalogEntry.isKey() --> <!-- ko component: { name: '${ASSIST_KEY_COMPONENT_NAME}', params: catalogEntry } --><!-- /ko --><!-- /ko -->
       </a>
       <!-- /ko -->
       <!-- ko ifnot: expandable -->
       <div class="assist-entry assist-field-link assist-field-link-dark default-cursor assist-ellipsis" href="javascript:void(0)" data-bind="event: { dblclick: dblClick }, attr: {'title': catalogEntry.getTitle(true) }, css: { 'assist-entry-left-action': navigationSettings.rightAssist }">
         <span data-bind="text: catalogEntry.getType()" class="muted pull-right margin-right-20"></span>
-        <span class="highlightable" data-bind="css: { 'highlight': highlight}, attr: {'column': columnName, 'table': tableName, 'database': databaseName}, text: catalogEntry.name, draggableText: { text: editorText, meta: {'type': 'sql', 'column': columnName, 'table': tableName, 'database': databaseName} }"></span><!-- ko if: catalogEntry.isKey() --> <i class="fa fa-key"></i><!-- /ko -->
+        <span class="highlightable" data-bind="css: { 'highlight': highlight}, attr: {'column': columnName, 'table': tableName, 'database': databaseName}, text: catalogEntry.name, draggableText: { text: editorText, meta: {'type': 'sql', 'column': columnName, 'table': tableName, 'database': databaseName} }"></span><!-- ko if: catalogEntry.isKey() --> <!-- ko component: { name: '${ASSIST_KEY_COMPONENT_NAME}', params: catalogEntry } --><!-- /ko --><!-- /ko -->
       </div>
       <!-- /ko -->
       <div class="center assist-spinner" data-bind="visible: loading"><i class="fa fa-spinner fa-spin"></i></div>

+ 76 - 0
desktop/core/src/desktop/js/ko/components/assist/ko.assistKey.js

@@ -0,0 +1,76 @@
+// 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.
+
+import ko from 'knockout';
+
+import componentUtils from 'ko/components/componentUtils';
+import huePubSub from 'utils/huePubSub';
+import I18n from 'utils/i18n';
+import { ASSIST_DB_HIGHLIGHT_EVENT } from './events';
+
+import 'ko/bindings/ko.tooltip';
+
+export const NAME = 'hue-assist-key';
+
+const TEMPLATE = `
+  <!-- ko if: entry.definition.foreignKey -->
+    <!-- ko if: entry.definition.foreignKey.to -->
+      <a class="assist-field-link" style="padding: 0 2px;" href="javascript: void(0);" data-bind="
+          tooltip: {
+            title: foreignKeyTooltipHtml,
+            html: true,
+            placement: 'bottom'
+          },
+          click: highlight
+        "><i class="fa fa-key"></i></a>
+    <!-- /ko -->
+  <!-- /ko -->
+  <!-- ko if: entry.definition.primaryKey -->
+    <i class="fa fa-key" style="padding: 0 2px;" data-bind="
+        tooltip: {
+          title: '${I18n('Primary Key')}',
+          placement: 'bottom'
+        }"></i>
+  <!-- /ko -->
+  <!-- ko ifnot: entry.definition.foreignKey || entry.definition.primaryKey -->
+  <i class="fa fa-key"></i>
+  <!-- /ko -->
+`;
+
+class AssistKey {
+  constructor(entry) {
+    this.entry = entry;
+
+    this.foreignKeyTooltipHtml = ko.pureComputed(
+      () => `<i style="margin-right: 4px" class="fa fa-arrow-right"></i>
+    ${entry.definition.foreignKey && entry.definition.foreignKey.to}`
+    );
+  }
+
+  highlight(entry, event) {
+    this.entry.dataCatalog
+      .getEntry({
+        path: this.entry.definition.foreignKey.to,
+        namespace: this.entry.namespace,
+        compute: this.entry.compute
+      })
+      .then(entry => {
+        huePubSub.publish(ASSIST_DB_HIGHLIGHT_EVENT, entry);
+      });
+  }
+}
+
+componentUtils.registerComponent(NAME, AssistKey, TEMPLATE);

+ 35 - 0
desktop/core/src/desktop/js/ko/components/assist/ko.assistKey.test.js

@@ -0,0 +1,35 @@
+// 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.
+
+import 'ext/bootstrap.2.3.2.min';
+
+import { koSetup } from 'jest/koTestUtils';
+import { NAME } from './ko.assistKey';
+
+describe('ko.assistKey.js', () => {
+  const setup = koSetup();
+
+  it('should render component', async () => {
+    const entry = {
+      definition: {
+        primaryKey: true
+      }
+    };
+    const element = await setup.renderComponent(NAME, entry);
+
+    expect(element.innerHTML).toMatchSnapshot();
+  });
+});