Browse Source

HUE-8237 [assist] Improvements to the file context popover

- Improved styling
- Header for preview
- Open in File Browser link
- Detail added to file context menu in the assist
Johan Ahlen 7 years ago
parent
commit
c4784ee874

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


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
+ 0 - 0
desktop/core/src/desktop/static/desktop/css/hue3-extra.css


+ 13 - 1
desktop/core/src/desktop/static/desktop/js/assist/assistStorageEntry.js

@@ -66,6 +66,7 @@ var AssistStorageEntry = (function () {
     self.currentPage = 1;
     self.currentPage = 1;
     self.hasMorePages = true;
     self.hasMorePages = true;
     self.preview = ko.observable();
     self.preview = ko.observable();
+    self.contextPopoverVisible = ko.observable(false);
 
 
     self.filter = ko.observable('').extend({ rateLimit: 400 });
     self.filter = ko.observable('').extend({ rateLimit: 400 });
 
 
@@ -288,9 +289,16 @@ var AssistStorageEntry = (function () {
     });
     });
   };
   };
 
 
-  AssistStorageEntry.prototype.showContextPopover = function (entry, event) {
+  AssistStorageEntry.prototype.showContextPopover = function (entry, event, positionAdjustment) {
     var $source = $(event.target);
     var $source = $(event.target);
     var offset = $source.offset();
     var offset = $source.offset();
+    entry.contextPopoverVisible(true);
+
+    if (positionAdjustment) {
+      offset.left += positionAdjustment.left;
+      offset.top += positionAdjustment.top;
+    }
+
 
 
     huePubSub.publish('context.popover.show', {
     huePubSub.publish('context.popover.show', {
       data: {
       data: {
@@ -307,6 +315,10 @@ var AssistStorageEntry = (function () {
         bottom: offset.top + $source.height() - 3
         bottom: offset.top + $source.height() - 3
       }
       }
     });
     });
+
+    huePubSub.subscribeOnce('context.popover.hidden', function () {
+      entry.contextPopoverVisible(false);
+    });
   };
   };
 
 
   AssistStorageEntry.prototype.openInImporter = function () {
   AssistStorageEntry.prototype.openInImporter = function () {

+ 7 - 2
desktop/core/src/desktop/static/desktop/less/components/hue-popover.less

@@ -248,8 +248,13 @@
 }
 }
 
 
 .context-popover-header {
 .context-popover-header {
-  font-size: 15px;
-  margin: 10px;
+  font-weight: bold;
+  color: @hue-primary-color-dark;
+  font-size: 14px;
+  text-transform: uppercase;
+  padding-left: 4px;
+  display: inline-block;
+  margin: 5px 0 0 15px;
 }
 }
 
 
 .context-popover-section {
 .context-popover-section {

+ 10 - 9
desktop/core/src/desktop/templates/assist.mako

@@ -86,7 +86,7 @@ from desktop.views import _ko
   <script type="text/html" id="sql-context-items">
   <script type="text/html" id="sql-context-items">
     <!-- ko if: typeof catalogEntry !== 'undefined' -->
     <!-- ko if: typeof catalogEntry !== 'undefined' -->
       <!-- ko if: sourceType === 'solr' -->
       <!-- ko if: sourceType === 'solr' -->
-        <li><a href="javascript:void(0);" data-bind="click: function (data) { showContextPopover(data, { target: $parentContext.$contextSourceElement }, { left: 4, top: 2 }); }"><i class="fa fa-fw fa-info"></i> ${ _('Show details') }</a></li>
+        <li><a href="javascript:void(0);" data-bind="click: function (data) { showContextPopover(data, { target: $parentContext.$contextSourceElement }, { left: -15, top: 2 }); }"><i class="fa fa-fw fa-info"></i> ${ _('Show details') }</a></li>
         <!-- ko if: catalogEntry.isTableOrView() -->
         <!-- ko if: catalogEntry.isTableOrView() -->
         <li><a href="javascript:void(0);" data-bind="click: openInIndexer"><i class="fa fa-fw fa-table"></i> ${ _('Open in Browser') }</a></li>
         <li><a href="javascript:void(0);" data-bind="click: openInIndexer"><i class="fa fa-fw fa-table"></i> ${ _('Open in Browser') }</a></li>
         <li>
         <li>
@@ -97,7 +97,7 @@ from desktop.views import _ko
         <!-- /ko -->
         <!-- /ko -->
       <!-- /ko -->
       <!-- /ko -->
       <!-- ko ifnot: sourceType === 'solr' -->
       <!-- ko ifnot: sourceType === 'solr' -->
-        <li><a href="javascript:void(0);" data-bind="click: function (data) { showContextPopover(data, { target: $parentContext.$contextSourceElement }, { left: 4, top: 2 }); }"><i class="fa fa-fw fa-info"></i> ${ _('Show details') }</a></li>
+        <li><a href="javascript:void(0);" data-bind="click: function (data) { showContextPopover(data, { target: $parentContext.$contextSourceElement }, { left: -15, top: 2 }); }"><i class="fa fa-fw fa-info"></i> ${ _('Show details') }</a></li>
         <!-- ko if: !catalogEntry.isDatabase() && $currentApp() === 'editor' -->
         <!-- ko if: !catalogEntry.isDatabase() && $currentApp() === 'editor' -->
         <li><a href="javascript:void(0);" data-bind="click: dblClick"><i class="fa fa-fw fa-paste"></i> ${ _('Insert at cursor') }</a></li>
         <li><a href="javascript:void(0);" data-bind="click: dblClick"><i class="fa fa-fw fa-paste"></i> ${ _('Insert at cursor') }</a></li>
         <!-- /ko -->
         <!-- /ko -->
@@ -172,6 +172,7 @@ from desktop.views import _ko
   </script>
   </script>
 
 
   <script type="text/html" id="hdfs-context-items">
   <script type="text/html" id="hdfs-context-items">
+    <li><a href="javascript:void(0);" data-bind="click: function (data) { showContextPopover(data, { target: $parentContext.$contextSourceElement }, { left: -15, top: 2 }); }"><i class="fa fa-fw fa-info"></i> ${ _('Show details') }</a></li>
     <li><a href="javascript:void(0);" data-bind="hueLink: definition.url"><i class="fa fa-fw" data-bind="css: {'fa-folder-open-o': definition.type === 'dir', 'fa-file-text-o': definition.type === 'file'}"></i> ${ _('Open in Browser') }</a></li>
     <li><a href="javascript:void(0);" data-bind="hueLink: definition.url"><i class="fa fa-fw" data-bind="css: {'fa-folder-open-o': definition.type === 'dir', 'fa-file-text-o': definition.type === 'file'}"></i> ${ _('Open in Browser') }</a></li>
     <!-- ko if: IS_HUE_4 && definition.type === 'file' -->
     <!-- ko if: IS_HUE_4 && definition.type === 'file' -->
     <li><a href="javascript:void(0);" data-bind="click: openInImporter"><!-- ko template: { name: 'app-icon-template', data: { icon: 'importer' } } --><!-- /ko --> ${ _('Open in Importer') }</a></li>
     <li><a href="javascript:void(0);" data-bind="click: openInImporter"><!-- ko template: { name: 'app-icon-template', data: { icon: 'importer' } } --><!-- /ko --> ${ _('Open in Importer') }</a></li>
@@ -186,7 +187,7 @@ from desktop.views import _ko
     <li><a href="javascript: void(0);" data-bind="click: open"><i class="fa fa-fw fa-folder-open-o"></i> ${ _('Open folder') }</a></li>
     <li><a href="javascript: void(0);" data-bind="click: open"><i class="fa fa-fw fa-folder-open-o"></i> ${ _('Open folder') }</a></li>
     <!-- /ko -->
     <!-- /ko -->
     <!-- ko if: definition().type !== 'directory' -->
     <!-- ko if: definition().type !== 'directory' -->
-    <li><a href="javascript: void(0);" data-bind="click: function(data) { showContextPopover(data, { target: $parentContext.$contextSourceElement }, { left: 4, top: 2 }); }"><i class="fa fa-fw fa-info"></i> ${ _('Show details') }</a></li>
+    <li><a href="javascript: void(0);" data-bind="click: function(data) { showContextPopover(data, { target: $parentContext.$contextSourceElement }, { left: -15, top: 2 }); }"><i class="fa fa-fw fa-info"></i> ${ _('Show details') }</a></li>
     <li><a href="javascript: void(0);" data-bind="click: open"><i class="fa fa-fw fa-edit"></i> ${ _('Open document') }</a></li>
     <li><a href="javascript: void(0);" data-bind="click: open"><i class="fa fa-fw fa-edit"></i> ${ _('Open document') }</a></li>
     <li><a href="javascript: void(0);" data-bind="click: function() { huePubSub.publish('doc.show.delete.modal', $data); activeEntry().getSelectedDocsWithDependents(); activeEntry().showDeleteConfirmation(); }"><i class="fa fa-fw fa-trash-o"></i> ${ _('Delete document') }</a></li>
     <li><a href="javascript: void(0);" data-bind="click: function() { huePubSub.publish('doc.show.delete.modal', $data); activeEntry().getSelectedDocsWithDependents(); activeEntry().showDeleteConfirmation(); }"><i class="fa fa-fw fa-trash-o"></i> ${ _('Delete document') }</a></li>
     <!-- /ko -->
     <!-- /ko -->
@@ -372,9 +373,9 @@ from desktop.views import _ko
       <div data-bind="visible: ! loading() && ! hasErrors()" style="position: relative;">
       <div data-bind="visible: ! loading() && ! hasErrors()" style="position: relative;">
         <!-- ko hueSpinner: { spin: loadingMore, overlay: true } --><!-- /ko -->
         <!-- ko hueSpinner: { spin: loadingMore, overlay: true } --><!-- /ko -->
         <ul class="assist-tables" data-bind="foreachVisible: { data: entries, minHeight: 22, container: '.assist-s3-scrollable', fetchMore: $data.fetchMore.bind($data) }">
         <ul class="assist-tables" data-bind="foreachVisible: { data: entries, minHeight: 22, container: '.assist-s3-scrollable', fetchMore: $data.fetchMore.bind($data) }">
-          <li class="assist-entry assist-table-link" style="position: relative;" data-bind="appAwareTemplateContextMenu: { template: 'hdfs-context-items', scrollContainer: '.assist-s3-scrollable' }, visibleOnHover: { 'selector': '.assist-actions' }">
+          <li class="assist-entry assist-table-link" style="position: relative;" data-bind="appAwareTemplateContextMenu: { template: 'hdfs-context-items', scrollContainer: '.assist-s3-scrollable' }, visibleOnHover: { override: contextPopoverVisible, 'selector': '.assist-actions' }">
             <div class="assist-actions table-actions" style="opacity: 0;" >
             <div class="assist-actions table-actions" style="opacity: 0;" >
-              <a style="padding: 0 3px;" class="inactive-action" href="javascript:void(0);" data-bind="click: showContextPopover">
+              <a style="padding: 0 3px;" class="inactive-action" href="javascript:void(0);" data-bind="click: showContextPopover, css: { 'blue': contextPopoverVisible }">
                 <i class='fa fa-info' title="${ _('Details') }"></i>
                 <i class='fa fa-info' title="${ _('Details') }"></i>
               </a>
               </a>
             </div>
             </div>
@@ -519,9 +520,9 @@ from desktop.views import _ko
       <div data-bind="visible: ! loading() && ! hasErrors()" style="position: relative;">
       <div data-bind="visible: ! loading() && ! hasErrors()" style="position: relative;">
         <!-- ko hueSpinner: { spin: loadingMore, overlay: true } --><!-- /ko -->
         <!-- ko hueSpinner: { spin: loadingMore, overlay: true } --><!-- /ko -->
         <ul class="assist-tables" data-bind="foreachVisible: { data: entries, minHeight: 22, container: '.assist-hdfs-scrollable', fetchMore: $data.fetchMore.bind($data) }">
         <ul class="assist-tables" data-bind="foreachVisible: { data: entries, minHeight: 22, container: '.assist-hdfs-scrollable', fetchMore: $data.fetchMore.bind($data) }">
-          <li class="assist-entry assist-table-link" style="position: relative;" data-bind="appAwareTemplateContextMenu: { template: 'hdfs-context-items', scrollContainer: '.assist-hdfs-scrollable' }, visibleOnHover: { 'selector': '.assist-actions' }">
+          <li class="assist-entry assist-table-link" style="position: relative;" data-bind="appAwareTemplateContextMenu: { template: 'hdfs-context-items', scrollContainer: '.assist-hdfs-scrollable' }, visibleOnHover: { override: contextPopoverVisible, 'selector': '.assist-actions' }">
             <div class="assist-actions table-actions" style="opacity: 0;" >
             <div class="assist-actions table-actions" style="opacity: 0;" >
-              <a style="padding: 0 3px;" class="inactive-action" href="javascript:void(0);" data-bind="click: showContextPopover">
+              <a style="padding: 0 3px;" class="inactive-action" href="javascript:void(0);" data-bind="click: showContextPopover, css: { 'blue': contextPopoverVisible }">
                 <i class='fa fa-info' title="${ _('Details') }"></i>
                 <i class='fa fa-info' title="${ _('Details') }"></i>
               </a>
               </a>
             </div>
             </div>
@@ -577,9 +578,9 @@ from desktop.views import _ko
       <div data-bind="visible: ! loading() && ! hasErrors()" style="position: relative;">
       <div data-bind="visible: ! loading() && ! hasErrors()" style="position: relative;">
         <!-- ko hueSpinner: { spin: loadingMore, overlay: true } --><!-- /ko -->
         <!-- ko hueSpinner: { spin: loadingMore, overlay: true } --><!-- /ko -->
         <ul class="assist-tables" data-bind="foreachVisible: { data: entries, minHeight: 22, container: '.assist-adls-scrollable', fetchMore: $data.fetchMore.bind($data) }">
         <ul class="assist-tables" data-bind="foreachVisible: { data: entries, minHeight: 22, container: '.assist-adls-scrollable', fetchMore: $data.fetchMore.bind($data) }">
-          <li class="assist-entry assist-table-link" style="position: relative;" data-bind="appAwareTemplateContextMenu: { template: 'hdfs-context-items', scrollContainer: '.assist-adls-scrollable' }, visibleOnHover: { 'selector': '.assist-actions' }">
+          <li class="assist-entry assist-table-link" style="position: relative;" data-bind="appAwareTemplateContextMenu: { template: 'hdfs-context-items', scrollContainer: '.assist-adls-scrollable' }, visibleOnHover: { override: contextPopoverVisible, 'selector': '.assist-actions' }">
             <div class="assist-actions table-actions" style="opacity: 0;" >
             <div class="assist-actions table-actions" style="opacity: 0;" >
-              <a style="padding: 0 3px;" class="inactive-action" href="javascript:void(0);" data-bind="click: showContextPopover">
+              <a style="padding: 0 3px;" class="inactive-action" href="javascript:void(0);" data-bind="click: showContextPopover, css: { 'blue': contextPopoverVisible }">
                 <i class='fa fa-info' title="${ _('Details') }"></i>
                 <i class='fa fa-info' title="${ _('Details') }"></i>
               </a>
               </a>
             </div>
             </div>

+ 67 - 49
desktop/core/src/desktop/templates/ko_components/ko_context_popover.mako

@@ -372,7 +372,6 @@ from metadata.conf import has_navigator
     </div>
     </div>
   </script>
   </script>
 
 
-
   <script type="text/html" id="context-storage-entry-title">
   <script type="text/html" id="context-storage-entry-title">
     <div class="hue-popover-title">
     <div class="hue-popover-title">
       <i class="hue-popover-title-icon fa muted" data-bind="css: storageEntry() && storageEntry().definition.type === 'dir' ? 'fa-folder-o' : 'fa-file-o'"></i>
       <i class="hue-popover-title-icon fa muted" data-bind="css: storageEntry() && storageEntry().definition.type === 'dir' ? 'fa-folder-o' : 'fa-file-o'"></i>
@@ -395,58 +394,71 @@ from metadata.conf import has_navigator
 
 
   <script type="text/html" id="context-storage-entry-contents">
   <script type="text/html" id="context-storage-entry-contents">
     <div class="context-popover-content" data-bind="with: storageEntry">
     <div class="context-popover-content" data-bind="with: storageEntry">
+      <!-- ko if: !loading() && hasErrors() -->
+      <div class="context-popover-flex-fill">
+        <div class="alert" data-bind="text: errorText"></div>
+      </div>
+      <!-- /ko -->
+
       <div class="context-popover-flex-fill" data-bind="visible: loading"><!-- ko hueSpinner: { spin: loading, center: true, size: 'xlarge' } --><!-- /ko --></div>
       <div class="context-popover-flex-fill" data-bind="visible: loading"><!-- ko hueSpinner: { spin: loading, center: true, size: 'xlarge' } --><!-- /ko --></div>
-      <!-- ko ifnot: loading -->
-        <!-- ko if: hasErrors -->
-        <div class="context-popover-flex-fill">
-          <div class="alert" data-bind="text: errorText"></div>
-        </div>
-        <!-- /ko -->
-        <!-- ko ifnot: hasErrors -->
-          <div class="context-popover-flex-fill storage-entry-container" data-bind="fetchMore: { fetchMore: fetchMore.bind($data), hasMore: hasMorePages, loadingMore: loadingMore.bind($data) }">
-            <!-- ko if: definition.type === 'dir' -->
-            <table class="table table-condensed table-nowrap">
-              <thead>
-                <tr>
-                  <th width="1%"></th>
-                  <th>${ _('Name') }</th>
-                  <th>${ _('Size') }</th>
-                  <th>${ _('Permissions') }</th>
-                </tr>
-              </thead>
-              <tbody>
-                <!-- ko if: $parent.storageEntry().parent -->
-                <tr>
-                  <td><i class="fa fa-folder-o"></i></td>
-                  <td><a href="javascript: void(0);" data-bind="click: function () { $parent.storageEntry($parent.storageEntry().parent) }">..</a></td>
-                  <td data-bind="text: $parent.storageEntry().definition.humansize"></td>
-                  <td data-bind="text: $parent.storageEntry().definition.rwx"></td>
-                </tr>
-                <!-- /ko -->
-                <!-- ko foreach: entries -->
-                <tr>
-                  <td><i class="fa" data-bind="css: definition.type === 'dir' ? 'fa-folder-o' : 'fa-file-o'"></i></td>
-                  <td><a href="javascript: void(0);" data-bind="click: function () { $parents[1].storageEntry($data) }, text: definition.name"></a></td>
-                  <td data-bind="text: definition.humansize"></td>
-                  <td data-bind="text: definition.rwx"></td>
-                </tr>
-                <!-- /ko -->
-              </tbody>
-            </table>
+
+      <!-- ko if: !loading() && !hasErrors() -->
+      <!-- ko if: definition.type === 'dir' -->
+      <div class="context-popover-flex-fill storage-entry-container" data-bind="fetchMore: { fetchMore: fetchMore.bind($data), hasMore: hasMorePages, loadingMore: loadingMore.bind($data) }">
+        <table class="table table-condensed table-nowrap">
+          <thead>
+            <tr>
+              <th width="1%"></th>
+              <th>${ _('Name') }</th>
+              <th>${ _('Size') }</th>
+              <th>${ _('Permissions') }</th>
+            </tr>
+          </thead>
+          <tbody>
+            <!-- ko if: $parent.storageEntry().parent -->
+            <tr>
+              <td><i class="fa fa-folder-o"></i></td>
+              <td><a href="javascript: void(0);" data-bind="click: function () { $parent.storageEntry($parent.storageEntry().parent) }">..</a></td>
+              <td data-bind="text: $parent.storageEntry().definition.humansize"></td>
+              <td data-bind="text: $parent.storageEntry().definition.rwx"></td>
+            </tr>
             <!-- /ko -->
             <!-- /ko -->
-            <!-- ko if: definition.type !== 'dir' -->
-            <div data-bind="with: preview">
-              <!-- ko if: view && view.contents -->
-              <pre data-bind="text: view.contents"></pre>
-              <!-- /ko -->
-              <!-- ko if: view && !view.contents -->
-              <div class="empty-file-contents">${ _('Empty file...') }</div>
-              <!-- /ko -->
-            </div>
+            <!-- ko foreach: entries -->
+            <tr>
+              <td><i class="fa" data-bind="css: definition.type === 'dir' ? 'fa-folder-o' : 'fa-file-o'"></i></td>
+              <td><a href="javascript: void(0);" data-bind="click: function () { $parents[1].storageEntry($data) }, text: definition.name"></a></td>
+              <td data-bind="text: definition.humansize"></td>
+              <td data-bind="text: definition.rwx"></td>
+            </tr>
             <!-- /ko -->
             <!-- /ko -->
-          </div>
-        <!-- /ko -->
+          </tbody>
+        </table>
+      </div>
+      <!-- /ko -->
+      <!-- ko if: definition.type !== 'dir' -->
+      <div class="context-popover-flex-header"><div class="context-popover-header">${ _('Preview') }</div></div>
+      <div class="context-popover-flex-fill storage-entry-container">
+        <div data-bind="with: preview">
+          <!-- ko if: view && view.contents -->
+          <pre data-bind="text: view.contents"></pre>
+          <!-- /ko -->
+          <!-- ko if: view && !view.contents -->
+          <div class="empty-file-contents">${ _('Empty file...') }</div>
+          <!-- /ko -->
+        </div>
+      </div>
+      <!-- /ko -->
       <!-- /ko -->
       <!-- /ko -->
+
+      <div class="context-popover-flex-bottom-links">
+        <div class="context-popover-link-row">
+          <!-- ko ifnot: loading -->
+          <a class="inactive-action pointer" data-bind="click: $parent.openInFileBrowser">
+            <i style="font-size: 11px;" title="${ _("Open in File Browser...") }" class="fa fa-external-link"></i> ${ _("File Browser") }
+          </a>
+          <!-- /ko -->
+        </div>
+      </div>
     </div>
     </div>
   </script>
   </script>
 
 
@@ -756,6 +768,12 @@ from metadata.conf import has_navigator
         });
         });
       };
       };
 
 
+      StorageContext.prototype.openInFileBrowser = function (entry) {
+        huePubSub.publish('open.link', entry.definition.url);
+        huePubSub.publish('context.popover.hide');
+        huePubSub.publish('global.search.close');
+      };
+
       function FunctionContextTabs(data, sourceType) {
       function FunctionContextTabs(data, sourceType) {
         var self = this;
         var self = this;
         self.func = ko.observable({
         self.func = ko.observable({

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