Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
ObjectExplorer.jsx197 linesDownload Raw Back to tree
1import React, { useEffect, useMemo, useRef, useState } from 'react';2import {Tree} from './tree';3import * as pgadminUtils from '../utils';4 5import { Directory } from 'react-aspen';6import { ManageTreeNodes } from './tree_nodes';7import { FileTreeX, TreeModelX } from '../components/PgTree';8import ContextMenu from '../components/ContextMenu';9import { generateNodeUrl } from '../../../browser/static/js/node_ajax';10import { copyToClipboard } from '../clipboard';11import { usePgAdmin } from '../BrowserComponent';12 13function postTreeReady(b) {14  const draggableTypes = [15    'collation domain domain_constraints fts_configuration fts_dictionary fts_parser fts_template synonym table partition type sequence package view mview foreign_table edbvar',16    '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',17    'trigger trigger_function',18    'edbfunc function edbproc procedure',19    'coll-column'20  ];21  const getQualifiedName = (data, item)=>{22    if(draggableTypes[0].includes(data._type)) {23      return pgadminUtils.fully_qualify(b, data, item);24    } else if(draggableTypes[1].includes(data._type)) {25      return pgadminUtils.quote_ident(data._label);26    } else if(draggableTypes[3].includes(data._type)) {27      let newData = {...data};28      let parsedFunc = pgadminUtils.parseFuncParams(newData._label);29      newData._label = parsedFunc.func_name;30      return pgadminUtils.fully_qualify(b, newData, item);31    } else {32      return data._label;33    }34  };35 36  b.tree.registerDraggableType({37    [draggableTypes[0]] : (data, item, treeNodeInfo)=>{38      let text = getQualifiedName(data, item);39      return {40        text: text,41        objUrl: generateNodeUrl.call(b.Nodes[data._type], treeNodeInfo, 'properties', data, true),42        nodeType: data._type,43        cur: {44          from: text.length,45          to: text.length,46        },47      };48    },49    [draggableTypes[1]] : (data)=>{50      return getQualifiedName(data);51    },52    [draggableTypes[2]] : (data)=>{53      return getQualifiedName(data);54    },55    [draggableTypes[3]] : (data, item)=>{56      let parsedFunc = pgadminUtils.parseFuncParams(data._label),57        dropVal = getQualifiedName(data, item),58        curPos = {from: 0, to: 0};59 60      if(parsedFunc.params.length > 0) {61        dropVal = dropVal + '(';62        curPos.from =  dropVal.length;63        dropVal = dropVal + parsedFunc.params[0][0];64        curPos.to = dropVal.length;65 66        for(let i=1; i<parsedFunc.params.length; i++) {67          dropVal = dropVal + ', ' + parsedFunc.params[i][0];68        }69 70        dropVal = dropVal + ')';71      } else {72        dropVal = dropVal + '()';73        curPos.from = curPos.to = dropVal.length + 1;74      }75 76      return {77        text: dropVal,78        cur: curPos,79      };80    },81    [draggableTypes[4]] : (_data, item)=>{82      return item?.children?.map((ci)=>{83        return getQualifiedName(ci._metadata.data);84      }).join(', ') ?? '';85    }86  });87 88  b.tree.onNodeCopy((data, item)=>{89    copyToClipboard(getQualifiedName(data, item));90  });91}92 93export default function ObjectExplorer() {94  const [contextPos, setContextPos] = React.useState(null);95  const pgAdmin = usePgAdmin();96  const contextMenuItems = pgAdmin.Browser.BrowserContextMenu;97  const [treeModelLoaded, setTreeModelLoaded] = useState(false);98  const treeModelXRef = useRef();99  const MOUNT_POINT = '/browser';100  const mtree = useMemo(()=>new ManageTreeNodes(), []);101 102  useEffect(()=>{103    // Init Tree with the Tree Parent node '/browser'104    mtree.init(MOUNT_POINT);105 106    const host = {107      pathStyle: 'unix',108      getItems: async (path) => {109        return mtree.readNode(path);110      },111      sortComparator: (a, b) => {112        // No nee to sort columns113        if (a._metadata && a._metadata.data._type == 'column') return 0;114        // Sort alphabetically115        if (a.constructor === b.constructor) {116          return pgAdmin.natural_sort(a.fileName, b.fileName);117        }118        let retval = 0;119        if (a.constructor === Directory) {120          retval = -1;121        } else if (b.constructor === Directory) {122          retval = 1;123        }124        return retval;125      },126    };127 128    treeModelXRef.current = new TreeModelX(host, MOUNT_POINT);129 130    treeModelXRef.current.root.ensureLoaded().then(()=>{131      setTreeModelLoaded(true);132    });133  }, []);134 135  const itemHandle = function onReady(handler) {136    pgAdmin.Browser.tree = new Tree(handler, mtree, pgAdmin.Browser);137    postTreeReady(pgAdmin.Browser);138  };139  // Create Node140  const create = async (parentPath, _data) => {141    try {142      const _node_path = parentPath + '/' + _data.id;143      return mtree.addNode(parentPath, _node_path, _data);144    } catch (error) {145      return null; // or throw error as you see fit146    }147  };148 149  // Remove Node150  const remove = async (path, _removeOnlyChild) => {151    try {152      await mtree.removeNode(path, _removeOnlyChild);153      return true;154    } catch (error) {155      return false; // or throw error as you see fit156    }157  };158 159  // Update Node160  const update = async (path, data) => {161    try {162      await mtree.updateNode(path, data);163      return true;164    } catch (error) {165      return false; // or throw error as you see fit166    }167  };168 169  const onContextMenu = React.useCallback(async (ev, item)=>{170    ev.preventDefault();171    if(item) {172      await pgAdmin.Browser.tree.select(item);173      setContextPos({x: ev.clientX, y: ev.clientY});174    }175  }, []);176 177  if(!treeModelLoaded) {178    return <span>Loading...</span>;179  }180 181  return (182    <>183      <FileTreeX184        model={treeModelXRef.current}185        onReady={itemHandle}186        create={create} update={update} remove={remove}187        height={'100%'} disableCache={true} onContextMenu={onContextMenu}188        onScroll={()=>{189          contextPos && setContextPos(null);190        }}191      />192      <ContextMenu position={contextPos} onClose={()=>setContextPos(null)}193        menuItems={contextMenuItems} label="Object Context Menu" />194    </>195  );196}197 
codekingpro/portable-devtools · Team Ai