On pressing Ctrl+C on a tree object, copy the fully qualified name to clipboard. #5854

This commit is contained in:
Aditya Toshniwal 2023-03-29 21:45:09 +05:30 committed by GitHub
parent 3f78cfa092
commit 5330121b36
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 60 additions and 18 deletions

View File

@ -17,6 +17,7 @@ import { pgHandleItemError } from '../../../static/js/utils';
import { Search } from './quick_search/trigger_search';
import { send_heartbeat, stop_heartbeat } from './heartbeat';
import getApiInstance from '../../../static/js/api_instance';
import { copyToClipboard } from '../../../static/js/clipboard';
define('pgadmin.browser', [
'sources/gettext', 'sources/url_for', 'jquery',
@ -70,10 +71,31 @@ define('pgadmin.browser', [
let initializeBrowserTree = pgAdmin.Browser.initializeBrowserTree =
function(b) {
const draggableTypes = [
'collation domain domain_constraints fts_configuration fts_dictionary fts_parser fts_template synonym table partition type sequence package view mview foreign_table edbvar',
'schema column database cast event_trigger extension language foreign_data_wrapper foreign_server user_mapping compound_trigger index index_constraint primary_key unique_constraint check_constraint exclusion_constraint foreign_key rule',
'trigger trigger_function',
'edbfunc function edbproc procedure'
];
InitTree.initBrowserTree(b).then(() => {
const getQualifiedName = (data, item)=>{
if(draggableTypes[0].includes(data._type)) {
return pgadminUtils.fully_qualify(b, data, item);
} else if(draggableTypes[1].includes(data._type)) {
return pgadminUtils.quote_ident(data._label);
} else if(draggableTypes[3].includes(data._type)) {
let newData = {...data};
let parsedFunc = pgadminUtils.parseFuncParams(newData._label);
newData._label = parsedFunc.func_name;
return pgadminUtils.fully_qualify(b, newData, item);
} else {
return data._label;
}
};
b.tree.registerDraggableType({
'collation domain domain_constraints fts_configuration fts_dictionary fts_parser fts_template synonym table partition type sequence package view mview foreign_table edbvar' : (data, item, treeNodeInfo)=>{
let text = pgadminUtils.fully_qualify(b, data, item);
[draggableTypes[0]] : (data, item, treeNodeInfo)=>{
let text = getQualifiedName(data, item);
return {
text: text,
objUrl: generateNodeUrl.call(pgBrowser.Nodes[data._type], treeNodeInfo, 'properties', data, true),
@ -84,22 +106,17 @@ define('pgadmin.browser', [
},
};
},
'schema column database cast event_trigger extension language foreign_data_wrapper foreign_server user_mapping compound_trigger index index_constraint primary_key unique_constraint check_constraint exclusion_constraint foreign_key rule' : (data)=>{
return pgadminUtils.quote_ident(data._label);
[draggableTypes[1]] : (data)=>{
return getQualifiedName(data);
},
'trigger trigger_function' : (data)=>{
return data._label;
[draggableTypes[2]] : (data)=>{
return getQualifiedName(data);
},
'edbfunc function edbproc procedure' : (data, item)=>{
let newData = {...data},
parsedFunc = null,
dropVal = '',
[draggableTypes[3]] : (data, item)=>{
let parsedFunc = pgadminUtils.parseFuncParams(data._label),
dropVal = getQualifiedName(data, item),
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;
@ -122,6 +139,10 @@ define('pgadmin.browser', [
};
},
});
b.tree.onNodeCopy((data, item)=>{
copyToClipboard(getQualifiedName(data, item));
});
}, () => {console.warn('Tree Load Error');});
};

View File

@ -159,7 +159,7 @@ export class FileTreeX extends React.Component<IFileTreeXProps> {
this.setPseudoActiveFile(null);
}));
this.keyboardHotkeys = new KeyboardHotkeys(this.fileTreeHandle);
this.keyboardHotkeys = new KeyboardHotkeys(this.fileTreeHandle, this.events);
if (typeof onReady === 'function') {
onReady(this.fileTreeHandle);

View File

@ -1,5 +1,6 @@
import { Notificar } from 'notificar';
import { FileEntry, Directory, FileType } from 'react-aspen';
import { IFileTreeXHandle } from '../types';
import { FileTreeXEvent, IFileTreeXHandle } from '../types';
export class KeyboardHotkeys {
private hotkeyActions = {
@ -12,15 +13,20 @@ export class KeyboardHotkeys {
'Home': () => this.jumpToFirstItem(),
'End': () => this.jumpToLastItem(),
'Escape': () => this.resetSteppedOrSelectedItem(),
'Ctrl+KeyC': () => this.copyEntry(),
};
constructor(private readonly fileTreeX: IFileTreeXHandle) { }
constructor(private readonly fileTreeX: IFileTreeXHandle, private readonly events: Notificar<FileTreeXEvent>) { }
public handleKeyDown = (ev: React.KeyboardEvent) => {
if (!this.fileTreeX.hasDirectFocus()) {
return false;
}
const { code } = ev.nativeEvent;
let { code } = ev.nativeEvent;
if((ev.nativeEvent.ctrlKey || ev.nativeEvent.metaKey) && ev.nativeEvent.key !== 'Control') {
code = `Ctrl+${code}`;
}
if (code in this.hotkeyActions) {
ev.preventDefault();
this.hotkeyActions[code]();
@ -126,4 +132,9 @@ export class KeyboardHotkeys {
private resetSteppedItem = () => {
this.fileTreeX.setActiveFile(null);
};
private copyEntry = () => {
const currentPseudoActive = this.fileTreeX.getActiveFile();
this.events.dispatch(FileTreeXEvent.onTreeEvents, null, 'copied', currentPseudoActive);
};
}

View File

@ -43,6 +43,9 @@ function manageTreeEvents(event, eventName, item) {
if (eventName == 'added' || eventName == 'beforeopen' || eventName == 'loaded') {
obj.tree.addNewNode(item.getMetadata('data').id, item.getMetadata('data'), item, item.parent.path);
}
if(eventName == 'copied') {
obj.tree.copyHandler?.(item.getMetadata('data'), item);
}
if (_.isObject(node.callbacks) &&
eventName in node.callbacks &&
typeof node.callbacks[eventName] == 'function' &&
@ -545,6 +548,13 @@ export class Tree {
e.dataTransfer.setDragImage(dragItem, 0, 0);
}
}
else {
e.preventDefault();
}
}
onNodeCopy(copyCallback) {
this.copyHandler = copyCallback;
}
}