浏览代码

HUE-3263 [assist] Show menu on drop of db entries (select, update, insert, delete etc.)

Johan Ahlen 9 年之前
父节点
当前提交
7c627c8

+ 92 - 10
desktop/core/src/desktop/static/desktop/js/ko.hue-bindings.js

@@ -61,7 +61,10 @@
       var $helper = $("<div>").text(ko.isObservable(options.text) ? options.text() : options.text).css("z-index", "99999");
       $element.draggable({
         helper: function () { return $helper },
-        appendTo: "body"
+        appendTo: "body",
+        start: function () {
+          huePubSub.publish('draggable.text.meta', options.meta);
+        }
       });
     }
   };
@@ -2890,6 +2893,62 @@
         }
       });
 
+      var $tableDropMenu = $el.next('.table-drop-menu');
+      var $identifierDropMenu = $tableDropMenu.find('.editor-drop-identifier')
+
+
+      var hideDropMenu = function () {
+        $tableDropMenu.css('opacity', 0);
+        window.setTimeout(function () {
+          $tableDropMenu.hide();
+        }, 300);
+      };
+
+      $(document).click(function (event) {
+        if ($tableDropMenu.find($(event.target)).length === 0) {
+          hideDropMenu();
+        };
+      });
+
+      var lastMeta = {};
+      huePubSub.subscribe('draggable.text.meta', function (meta) {
+        lastMeta = meta;
+        if (typeof meta !== 'undefined' && typeof meta.table !== 'undefined') {
+          $identifierDropMenu.text(meta.table)
+        }
+      });
+
+      var setFromDropMenu = function (text) {
+        var before = editor.getTextBeforeCursor();
+        if (before.length > 0 && before.charAt(before.length - 1) !== ' ') {
+          text = " " + text;
+        }
+        editor.session.insert(editor.getCursorPosition(), text);
+        hideDropMenu();
+        editor.focus();
+      }
+
+      $tableDropMenu.find('.editor-drop-value').click(function () {
+        setFromDropMenu(lastMeta.table);
+      });
+
+      $tableDropMenu.find('.editor-drop-select').click(function () {
+        setFromDropMenu('SELECT * FROM ' + lastMeta.table + ';');
+        $tableDropMenu.hide();
+      });
+
+      $tableDropMenu.find('.editor-drop-insert').click(function () {
+        setFromDropMenu('INSERT INTO ' + lastMeta.table + ' VALUES ();');
+      });
+
+      $tableDropMenu.find('.editor-drop-update').click(function () {
+        setFromDropMenu('UPDATE ' + lastMeta.table + ' SET ');
+      });
+
+      $tableDropMenu.find('.editor-drop-delete').click(function () {
+        setFromDropMenu('DELETE FROM ' + lastMeta.table + ' WHERE ');
+      });
+
       $el.droppable({
         accept: ".draggableText",
         drop: function (e, ui) {
@@ -2897,16 +2956,39 @@
           var text = ui.helper.text();
           editor.moveCursorToPosition(position);
           var before = editor.getTextBeforeCursor();
-          if (before.length > 0 && before.charAt(before.length - 1) !== ' ' && before.charAt(before.length - 1) !== '.') {
-            text = " " + text;
-          }
-          var after = editor.getTextAfterCursor();
-          if (after.length > 0 && after.charAt(0) !== ' ' && text.charAt(text.length - 1) !== ' ') {
-            text += " ";
+          if (/.*;|^\s*$/.test(before)) {
+            $('.table-drop-menu').show();
+
+            $tableDropMenu.css('top', 0);
+            $tableDropMenu.css('left', 0);
+            $tableDropMenu.css('opacity', 0);
+            $tableDropMenu.show();
+            var menuWidth = $tableDropMenu.outerWidth(true)
+            if (e.clientX + menuWidth > $(window).width()) {
+              $tableDropMenu.css('left', e.clientX - menuWidth);
+            } else {
+              $tableDropMenu.css('left', e.clientX);
+            }
+
+            var menuHeight = $tableDropMenu.outerHeight(true);
+            if (e.clientY + menuHeight > $(window).height()) {
+              $tableDropMenu.css('top', $(window).height() - menuHeight);
+            } else {
+              $tableDropMenu.css('top', e.clientY);
+            }
+            $tableDropMenu.css('opacity', 1);
+          } else {
+            if (before.length > 0 && before.charAt(before.length - 1) !== ' ' && before.charAt(before.length - 1) !== '.') {
+              text = " " + text;
+            }
+            var after = editor.getTextAfterCursor();
+            if (after.length > 0 && after.charAt(0) !== ' ' && text.charAt(text.length - 1) !== ' ') {
+              text += " ";
+            }
+            editor.session.insert(position, text);
+            position.column += text.length;
+            editor.clearSelection();
           }
-          editor.session.insert(position, text);
-          position.column += text.length;
-          editor.clearSelection();
         }
       });
 

+ 2 - 2
desktop/core/src/desktop/templates/assist.mako

@@ -413,7 +413,7 @@ from desktop.views import _ko
         <span data-bind="visible: navigationSettings.showStats, component: { name: 'table-stats', params: { statsVisible: statsVisible, sourceType: sourceType, snippet: assistDbSource.snippet, databaseName: databaseName, tableName: tableName, columnName: columnName, fieldType: definition.type, assistHelper: assistDbSource.assistHelper }}"></span>
         <a class="inactive-action" href="javascript:void(0)" data-bind="visible: navigationSettings.openItem, click: openItem"><i class="fa fa-long-arrow-right" title="${_('Open')}"></i></a>
       </div>
-      <a class="assist-entry assist-table-link" href="javascript:void(0)" data-bind="multiClick: { click: toggleOpen, dblClick: dblClick }, attr: {'title': definition.title }"><i class="fa fa-fw fa-table muted valign-middle"></i><span data-bind="text: definition.displayName, draggableText: { text: editorText }"></span></a>
+      <a class="assist-entry assist-table-link" href="javascript:void(0)" data-bind="multiClick: { click: toggleOpen, dblClick: dblClick }, attr: {'title': definition.title }"><i class="fa fa-fw fa-table muted valign-middle"></i><span data-bind="text: definition.displayName, draggableText: { text: editorText,  meta: {'table': tableName, 'database': databaseName} }"></span></a>
       <div class="center" data-bind="visible: loading" style="display:none;"><i class="fa fa-spinner fa-spin assist-spinner"></i></div>
       <!-- ko template: { if: open, name: 'assist-db-entries'  } --><!-- /ko -->
     </li>
@@ -434,7 +434,7 @@ from desktop.views import _ko
           <!-- ko if: definition.isView -->
             <i class="fa fa-fw fa-eye muted valign-middle"></i>
           <!-- /ko -->
-          <span data-bind="css: {'query-builder-menu': definition.isColumn}, attr: {'column': columnName, 'table': tableName, 'database': databaseName}, text: definition.displayName, draggableText: { text: editorText }"></span>
+          <span data-bind="css: {'query-builder-menu': definition.isColumn}, attr: {'column': columnName, 'table': tableName, 'database': databaseName}, text: definition.displayName, draggableText: { text: editorText, meta: {'column': columnName, 'table': tableName, 'database': databaseName} }"></span>
         </a>
         <div class="center" data-bind="visible: loading" style="display:none;"><i class="fa fa-spinner fa-spin assist-spinner"></i></div>
         <!-- ko template: { if: open, name: 'assist-db-entries'  } --><!-- /ko -->

+ 21 - 13
desktop/libs/notebook/src/notebook/templates/editor_components.mako

@@ -1330,19 +1330,27 @@ ${ hueIcons.symbols() }
   <div class="row-fluid" style="margin-bottom: 5px">
     <div class="editor span12" data-bind="css: {'single-snippet-editor ace-container-resizable' : $root.editorMode }, clickForAceFocus: ace">
       <div class="ace-editor" data-bind="css: {'single-snippet-editor ace-editor-resizable' : $root.editorMode, 'active-editor': inFocus }, attr: { id: id() }, delayedOverflow, aceEditor: {
-          snippet: $data,
-          openIt: '${ _ko("Alt or Ctrl + Click to open it") }',
-          expandStar: '${ _ko("Alt or Ctrl + Click to replace with all columns") }',
-          onBlur: saveTemporarySnippet,
-          highlightedRange: result.statement_range,
-          aceOptions: {
-            showLineNumbers: $root.editorMode,
-            showGutter: $root.editorMode,
-            maxLines: $root.editorMode ? null : 25,
-            minLines: $root.editorMode ? null : 3
-          }
-        }"></div>
-      </div>
+        snippet: $data,
+        openIt: '${ _ko("Alt or Ctrl + Click to open it") }',
+        expandStar: '${ _ko("Alt or Ctrl + Click to replace with all columns") }',
+        onBlur: saveTemporarySnippet,
+        highlightedRange: result.statement_range,
+        aceOptions: {
+          showLineNumbers: $root.editorMode,
+          showGutter: $root.editorMode,
+          maxLines: $root.editorMode ? null : 25,
+          minLines: $root.editorMode ? null : 3
+        }
+      }"></div>
+      <ul class="table-drop-menu hue-context-menu">
+        <li class="editor-drop-value"><a href="javascript:void(0);">"<span class="editor-drop-identifier"></span>"</a></li>
+        <li class="divider"></li>
+        <li class="editor-drop-select"><a href="javascript:void(0);">${ _('SELECT FROM ') } <span class="editor-drop-identifier"></span>...</a></li>
+        <li class="editor-drop-insert"><a href="javascript:void(0);">${ _('INSERT INTO') } <span class="editor-drop-identifier"></span>...</a></li>
+        <li class="editor-drop-update"><a href="javascript:void(0);">${ _('UPDATE') } <span class="editor-drop-identifier"></span>...</a></li>
+        <li class="editor-drop-delete"><a href="javascript:void(0);">${ _('DELETE FROM') } <span class="editor-drop-identifier"></span>...</a></li>
+      </ul>
+    </div>
     <div class="clearfix"></div>
     <ul data-bind="foreach: variables" class="unstyled inline">
         <li>