mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Allow some objects to be dragged/dropped into the Query Tool to insert their signature into the query text. Fixes #4139
This commit is contained in:
committed by
Dave Page
parent
bdb8f20aed
commit
173b812b93
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user