public inbox for [email protected]  
help / color / mirror / Atom feed
[pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree
8+ messages / 2 participants
[nested] [flat]

* [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree
@ 2019-06-26 06:23 Aditya Toshniwal <[email protected]>
  2019-06-26 11:21 ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Dave Page <[email protected]>
  0 siblings, 1 reply; 8+ messages in thread

From: Aditya Toshniwal @ 2019-06-26 06:23 UTC (permalink / raw)
  To: pgadmin-hackers

Hi Hackers,

Attached is the patch to allow tree nodes to be dragged and dropped in
query editor wherever you take the drop cursor. The drop text will be fully
qualified and double quoted if required.
For functions/procedures it will drop the the label stripping away the
parameter names, with empty pair of round brackets. It will also set the
focus cursor inside the brackets if there were params otherwiser to the end
of text.
For adding a node type, you need to register it in browser.js along with a
callback function which will return drop text along with cursor positioning
and selection. Currently, I have registered for "table partition type
sequence package view mview foreign_table edbvar schema column edbfunc
function edbproc procedure".

Please note, the drag design customisation is not supported in IE.

Kindly review.

-- 
Thanks and Regards,
Aditya Toshniwal
Software Engineer | EnterpriseDB India | Pune
"Don't Complain about Heat, Plant a TREE"


Attachments:

  [application/octet-stream] RM4139.patch (10.6K, 3-RM4139.patch)
  download | inline diff:
diff --git a/web/pgadmin/browser/static/js/browser.js b/web/pgadmin/browser/static/js/browser.js
index 29c11c2e..8c0f9a5a 100644
--- a/web/pgadmin/browser/static/js/browser.js
+++ b/web/pgadmin/browser/static/js/browser.js
@@ -12,7 +12,7 @@ define('pgadmin.browser', [
   'sources/gettext', 'sources/url_for', 'require', 'jquery', 'underscore', 'underscore.string',
   'bootstrap', 'sources/pgadmin', 'pgadmin.alertifyjs', 'bundled_codemirror',
   'sources/check_node_visibility', './toolbar', 'pgadmin.help',
-  'sources/csrf', 'pgadmin.browser.utils',
+  'sources/csrf', 'sources/utils', 'pgadmin.browser.utils',
   'wcdocker', 'jquery.contextmenu', 'jquery.aciplugin', 'jquery.acitree',
   'pgadmin.browser.preferences', 'pgadmin.browser.messages',
   'pgadmin.browser.menu', 'pgadmin.browser.panel', 'pgadmin.browser.layout',
@@ -24,7 +24,7 @@ define('pgadmin.browser', [
   tree,
   gettext, url_for, require, $, _, S,
   Bootstrap, pgAdmin, Alertify, codemirror,
-  checkNodeVisibility, toolBar, help, csrfToken
+  checkNodeVisibility, toolBar, help, csrfToken, pgadminUtils,
 ) {
   window.jQuery = window.$ = $;
   // Some scripts do export their object in the window only.
@@ -102,6 +102,38 @@ define('pgadmin.browser', [
 
       b.tree = $('#tree').aciTree('api');
       b.treeMenu.register($('#tree'));
+
+      b.treeMenu.registerDraggableType({
+        'table partition type sequence package view mview foreign_table edbvar' : (data, item)=>{
+          return pgadminUtils.fully_qualify(b, data, item);
+        },
+        'schema column' : (data)=>{
+          return pgadminUtils.quote_ident(data.label);
+        },
+        'edbfunc function edbproc procedure' : (data, item)=>{
+          let newData = {
+              ...data,
+            },
+            bracketPos = newData.label.lastIndexOf('(');
+
+          /* Strip the bracket */
+          newData.label = newData.label.substr(0, bracketPos);
+          let dropVal = pgadminUtils.fully_qualify(b, newData, item);
+          dropVal = dropVal + '()';
+
+          let curPos = dropVal.length;
+          /* If it has params */
+          if(data.label.substr(bracketPos).length > 2) {
+            curPos = curPos - 1;
+          }
+          return {
+            text: dropVal,
+            cur: {
+              from: curPos, to: curPos,
+            },
+          };
+        },
+      });
     };
 
   // Extend the browser class attributes
diff --git a/web/pgadmin/static/js/tree/tree.js b/web/pgadmin/static/js/tree/tree.js
index 782f4d59..99397ef4 100644
--- a/web/pgadmin/static/js/tree/tree.js
+++ b/web/pgadmin/static/js/tree/tree.js
@@ -8,6 +8,7 @@
 //////////////////////////////////////////////////////////////////////////
 
 import {isValidData} from 'sources/utils';
+import $ from 'jquery';
 
 export class TreeNode {
   constructor(id, data, domNode, parent) {
@@ -97,6 +98,87 @@ export class Tree {
   constructor() {
     this.rootNode = new TreeNode(undefined, {});
     this.aciTreeApi = undefined;
+    this.draggableTypes = {};
+  }
+
+  /*
+   *
+   * The dropDetailsFunc should return an object of sample
+   * {text: 'xyz', cur: {from:0, to:0} where text is the drop text and
+   * cur is selection range of text after dropping. If returned as
+   * string, by default cursor will be set to the end of text
+   */
+  registerDraggableType(typeOrTypeDict, dropDetailsFunc=null) {
+    if(typeof typeOrTypeDict == 'object') {
+      Object.keys(typeOrTypeDict).forEach((type)=>{
+        this.registerDraggableType(type, typeOrTypeDict[type]);
+      });
+    } else {
+      if(dropDetailsFunc != null) {
+        typeOrTypeDict.replace(/ +/, ' ').split(' ').forEach((type)=>{
+          this.draggableTypes[type] = dropDetailsFunc;
+        });
+      }
+    }
+  }
+
+  getDraggable(type) {
+    if(this.draggableTypes[type]) {
+      return this.draggableTypes[type];
+    } else {
+      return null;
+    }
+  }
+
+  prepareDraggable(data, item) {
+    let dropDetailsFunc = this.getDraggable(data._type);
+
+    if(dropDetailsFunc != null) {
+      item.find('.aciTreeItem')
+        .attr('draggable', true)
+        .on('dragstart', (e)=> {
+          let dropDetails = dropDetailsFunc(data, item);
+          let origEvent = e.originalEvent;
+
+          if(typeof dropDetails == 'string') {
+            dropDetails = {
+              text:dropDetails,
+              cur:{
+                from:dropDetails.length,
+                to: dropDetails.length,
+              },
+            };
+          } else {
+            if(!dropDetails.cur) {
+              dropDetails = {
+                ...dropDetails,
+                cur:{
+                  from:dropDetails.text.length,
+                  to: dropDetails.text.length,
+                },
+              };
+            }
+          }
+
+          origEvent.dataTransfer.setData('text', JSON.stringify(dropDetails));
+
+          /* setDragImage is not supported in IE. We leave it to
+           * its default look and feel
+           */
+          if(origEvent.dataTransfer.setDragImage) {
+            let dragItem = $(`
+              <div class="drag-tree-node">
+                <span>${dropDetails.text}</span>
+              </div>`
+            );
+
+            $('body .drag-tree-node').remove();
+            $('body').append(dragItem);
+
+            origEvent.dataTransfer.setDragImage(dragItem[0], 0, 0);
+          }
+        });
+    }
   }
 
   addNewNode(id, data, domNode, parentPath) {
@@ -163,6 +245,9 @@ export class Tree {
         if (eventName === 'added') {
           const id = api.getId(item);
           const data = api.itemData(item);
+
+          this.prepareDraggable(data, item);
+
           const parentId = this.translateTreeNodeIdFromACITree(api.parent(item));
           this.addNewNode(id, data, item, parentId);
         }
diff --git a/web/pgadmin/static/js/utils.js b/web/pgadmin/static/js/utils.js
index 1c58a9eb..5c908afb 100644
--- a/web/pgadmin/static/js/utils.js
+++ b/web/pgadmin/static/js/utils.js
@@ -8,6 +8,7 @@
 //////////////////////////////////////////////////////////////////////////
 
 import _ from 'underscore';
+import { getTreeNodeHierarchyFromIdentifier } from 'sources/tree/pgadmin_tree_node';
 
 export function parseShortcutValue(obj) {
   var shortcut = '';
@@ -83,3 +84,50 @@ export function getGCD(inp_arr) {
 export function getMod(no, divisor) {
   return ((no % divisor) + divisor) % divisor;
 }
+
+export function quote_ident(value) {
+  /* check if the string is number or not */
+  let quoteIt = false;
+  if (!isNaN(parseInt(value))){
+    quoteIt = true;
+  }
+
+  if(value.search(/[^a-z0-9_]/g) > -1) {
+    quoteIt = true;
+  }
+
+  if(quoteIt) {
+    return `"${value}"`;
+  } else {
+    return value;
+  }
+}
+
+export function fully_qualify(pgBrowser, data, item) {
+  const parentData = getTreeNodeHierarchyFromIdentifier.call(pgBrowser, item);
+  let namespace = '';
+
+  if (parentData.schema !== undefined) {
+    namespace = quote_ident(parentData.schema.label);
+  }
+  else if (parentData.view !== undefined) {
+    namespace = quote_ident(parentData.view.label);
+  }
+  else if (parentData.catalog !== undefined) {
+    namespace = quote_ident(parentData.catalog.label);
+  }
+
+  if (parentData.package !== undefined && data._type != 'package') {
+    if(namespace == '') {
+      namespace = quote_ident(parentData.package.label);
+    } else {
+      namespace += '.' + quote_ident(parentData.package.label);
+    }
+  }
+
+  if(namespace != '') {
+    return namespace + '.' + quote_ident(data.label);
+  } else {
+    return quote_ident(data.label);
+  }
+}
diff --git a/web/pgadmin/static/scss/_pgadmin.style.scss b/web/pgadmin/static/scss/_pgadmin.style.scss
index ed426545..f5a8877c 100644
--- a/web/pgadmin/static/scss/_pgadmin.style.scss
+++ b/web/pgadmin/static/scss/_pgadmin.style.scss
@@ -983,3 +983,15 @@ table.table-empty-rows{
   padding: 0px !important;
   position: absolute;
 }
+
+.drag-tree-node {
+  position: absolute;
+  top:-100px;
+  left:0;
+  z-index: 99999;
+  color: $input-focus-color;
+  background: $input-bg;
+  border: $input-border-width solid $input-focus-border-color;
+  border-radius: $input-border-radius;
+  padding: $input-btn-padding-y $input-btn-padding-x;
+}
diff --git a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
index a8560574..ef468f63 100644
--- a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
+++ b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
@@ -341,8 +341,31 @@ define('tools.querytool', [
         gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
         extraKeys: pgBrowser.editor_shortcut_keys,
         scrollbarStyle: 'simple',
+        dragDrop: false,
       });
 
+      if(self.handler.is_query_tool) {
+        self.query_tool_obj.setOption('dragDrop', true);
+        self.query_tool_obj.on('drop', (editor, e) => {
+          var cursor = editor.coordsChar({
+            left: e.x,
+            top: e.y,
+          });
+          var dropDetails = JSON.parse(e.dataTransfer.getData('text'));
+          e.codemirrorIgnore = true;
+          e.dataTransfer.clearData('text');
+          editor.replaceRange(dropDetails.text, cursor);
+          editor.focus();
+          editor.setSelection({
+            ...cursor,
+            ch: cursor.ch + dropDetails.cur.from,
+          },{
+            ...cursor,
+            ch: cursor.ch +dropDetails.cur.to,
+          });
+        });
+      }
+
       pgBrowser.Events.on('pgadmin:query_tool:sql_panel:focus', ()=>{
         self.query_tool_obj.focus();
       });
diff --git a/web/regression/javascript/pgadmin_utils_spec.js b/web/regression/javascript/pgadmin_utils_spec.js
index 02bd5478..7df78d29 100644
--- a/web/regression/javascript/pgadmin_utils_spec.js
+++ b/web/regression/javascript/pgadmin_utils_spec.js
@@ -7,7 +7,7 @@
 //
 //////////////////////////////////////////////////////////////
 
-import { getEpoch, getGCD, getMod } from 'sources/utils';
+import { getEpoch, getGCD, getMod, quote_ident } from 'sources/utils';
 
 describe('getEpoch', function () {
   it('should return non zero', function () {
@@ -51,3 +51,20 @@ describe('getMod', function () {
     expect(getMod(-7,5)).toEqual(3);
   });
 });
+
+describe('quote_ident', function () {
+  it('normal string', function () {
+    expect(quote_ident('abcd')).toEqual('abcd');
+  });
+
+  it('contains certain characters string', function () {
+    expect(quote_ident('Abcd')).toEqual('"Abcd"');
+    expect(quote_ident('abc$d')).toEqual('"abc$d"');
+    expect(quote_ident('ab cd')).toEqual('"ab cd"');
+  });
+
+  it('starts with number', function () {
+    expect(quote_ident('1a')).toEqual('"1a"');
+    expect(quote_ident('a1')).toEqual('a1');
+  });
+});


^ permalink  raw  reply  [nested|flat] 8+ messages in thread

* Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree
  2019-06-26 06:23 [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Aditya Toshniwal <[email protected]>
@ 2019-06-26 11:21 ` Dave Page <[email protected]>
  2019-06-26 11:28   ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Aditya Toshniwal <[email protected]>
  0 siblings, 1 reply; 8+ messages in thread

From: Dave Page @ 2019-06-26 11:21 UTC (permalink / raw)
  To: Aditya Toshniwal <[email protected]>; +Cc: pgadmin-hackers

Hi

On Wed, Jun 26, 2019 at 2:24 AM Aditya Toshniwal <
[email protected]> wrote:

> Hi Hackers,
>
> Attached is the patch to allow tree nodes to be dragged and dropped in
> query editor wherever you take the drop cursor. The drop text will be fully
> qualified and double quoted if required.
> For functions/procedures it will drop the the label stripping away the
> parameter names, with empty pair of round brackets. It will also set the
> focus cursor inside the brackets if there were params otherwiser to the end
> of text.
> For adding a node type, you need to register it in browser.js along with a
> callback function which will return drop text along with cursor positioning
> and selection. Currently, I have registered for "table partition type
> sequence package view mview foreign_table edbvar schema column edbfunc
> function edbproc procedure".
>
> Please note, the drag design customisation is not supported in IE.
>

I think for functions/procedures, we should include placeholders for the
parameters, so the user has a hint about what they need to fill in to
complete the call.

Also; shouldn't there be a doc update?

Thanks.

-- 
Dave Page
Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake

EnterpriseDB UK: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


^ permalink  raw  reply  [nested|flat] 8+ messages in thread

* Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree
  2019-06-26 06:23 [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Aditya Toshniwal <[email protected]>
  2019-06-26 11:21 ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Dave Page <[email protected]>
@ 2019-06-26 11:28   ` Aditya Toshniwal <[email protected]>
  2019-06-26 11:36     ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Dave Page <[email protected]>
  0 siblings, 1 reply; 8+ messages in thread

From: Aditya Toshniwal @ 2019-06-26 11:28 UTC (permalink / raw)
  To: Dave Page <[email protected]>; +Cc: pgadmin-hackers

Hi,

On Wed, Jun 26, 2019 at 4:51 PM Dave Page <[email protected]> wrote:

> Hi
>
> On Wed, Jun 26, 2019 at 2:24 AM Aditya Toshniwal <
> [email protected]> wrote:
>
>> Hi Hackers,
>>
>> Attached is the patch to allow tree nodes to be dragged and dropped in
>> query editor wherever you take the drop cursor. The drop text will be fully
>> qualified and double quoted if required.
>> For functions/procedures it will drop the the label stripping away the
>> parameter names, with empty pair of round brackets. It will also set the
>> focus cursor inside the brackets if there were params otherwiser to the end
>> of text.
>> For adding a node type, you need to register it in browser.js along with
>> a callback function which will return drop text along with cursor
>> positioning and selection. Currently, I have registered for "table
>> partition type sequence package view mview foreign_table edbvar schema
>> column edbfunc function edbproc procedure".
>>
>> Please note, the drag design customisation is not supported in IE.
>>
>
> I think for functions/procedures, we should include placeholders for the
> parameters, so the user has a hint about what they need to fill in to
> complete the call.
>
I can fill in the parameter names same as tree node, with cursor selection
on all the params ?

>
> Also; shouldn't there be a doc update?
>
Yeah :/
Should there be any screenshots ?

>
> Thanks.
>
> --
> Dave Page
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>
> EnterpriseDB UK: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>


-- 
Thanks and Regards,
Aditya Toshniwal
Software Engineer | EnterpriseDB India | Pune
"Don't Complain about Heat, Plant a TREE"


^ permalink  raw  reply  [nested|flat] 8+ messages in thread

* Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree
  2019-06-26 06:23 [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Aditya Toshniwal <[email protected]>
  2019-06-26 11:21 ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Dave Page <[email protected]>
  2019-06-26 11:28   ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Aditya Toshniwal <[email protected]>
@ 2019-06-26 11:36     ` Dave Page <[email protected]>
  2019-06-26 11:38       ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Aditya Toshniwal <[email protected]>
  0 siblings, 1 reply; 8+ messages in thread

From: Dave Page @ 2019-06-26 11:36 UTC (permalink / raw)
  To: Aditya Toshniwal <[email protected]>; +Cc: pgadmin-hackers

On Wed, Jun 26, 2019 at 7:28 AM Aditya Toshniwal <
[email protected]> wrote:

> Hi,
>
> On Wed, Jun 26, 2019 at 4:51 PM Dave Page <[email protected]> wrote:
>
>> Hi
>>
>> On Wed, Jun 26, 2019 at 2:24 AM Aditya Toshniwal <
>> [email protected]> wrote:
>>
>>> Hi Hackers,
>>>
>>> Attached is the patch to allow tree nodes to be dragged and dropped in
>>> query editor wherever you take the drop cursor. The drop text will be fully
>>> qualified and double quoted if required.
>>> For functions/procedures it will drop the the label stripping away the
>>> parameter names, with empty pair of round brackets. It will also set the
>>> focus cursor inside the brackets if there were params otherwiser to the end
>>> of text.
>>> For adding a node type, you need to register it in browser.js along with
>>> a callback function which will return drop text along with cursor
>>> positioning and selection. Currently, I have registered for "table
>>> partition type sequence package view mview foreign_table edbvar schema
>>> column edbfunc function edbproc procedure".
>>>
>>> Please note, the drag design customisation is not supported in IE.
>>>
>>
>> I think for functions/procedures, we should include placeholders for the
>> parameters, so the user has a hint about what they need to fill in to
>> complete the call.
>>
> I can fill in the parameter names same as tree node, with cursor selection
> on all the params ?
>

Can you select the first one, and put the cursor in front of it?


>
>> Also; shouldn't there be a doc update?
>>
> Yeah :/
> Should there be any screenshots ?
>

I don't see much need.

Thanks.


>
>> Thanks.
>>
>> --
>> Dave Page
>> Blog: http://pgsnake.blogspot.com
>> Twitter: @pgsnake
>>
>> EnterpriseDB UK: http://www.enterprisedb.com
>> The Enterprise PostgreSQL Company
>>
>
>
> --
> Thanks and Regards,
> Aditya Toshniwal
> Software Engineer | EnterpriseDB India | Pune
> "Don't Complain about Heat, Plant a TREE"
>


-- 
Dave Page
Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake

EnterpriseDB UK: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


^ permalink  raw  reply  [nested|flat] 8+ messages in thread

* Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree
  2019-06-26 06:23 [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Aditya Toshniwal <[email protected]>
  2019-06-26 11:21 ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Dave Page <[email protected]>
  2019-06-26 11:28   ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Aditya Toshniwal <[email protected]>
  2019-06-26 11:36     ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Dave Page <[email protected]>
@ 2019-06-26 11:38       ` Aditya Toshniwal <[email protected]>
  2019-06-26 11:39         ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Dave Page <[email protected]>
  0 siblings, 1 reply; 8+ messages in thread

From: Aditya Toshniwal @ 2019-06-26 11:38 UTC (permalink / raw)
  To: Dave Page <[email protected]>; +Cc: pgadmin-hackers

Hi,

On Wed, Jun 26, 2019 at 5:06 PM Dave Page <[email protected]> wrote:

>
>
> On Wed, Jun 26, 2019 at 7:28 AM Aditya Toshniwal <
> [email protected]> wrote:
>
>> Hi,
>>
>> On Wed, Jun 26, 2019 at 4:51 PM Dave Page <[email protected]> wrote:
>>
>>> Hi
>>>
>>> On Wed, Jun 26, 2019 at 2:24 AM Aditya Toshniwal <
>>> [email protected]> wrote:
>>>
>>>> Hi Hackers,
>>>>
>>>> Attached is the patch to allow tree nodes to be dragged and dropped in
>>>> query editor wherever you take the drop cursor. The drop text will be fully
>>>> qualified and double quoted if required.
>>>> For functions/procedures it will drop the the label stripping away the
>>>> parameter names, with empty pair of round brackets. It will also set the
>>>> focus cursor inside the brackets if there were params otherwiser to the end
>>>> of text.
>>>> For adding a node type, you need to register it in browser.js along
>>>> with a callback function which will return drop text along with cursor
>>>> positioning and selection. Currently, I have registered for "table
>>>> partition type sequence package view mview foreign_table edbvar schema
>>>> column edbfunc function edbproc procedure".
>>>>
>>>> Please note, the drag design customisation is not supported in IE.
>>>>
>>>
>>> I think for functions/procedures, we should include placeholders for the
>>> parameters, so the user has a hint about what they need to fill in to
>>> complete the call.
>>>
>> I can fill in the parameter names same as tree node, with cursor
>> selection on all the params ?
>>
>
> Can you select the first one, and put the cursor in front of it?
>
Yes. Will do that. So that, just after drop if the user types anything it
will replace the first param name.

>
>
>>
>>> Also; shouldn't there be a doc update?
>>>
>> Yeah :/
>> Should there be any screenshots ?
>>
>
> I don't see much need.
>
Cool.

>
> Thanks.
>
>
>>
>>> Thanks.
>>>
>>> --
>>> Dave Page
>>> Blog: http://pgsnake.blogspot.com
>>> Twitter: @pgsnake
>>>
>>> EnterpriseDB UK: http://www.enterprisedb.com
>>> The Enterprise PostgreSQL Company
>>>
>>
>>
>> --
>> Thanks and Regards,
>> Aditya Toshniwal
>> Software Engineer | EnterpriseDB India | Pune
>> "Don't Complain about Heat, Plant a TREE"
>>
>
>
> --
> Dave Page
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>
> EnterpriseDB UK: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>


-- 
Thanks and Regards,
Aditya Toshniwal
Software Engineer | EnterpriseDB India | Pune
"Don't Complain about Heat, Plant a TREE"


^ permalink  raw  reply  [nested|flat] 8+ messages in thread

* Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree
  2019-06-26 06:23 [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Aditya Toshniwal <[email protected]>
  2019-06-26 11:21 ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Dave Page <[email protected]>
  2019-06-26 11:28   ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Aditya Toshniwal <[email protected]>
  2019-06-26 11:36     ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Dave Page <[email protected]>
  2019-06-26 11:38       ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Aditya Toshniwal <[email protected]>
@ 2019-06-26 11:39         ` Dave Page <[email protected]>
  2019-06-27 10:31           ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Aditya Toshniwal <[email protected]>
  0 siblings, 1 reply; 8+ messages in thread

From: Dave Page @ 2019-06-26 11:39 UTC (permalink / raw)
  To: Aditya Toshniwal <[email protected]>; +Cc: pgadmin-hackers

On Wed, Jun 26, 2019 at 7:38 AM Aditya Toshniwal <
[email protected]> wrote:

> Hi,
>
> On Wed, Jun 26, 2019 at 5:06 PM Dave Page <[email protected]> wrote:
>
>>
>>
>> On Wed, Jun 26, 2019 at 7:28 AM Aditya Toshniwal <
>> [email protected]> wrote:
>>
>>> Hi,
>>>
>>> On Wed, Jun 26, 2019 at 4:51 PM Dave Page <[email protected]> wrote:
>>>
>>>> Hi
>>>>
>>>> On Wed, Jun 26, 2019 at 2:24 AM Aditya Toshniwal <
>>>> [email protected]> wrote:
>>>>
>>>>> Hi Hackers,
>>>>>
>>>>> Attached is the patch to allow tree nodes to be dragged and dropped in
>>>>> query editor wherever you take the drop cursor. The drop text will be fully
>>>>> qualified and double quoted if required.
>>>>> For functions/procedures it will drop the the label stripping away the
>>>>> parameter names, with empty pair of round brackets. It will also set the
>>>>> focus cursor inside the brackets if there were params otherwiser to the end
>>>>> of text.
>>>>> For adding a node type, you need to register it in browser.js along
>>>>> with a callback function which will return drop text along with cursor
>>>>> positioning and selection. Currently, I have registered for "table
>>>>> partition type sequence package view mview foreign_table edbvar schema
>>>>> column edbfunc function edbproc procedure".
>>>>>
>>>>> Please note, the drag design customisation is not supported in IE.
>>>>>
>>>>
>>>> I think for functions/procedures, we should include placeholders for
>>>> the parameters, so the user has a hint about what they need to fill in to
>>>> complete the call.
>>>>
>>> I can fill in the parameter names same as tree node, with cursor
>>> selection on all the params ?
>>>
>>
>> Can you select the first one, and put the cursor in front of it?
>>
> Yes. Will do that. So that, just after drop if the user types anything it
> will replace the first param name.
>

Right.


>
>>
>>>
>>>> Also; shouldn't there be a doc update?
>>>>
>>> Yeah :/
>>> Should there be any screenshots ?
>>>
>>
>> I don't see much need.
>>
> Cool.
>

:-)


>
>> Thanks.
>>
>>
>>>
>>>> Thanks.
>>>>
>>>> --
>>>> Dave Page
>>>> Blog: http://pgsnake.blogspot.com
>>>> Twitter: @pgsnake
>>>>
>>>> EnterpriseDB UK: http://www.enterprisedb.com
>>>> The Enterprise PostgreSQL Company
>>>>
>>>
>>>
>>> --
>>> Thanks and Regards,
>>> Aditya Toshniwal
>>> Software Engineer | EnterpriseDB India | Pune
>>> "Don't Complain about Heat, Plant a TREE"
>>>
>>
>>
>> --
>> Dave Page
>> Blog: http://pgsnake.blogspot.com
>> Twitter: @pgsnake
>>
>> EnterpriseDB UK: http://www.enterprisedb.com
>> The Enterprise PostgreSQL Company
>>
>
>
> --
> Thanks and Regards,
> Aditya Toshniwal
> Software Engineer | EnterpriseDB India | Pune
> "Don't Complain about Heat, Plant a TREE"
>


-- 
Dave Page
Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake

EnterpriseDB UK: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


^ permalink  raw  reply  [nested|flat] 8+ messages in thread

* Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree
  2019-06-26 06:23 [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Aditya Toshniwal <[email protected]>
  2019-06-26 11:21 ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Dave Page <[email protected]>
  2019-06-26 11:28   ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Aditya Toshniwal <[email protected]>
  2019-06-26 11:36     ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Dave Page <[email protected]>
  2019-06-26 11:38       ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Aditya Toshniwal <[email protected]>
  2019-06-26 11:39         ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Dave Page <[email protected]>
@ 2019-06-27 10:31           ` Aditya Toshniwal <[email protected]>
  2019-06-27 14:30             ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Dave Page <[email protected]>
  0 siblings, 1 reply; 8+ messages in thread

From: Aditya Toshniwal @ 2019-06-27 10:31 UTC (permalink / raw)
  To: Dave Page <[email protected]>; +Cc: pgadmin-hackers

Hi Hackers,

Attached is the updated patch based on the review comments in trailing mail.
Kindly review.

On Wed, Jun 26, 2019 at 5:09 PM Dave Page <[email protected]> wrote:

>
>
> On Wed, Jun 26, 2019 at 7:38 AM Aditya Toshniwal <
> [email protected]> wrote:
>
>> Hi,
>>
>> On Wed, Jun 26, 2019 at 5:06 PM Dave Page <[email protected]> wrote:
>>
>>>
>>>
>>> On Wed, Jun 26, 2019 at 7:28 AM Aditya Toshniwal <
>>> [email protected]> wrote:
>>>
>>>> Hi,
>>>>
>>>> On Wed, Jun 26, 2019 at 4:51 PM Dave Page <[email protected]> wrote:
>>>>
>>>>> Hi
>>>>>
>>>>> On Wed, Jun 26, 2019 at 2:24 AM Aditya Toshniwal <
>>>>> [email protected]> wrote:
>>>>>
>>>>>> Hi Hackers,
>>>>>>
>>>>>> Attached is the patch to allow tree nodes to be dragged and dropped
>>>>>> in query editor wherever you take the drop cursor. The drop text will be
>>>>>> fully qualified and double quoted if required.
>>>>>> For functions/procedures it will drop the the label stripping away
>>>>>> the parameter names, with empty pair of round brackets. It will also set
>>>>>> the focus cursor inside the brackets if there were params otherwiser to the
>>>>>> end of text.
>>>>>> For adding a node type, you need to register it in browser.js along
>>>>>> with a callback function which will return drop text along with cursor
>>>>>> positioning and selection. Currently, I have registered for "table
>>>>>> partition type sequence package view mview foreign_table edbvar schema
>>>>>> column edbfunc function edbproc procedure".
>>>>>>
>>>>>> Please note, the drag design customisation is not supported in IE.
>>>>>>
>>>>>
>>>>> I think for functions/procedures, we should include placeholders for
>>>>> the parameters, so the user has a hint about what they need to fill in to
>>>>> complete the call.
>>>>>
>>>> I can fill in the parameter names same as tree node, with cursor
>>>> selection on all the params ?
>>>>
>>>
>>> Can you select the first one, and put the cursor in front of it?
>>>
>> Yes. Will do that. So that, just after drop if the user types anything it
>> will replace the first param name.
>>
>
> Right.
>
>
>>
>>>
>>>>
>>>>> Also; shouldn't there be a doc update?
>>>>>
>>>> Yeah :/
>>>> Should there be any screenshots ?
>>>>
>>>
>>> I don't see much need.
>>>
>> Cool.
>>
>
> :-)
>
>
>>
>>> Thanks.
>>>
>>>
>>>>
>>>>> Thanks.
>>>>>
>>>>> --
>>>>> Dave Page
>>>>> Blog: http://pgsnake.blogspot.com
>>>>> Twitter: @pgsnake
>>>>>
>>>>> EnterpriseDB UK: http://www.enterprisedb.com
>>>>> The Enterprise PostgreSQL Company
>>>>>
>>>>
>>>>
>>>> --
>>>> Thanks and Regards,
>>>> Aditya Toshniwal
>>>> Software Engineer | EnterpriseDB India | Pune
>>>> "Don't Complain about Heat, Plant a TREE"
>>>>
>>>
>>>
>>> --
>>> Dave Page
>>> Blog: http://pgsnake.blogspot.com
>>> Twitter: @pgsnake
>>>
>>> EnterpriseDB UK: http://www.enterprisedb.com
>>> The Enterprise PostgreSQL Company
>>>
>>
>>
>> --
>> Thanks and Regards,
>> Aditya Toshniwal
>> Software Engineer | EnterpriseDB India | Pune
>> "Don't Complain about Heat, Plant a TREE"
>>
>
>
> --
> Dave Page
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>
> EnterpriseDB UK: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>


-- 
Thanks and Regards,
Aditya Toshniwal
Software Engineer | EnterpriseDB India | Pune
"Don't Complain about Heat, Plant a TREE"


Attachments:

  [application/octet-stream] RM4139_v2.patch (15.4K, 3-RM4139_v2.patch)
  download | inline diff:
diff --git a/docs/en_US/tree_control.rst b/docs/en_US/tree_control.rst
index 73eb114f..03d4f1ca 100644
--- a/docs/en_US/tree_control.rst
+++ b/docs/en_US/tree_control.rst
@@ -19,6 +19,12 @@ view:
   control.
 * Click the minus sign (-) to the left of a node to close that node.
 
+You can also **drag and drop** certain object names to the query tool which
+is very helpful to save time in typing long object names. The text on drop will be
+fully qualified with schema name. Double quotes will be added to the text if required.
+For functions and procedures, the function name along with parameter names will
+be pasted in the query tool.
+
 Access context-sensitive menus by right-clicking on a node of the tree control
 to perform common tasks. Menus display options that include one or more of the
 following selections (options appear in alphabetical order):
diff --git a/web/pgadmin/browser/static/js/browser.js b/web/pgadmin/browser/static/js/browser.js
index 29c11c2e..38252887 100644
--- a/web/pgadmin/browser/static/js/browser.js
+++ b/web/pgadmin/browser/static/js/browser.js
@@ -12,7 +12,7 @@ define('pgadmin.browser', [
   'sources/gettext', 'sources/url_for', 'require', 'jquery', 'underscore', 'underscore.string',
   'bootstrap', 'sources/pgadmin', 'pgadmin.alertifyjs', 'bundled_codemirror',
   'sources/check_node_visibility', './toolbar', 'pgadmin.help',
-  'sources/csrf', 'pgadmin.browser.utils',
+  'sources/csrf', 'sources/utils', 'pgadmin.browser.utils',
   'wcdocker', 'jquery.contextmenu', 'jquery.aciplugin', 'jquery.acitree',
   'pgadmin.browser.preferences', 'pgadmin.browser.messages',
   'pgadmin.browser.menu', 'pgadmin.browser.panel', 'pgadmin.browser.layout',
@@ -24,7 +24,7 @@ define('pgadmin.browser', [
   tree,
   gettext, url_for, require, $, _, S,
   Bootstrap, pgAdmin, Alertify, codemirror,
-  checkNodeVisibility, toolBar, help, csrfToken
+  checkNodeVisibility, toolBar, help, csrfToken, pgadminUtils,
 ) {
   window.jQuery = window.$ = $;
   // Some scripts do export their object in the window only.
@@ -102,6 +102,46 @@ define('pgadmin.browser', [
 
       b.tree = $('#tree').aciTree('api');
       b.treeMenu.register($('#tree'));
+
+      b.treeMenu.registerDraggableType({
+        'table partition type sequence package view mview foreign_table edbvar' : (data, item)=>{
+          return pgadminUtils.fully_qualify(b, data, item);
+        },
+        'schema column' : (data)=>{
+          return pgadminUtils.quote_ident(data._label);
+        },
+        'edbfunc function edbproc procedure' : (data, item)=>{
+          let newData = {...data},
+            parsedFunc = null,
+            dropVal = '',
+            curPos = {from: 0, to: 0};
+
+          parsedFunc = pgadminUtils.parseFuncParams(newData._label);
+          newData._label = parsedFunc.func_name;
+          dropVal = pgadminUtils.fully_qualify(b, newData, item);
+
+          if(parsedFunc.params.length > 0) {
+            dropVal = dropVal + '(';
+            curPos.from =  dropVal.length;
+            dropVal = dropVal + parsedFunc.params[0][0];
+            curPos.to = dropVal.length;
+
+            for(let i=1; i<parsedFunc.params.length; i++) {
+              dropVal = dropVal + ', ' + parsedFunc.params[i][0];
+            }
+
+            dropVal = dropVal + ')';
+          } else {
+            dropVal = dropVal + '()';
+            curPos.from = curPos.to = dropVal.length + 1;
+          }
+
+          return {
+            text: dropVal,
+            cur: curPos,
+          };
+        },
+      });
     };
 
   // Extend the browser class attributes
diff --git a/web/pgadmin/static/js/tree/tree.js b/web/pgadmin/static/js/tree/tree.js
index 782f4d59..99397ef4 100644
--- a/web/pgadmin/static/js/tree/tree.js
+++ b/web/pgadmin/static/js/tree/tree.js
@@ -8,6 +8,7 @@
 //////////////////////////////////////////////////////////////////////////
 
 import {isValidData} from 'sources/utils';
+import $ from 'jquery';
 
 export class TreeNode {
   constructor(id, data, domNode, parent) {
@@ -97,6 +98,87 @@ export class Tree {
   constructor() {
     this.rootNode = new TreeNode(undefined, {});
     this.aciTreeApi = undefined;
+    this.draggableTypes = {};
+  }
+
+  /*
+   *
+   * The dropDetailsFunc should return an object of sample
+   * {text: 'xyz', cur: {from:0, to:0} where text is the drop text and
+   * cur is selection range of text after dropping. If returned as
+   * string, by default cursor will be set to the end of text
+   */
+  registerDraggableType(typeOrTypeDict, dropDetailsFunc=null) {
+    if(typeof typeOrTypeDict == 'object') {
+      Object.keys(typeOrTypeDict).forEach((type)=>{
+        this.registerDraggableType(type, typeOrTypeDict[type]);
+      });
+    } else {
+      if(dropDetailsFunc != null) {
+        typeOrTypeDict.replace(/ +/, ' ').split(' ').forEach((type)=>{
+          this.draggableTypes[type] = dropDetailsFunc;
+        });
+      }
+    }
+  }
+
+  getDraggable(type) {
+    if(this.draggableTypes[type]) {
+      return this.draggableTypes[type];
+    } else {
+      return null;
+    }
+  }
+
+  prepareDraggable(data, item) {
+    let dropDetailsFunc = this.getDraggable(data._type);
+
+    if(dropDetailsFunc != null) {
+      item.find('.aciTreeItem')
+        .attr('draggable', true)
+        .on('dragstart', (e)=> {
+          let dropDetails = dropDetailsFunc(data, item);
+          let origEvent = e.originalEvent;
+
+          if(typeof dropDetails == 'string') {
+            dropDetails = {
+              text:dropDetails,
+              cur:{
+                from:dropDetails.length,
+                to: dropDetails.length,
+              },
+            };
+          } else {
+            if(!dropDetails.cur) {
+              dropDetails = {
+                ...dropDetails,
+                cur:{
+                  from:dropDetails.text.length,
+                  to: dropDetails.text.length,
+                },
+              };
+            }
+          }
+
+          origEvent.dataTransfer.setData('text', JSON.stringify(dropDetails));
+
+          /* setDragImage is not supported in IE. We leave it to
+           * its default look and feel
+           */
+          if(origEvent.dataTransfer.setDragImage) {
+            let dragItem = $(`
+              <div class="drag-tree-node">
+                <span>${dropDetails.text}</span>
+              </div>`
+            );
+
+            $('body .drag-tree-node').remove();
+            $('body').append(dragItem);
+
+            origEvent.dataTransfer.setDragImage(dragItem[0], 0, 0);
+          }
+        });
+    }
   }
 
   addNewNode(id, data, domNode, parentPath) {
@@ -163,6 +245,9 @@ export class Tree {
         if (eventName === 'added') {
           const id = api.getId(item);
           const data = api.itemData(item);
+
+          this.prepareDraggable(data, item);
+
           const parentId = this.translateTreeNodeIdFromACITree(api.parent(item));
           this.addNewNode(id, data, item, parentId);
         }
diff --git a/web/pgadmin/static/js/utils.js b/web/pgadmin/static/js/utils.js
index 1c58a9eb..fe9fd8ed 100644
--- a/web/pgadmin/static/js/utils.js
+++ b/web/pgadmin/static/js/utils.js
@@ -8,6 +8,7 @@
 //////////////////////////////////////////////////////////////////////////
 
 import _ from 'underscore';
+import { getTreeNodeHierarchyFromIdentifier } from 'sources/tree/pgadmin_tree_node';
 
 export function parseShortcutValue(obj) {
   var shortcut = '';
@@ -83,3 +84,118 @@ export function getGCD(inp_arr) {
 export function getMod(no, divisor) {
   return ((no % divisor) + divisor) % divisor;
 }
+
+export function parseFuncParams(label) {
+  let paramArr = [],
+    funcName = '',
+    paramStr = '';
+
+  if(label.endsWith('()')) {
+    funcName = label.substring(0, label.length-2);
+  } else if(!label.endsWith(')')) {
+    funcName = label;
+  } else if(!label.endsWith('()') && label.endsWith(')')) {
+    let i = 0,
+      startBracketPos = label.length;
+
+    /* Parse through the characters in reverse to find the param start bracket */
+    i = label.length-2;
+    while(i >= 0) {
+      if(label[i] == '(') {
+        startBracketPos = i;
+        break;
+      } else if(label[i] == '"') {
+        /* If quotes, skip all the chars till next quote */
+        i--;
+        while(label[i] != '"') i--;
+      }
+      i--;
+    }
+
+    funcName = label.substring(0, startBracketPos);
+    paramStr = label.substring(startBracketPos+1, label.length-1);
+
+    let paramStart = 0,
+      paramName = '',
+      paramModes = ['IN', 'OUT', 'INOUT', 'VARIADIC'];
+
+    paramStart = i = 0;
+    while(i < paramStr.length) {
+      if(paramStr[i] == '"') {
+        /* If quotes, skip all the chars till next quote */
+        i++;
+        while(paramStr[i] != '"') i++;
+      } else if (paramStr[i] == ' ') {
+        /* if paramName is already set, ignore till comma
+         * Or if paramName is parsed as one of the modes, reset.
+         */
+        if(paramName == '' || paramModes.indexOf(paramName) > -1 ) {
+          paramName = paramStr.substring(paramStart, i);
+          paramStart = i+1;
+        }
+      }
+      else if (paramStr[i] == ',') {
+        paramArr.push([paramName, paramStr.substring(paramStart, i)]);
+        paramName = '';
+        paramStart = i+1;
+      }
+      i++;
+    }
+    paramArr.push([paramName, paramStr.substring(paramStart)]);
+  }
+
+  return {
+    'func_name': funcName,
+    'param_string': paramStr,
+    'params': paramArr,
+  };
+}
+
+export function quote_ident(value) {
+  /* check if the string is number or not */
+  let quoteIt = false;
+  if (!isNaN(parseInt(value))){
+    quoteIt = true;
+  }
+
+  if(value.search(/[^a-z0-9_]/g) > -1) {
+    /* escape double quotes */
+    value = value.replace(/"/g, '""');
+    quoteIt = true;
+  }
+
+  if(quoteIt) {
+    return `"${value}"`;
+  } else {
+    return value;
+  }
+}
+
+export function fully_qualify(pgBrowser, data, item) {
+  const parentData = getTreeNodeHierarchyFromIdentifier.call(pgBrowser, item);
+  let namespace = '';
+
+  if (parentData.schema !== undefined) {
+    namespace = quote_ident(parentData.schema._label);
+  }
+  else if (parentData.view !== undefined) {
+    namespace = quote_ident(parentData.view._label);
+  }
+  else if (parentData.catalog !== undefined) {
+    namespace = quote_ident(parentData.catalog._label);
+  }
+
+  if (parentData.package !== undefined && data._type != 'package') {
+    if(namespace == '') {
+      namespace = quote_ident(parentData.package._label);
+    } else {
+      namespace += '.' + quote_ident(parentData.package._label);
+    }
+  }
+
+  if(namespace != '') {
+    return namespace + '.' + quote_ident(data._label);
+  } else {
+    return quote_ident(data._label);
+  }
+}
diff --git a/web/pgadmin/static/scss/_pgadmin.style.scss b/web/pgadmin/static/scss/_pgadmin.style.scss
index ed426545..f5a8877c 100644
--- a/web/pgadmin/static/scss/_pgadmin.style.scss
+++ b/web/pgadmin/static/scss/_pgadmin.style.scss
@@ -983,3 +983,15 @@ table.table-empty-rows{
   padding: 0px !important;
   position: absolute;
 }
+
+.drag-tree-node {
+  position: absolute;
+  top:-100px;
+  left:0;
+  z-index: 99999;
+  color: $input-focus-color;
+  background: $input-bg;
+  border: $input-border-width solid $input-focus-border-color;
+  border-radius: $input-border-radius;
+  padding: $input-btn-padding-y $input-btn-padding-x;
+}
diff --git a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
index a8560574..ef468f63 100644
--- a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
+++ b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
@@ -341,8 +341,31 @@ define('tools.querytool', [
         gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
         extraKeys: pgBrowser.editor_shortcut_keys,
         scrollbarStyle: 'simple',
+        dragDrop: false,
       });
 
+      if(self.handler.is_query_tool) {
+        self.query_tool_obj.setOption('dragDrop', true);
+        self.query_tool_obj.on('drop', (editor, e) => {
+          var cursor = editor.coordsChar({
+            left: e.x,
+            top: e.y,
+          });
+          var dropDetails = JSON.parse(e.dataTransfer.getData('text'));
+          e.codemirrorIgnore = true;
+          e.dataTransfer.clearData('text');
+          editor.replaceRange(dropDetails.text, cursor);
+          editor.focus();
+          editor.setSelection({
+            ...cursor,
+            ch: cursor.ch + dropDetails.cur.from,
+          },{
+            ...cursor,
+            ch: cursor.ch +dropDetails.cur.to,
+          });
+        });
+      }
+
       pgBrowser.Events.on('pgadmin:query_tool:sql_panel:focus', ()=>{
         self.query_tool_obj.focus();
       });
diff --git a/web/regression/javascript/pgadmin_utils_spec.js b/web/regression/javascript/pgadmin_utils_spec.js
index 02bd5478..bc1959a4 100644
--- a/web/regression/javascript/pgadmin_utils_spec.js
+++ b/web/regression/javascript/pgadmin_utils_spec.js
@@ -7,7 +7,7 @@
 //
 //////////////////////////////////////////////////////////////
 
-import { getEpoch, getGCD, getMod } from 'sources/utils';
+import { getEpoch, getGCD, getMod, quote_ident, parseFuncParams } from 'sources/utils';
 
 describe('getEpoch', function () {
   it('should return non zero', function () {
@@ -51,3 +51,87 @@ describe('getMod', function () {
     expect(getMod(-7,5)).toEqual(3);
   });
 });
+
+describe('quote_ident', function () {
+  it('normal string', function () {
+    expect(quote_ident('abcd')).toEqual('abcd');
+  });
+
+  it('contains certain characters string', function () {
+    expect(quote_ident('Abcd')).toEqual('"Abcd"');
+    expect(quote_ident('abc$d')).toEqual('"abc$d"');
+    expect(quote_ident('ab cd')).toEqual('"ab cd"');
+  });
+
+  it('starts with number', function () {
+    expect(quote_ident('1a')).toEqual('"1a"');
+    expect(quote_ident('a1')).toEqual('a1');
+  });
+});
+
+describe('parseFuncParams', function () {
+  let funcLabel = '',
+    expectedObj = {};
+
+  it('function with params', function () {
+    funcLabel = 'func1(a integer, b text)';
+    expectedObj = {
+      'func_name': 'func1',
+      'param_string': 'a integer, b text',
+      'params': [
+        ['a', 'integer'],
+        ['b', 'text'],
+      ],
+    };
+    expect(parseFuncParams(funcLabel)).toEqual(expectedObj);
+  });
+
+  it('function without params', function () {
+    funcLabel = 'func1()';
+    expectedObj = {
+      'func_name': 'func1',
+      'param_string': '',
+      'params': [],
+    };
+    expect(parseFuncParams(funcLabel)).toEqual(expectedObj);
+  });
+
+  it('function name special chars', function () {
+    funcLabel = 'fun(c1(a integer, b text)';
+    expectedObj = {
+      'func_name': 'fun(c1',
+      'param_string': 'a integer, b text',
+      'params': [
+        ['a', 'integer'],
+        ['b', 'text'],
+      ],
+    };
+    expect(parseFuncParams(funcLabel)).toEqual(expectedObj);
+  });
+
+  it('function params special chars', function () {
+    funcLabel = 'func1("a(b" integer, "a b" text)';
+    expectedObj = {
+      'func_name': 'func1',
+      'param_string': '"a(b" integer, "a b" text',
+      'params': [
+        ['"a(b"', 'integer'],
+        ['"a b"', 'text'],
+      ],
+    };
+    expect(parseFuncParams(funcLabel)).toEqual(expectedObj);
+  });
+
+  it('function params with modes', function () {
+    funcLabel = 'func1(IN a integer, OUT b text)';
+    expectedObj = {
+      'func_name': 'func1',
+      'param_string': 'IN a integer, OUT b text',
+      'params': [
+        ['a', 'integer'],
+        ['b', 'text'],
+      ],
+    };
+    expect(parseFuncParams(funcLabel)).toEqual(expectedObj);
+  });
+});


^ permalink  raw  reply  [nested|flat] 8+ messages in thread

* Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree
  2019-06-26 06:23 [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Aditya Toshniwal <[email protected]>
  2019-06-26 11:21 ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Dave Page <[email protected]>
  2019-06-26 11:28   ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Aditya Toshniwal <[email protected]>
  2019-06-26 11:36     ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Dave Page <[email protected]>
  2019-06-26 11:38       ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Aditya Toshniwal <[email protected]>
  2019-06-26 11:39         ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Dave Page <[email protected]>
  2019-06-27 10:31           ` Re: [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Aditya Toshniwal <[email protected]>
@ 2019-06-27 14:30             ` Dave Page <[email protected]>
  0 siblings, 0 replies; 8+ messages in thread

From: Dave Page @ 2019-06-27 14:30 UTC (permalink / raw)
  To: Aditya Toshniwal <[email protected]>; +Cc: pgadmin-hackers

Thanks, applied.

On Thu, Jun 27, 2019 at 6:32 AM Aditya Toshniwal <
[email protected]> wrote:

> Hi Hackers,
>
> Attached is the updated patch based on the review comments in
> trailing mail.
> Kindly review.
>
> On Wed, Jun 26, 2019 at 5:09 PM Dave Page <[email protected]> wrote:
>
>>
>>
>> On Wed, Jun 26, 2019 at 7:38 AM Aditya Toshniwal <
>> [email protected]> wrote:
>>
>>> Hi,
>>>
>>> On Wed, Jun 26, 2019 at 5:06 PM Dave Page <[email protected]> wrote:
>>>
>>>>
>>>>
>>>> On Wed, Jun 26, 2019 at 7:28 AM Aditya Toshniwal <
>>>> [email protected]> wrote:
>>>>
>>>>> Hi,
>>>>>
>>>>> On Wed, Jun 26, 2019 at 4:51 PM Dave Page <[email protected]> wrote:
>>>>>
>>>>>> Hi
>>>>>>
>>>>>> On Wed, Jun 26, 2019 at 2:24 AM Aditya Toshniwal <
>>>>>> [email protected]> wrote:
>>>>>>
>>>>>>> Hi Hackers,
>>>>>>>
>>>>>>> Attached is the patch to allow tree nodes to be dragged and dropped
>>>>>>> in query editor wherever you take the drop cursor. The drop text will be
>>>>>>> fully qualified and double quoted if required.
>>>>>>> For functions/procedures it will drop the the label stripping away
>>>>>>> the parameter names, with empty pair of round brackets. It will also set
>>>>>>> the focus cursor inside the brackets if there were params otherwiser to the
>>>>>>> end of text.
>>>>>>> For adding a node type, you need to register it in browser.js along
>>>>>>> with a callback function which will return drop text along with cursor
>>>>>>> positioning and selection. Currently, I have registered for "table
>>>>>>> partition type sequence package view mview foreign_table edbvar schema
>>>>>>> column edbfunc function edbproc procedure".
>>>>>>>
>>>>>>> Please note, the drag design customisation is not supported in IE.
>>>>>>>
>>>>>>
>>>>>> I think for functions/procedures, we should include placeholders for
>>>>>> the parameters, so the user has a hint about what they need to fill in to
>>>>>> complete the call.
>>>>>>
>>>>> I can fill in the parameter names same as tree node, with cursor
>>>>> selection on all the params ?
>>>>>
>>>>
>>>> Can you select the first one, and put the cursor in front of it?
>>>>
>>> Yes. Will do that. So that, just after drop if the user types anything
>>> it will replace the first param name.
>>>
>>
>> Right.
>>
>>
>>>
>>>>
>>>>>
>>>>>> Also; shouldn't there be a doc update?
>>>>>>
>>>>> Yeah :/
>>>>> Should there be any screenshots ?
>>>>>
>>>>
>>>> I don't see much need.
>>>>
>>> Cool.
>>>
>>
>> :-)
>>
>>
>>>
>>>> Thanks.
>>>>
>>>>
>>>>>
>>>>>> Thanks.
>>>>>>
>>>>>> --
>>>>>> Dave Page
>>>>>> Blog: http://pgsnake.blogspot.com
>>>>>> Twitter: @pgsnake
>>>>>>
>>>>>> EnterpriseDB UK: http://www.enterprisedb.com
>>>>>> The Enterprise PostgreSQL Company
>>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> Thanks and Regards,
>>>>> Aditya Toshniwal
>>>>> Software Engineer | EnterpriseDB India | Pune
>>>>> "Don't Complain about Heat, Plant a TREE"
>>>>>
>>>>
>>>>
>>>> --
>>>> Dave Page
>>>> Blog: http://pgsnake.blogspot.com
>>>> Twitter: @pgsnake
>>>>
>>>> EnterpriseDB UK: http://www.enterprisedb.com
>>>> The Enterprise PostgreSQL Company
>>>>
>>>
>>>
>>> --
>>> Thanks and Regards,
>>> Aditya Toshniwal
>>> Software Engineer | EnterpriseDB India | Pune
>>> "Don't Complain about Heat, Plant a TREE"
>>>
>>
>>
>> --
>> Dave Page
>> Blog: http://pgsnake.blogspot.com
>> Twitter: @pgsnake
>>
>> EnterpriseDB UK: http://www.enterprisedb.com
>> The Enterprise PostgreSQL Company
>>
>
>
> --
> Thanks and Regards,
> Aditya Toshniwal
> Software Engineer | EnterpriseDB India | Pune
> "Don't Complain about Heat, Plant a TREE"
>


-- 
Dave Page
Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake

EnterpriseDB UK: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


^ permalink  raw  reply  [nested|flat] 8+ messages in thread


end of thread, other threads:[~2019-06-27 14:30 UTC | newest]

Thread overview: 8+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2019-06-26 06:23 [pgAdmin][RM4139] Drag and drop object names in Query Editor from Browser Tree Aditya Toshniwal <[email protected]>
2019-06-26 11:21 ` Dave Page <[email protected]>
2019-06-26 11:28   ` Aditya Toshniwal <[email protected]>
2019-06-26 11:36     ` Dave Page <[email protected]>
2019-06-26 11:38       ` Aditya Toshniwal <[email protected]>
2019-06-26 11:39         ` Dave Page <[email protected]>
2019-06-27 10:31           ` Aditya Toshniwal <[email protected]>
2019-06-27 14:30             ` Dave Page <[email protected]>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox