codekingpro/portable-devtools
114k
1/////////////////////////////////////////////////////////////2//3// pgAdmin 4 - PostgreSQL Tools4//5// Copyright (C) 2013 - 2024, The pgAdmin Development Team6// This software is released under the PostgreSQL Licence7//8//////////////////////////////////////////////////////////////9 10import * as BrowserFS from 'browserfs';11import pgAdmin from 'sources/pgadmin';12import _ from 'lodash';13import { FileType } from 'react-aspen';14import { findInTree } from './tree';15 16export class ManagePreferenceTreeNodes {17 constructor(data) {18 this.tree = {};19 this.tempTree = new TreeNode(undefined, {});20 this.treeData = data || [];21 }22 23 public init = (_root: string) => new Promise((res) => {24 const node = { parent: null, children: [], data: null };25 this.tree = {};26 this.tree[_root] = { name: 'root', type: FileType.Directory, metadata: node };27 res();28 });29 30 public updateNode = (_path, _data) => new Promise((res) => {31 const item = this.findNode(_path);32 if (item) {33 item.name = _data.label;34 item.metadata.data = _data;35 }36 res(true);37 });38 39 public removeNode = async (_path) => {40 const item = this.findNode(_path);41 42 if (item && item.parentNode) {43 item.children = [];44 item.parentNode.children.splice(item.parentNode.children.indexOf(item), 1);45 }46 return true;47 };48 49 findNode(path) {50 if (path === null || path === undefined || path.length === 0 || path == '/preferences') {51 return this.tempTree;52 }53 54 return findInTree(this.tempTree, path);55 }56 57 public addNode = (_parent: string, _path: string, _data: []) => new Promise((res) => {58 _data.type = _data.inode ? FileType.Directory : FileType.File;59 _data._label = _data.label;60 _data.label = _.escape(_data.label);61 62 _data.is_collection = isCollectionNode(_data._type);63 const nodeData = { parent: _parent, children: _data?.children ? _data.children : [], data: _data };64 65 const tmpParentNode = this.findNode(_parent);66 const treeNode = new TreeNode(_data.id, _data, {}, tmpParentNode, nodeData, _data.type);67 68 if (tmpParentNode !== null && tmpParentNode !== undefined) tmpParentNode.children.push(treeNode);69 70 res(treeNode);71 });72 73 public readNode = (_path: string) => new Promise<string[]>((res, rej) => {74 const temp_tree_path = _path,75 node = this.findNode(_path);76 node.children = [];77 78 if (node && node.children.length > 0) {79 if (!node.type === FileType.File) {80 rej('It\'s a leaf node');81 }82 else {83 if (node?.children.length != 0) res(node.children);84 }85 }86 87 const self = this;88 89 async function loadData() {90 const Path = BrowserFS.BFSRequire('path');91 const fill = async (tree) => {92 for (const idx in tree) {93 const _node = tree[idx];94 const _pathl = Path.join(_path, _node.id);95 await self.addNode(temp_tree_path, _pathl, _node);96 }97 };98 99 if (node && !_.isUndefined(node.id)) {100 const _data = self.treeData.find((el) => el.id == node.id);101 const subNodes = [];102 103 _data.childrenNodes.forEach(element => {104 subNodes.push(element);105 });106 107 await fill(subNodes);108 } else {109 await fill(self.treeData);110 }111 112 self.returnChildrens(node, res);113 }114 loadData();115 });116 117 public returnChildrens = (node: any, res: any) =>{118 if (node?.children.length > 0) return res(node.children);119 else return res(null);120 };121}122 123 124 125export class TreeNode {126 constructor(id, data, domNode, parent, metadata, type) {127 this.id = id;128 this.data = data;129 this.setParent(parent);130 this.children = [];131 this.domNode = domNode;132 this.metadata = metadata;133 this.name = metadata ? metadata.data.label : '';134 this.type = type ? type : undefined;135 }136 137 hasParent() {138 return this.parentNode !== null && this.parentNode !== undefined;139 }140 141 parent() {142 return this.parentNode;143 }144 145 setParent(parent) {146 this.parentNode = parent;147 this.path = this.id;148 if (this.id)149 if (parent !== null && parent !== undefined && parent.path !== undefined) {150 this.path = parent.path + '/' + this.id;151 } else {152 this.path = '/preferences/' + this.id;153 }154 }155 156 getData() {157 if (this.data === undefined) {158 return undefined;159 } else if (this.data === null) {160 return null;161 }162 return Object.assign({}, this.data);163 }164 165 getHtmlIdentifier() {166 return this.domNode;167 }168 169 /*170 * Find the ancestor with matches this condition171 */172 ancestorNode(condition) {173 let node;174 175 while (this.hasParent()) {176 node = this.parent();177 if (condition(node)) {178 return node;179 }180 }181 182 return null;183 }184 185 /**186 * Given a condition returns true if the current node187 * or any of the parent nodes condition result is true188 */189 anyFamilyMember(condition) {190 if (condition(this)) {191 return true;192 }193 194 return this.ancestorNode(condition) !== null;195 }196 anyParent(condition) {197 return this.ancestorNode(condition) !== null;198 }199 200 reload(tree) {201 return new Promise((resolve) => {202 this.unload(tree)203 .then(() => {204 tree.setInode(this.domNode);205 tree.deselect(this.domNode);206 setTimeout(() => {207 tree.selectNode(this.domNode);208 }, 0);209 resolve();210 });211 });212 }213 214 unload(tree) {215 return new Promise((resolve, reject) => {216 this.children = [];217 tree.unload(this.domNode)218 .then(219 () => {220 resolve(true);221 },222 () => {223 reject();224 });225 });226 }227 228 229 open(tree, suppressNoDom) {230 return new Promise((resolve, reject) => {231 if (suppressNoDom && (this.domNode == null || typeof (this.domNode) === 'undefined')) {232 resolve(true);233 } else if (tree.isOpen(this.domNode)) {234 resolve(true);235 } else {236 tree.open(this.domNode).then(() => resolve(true), () => reject(true));237 }238 });239 }240 241}242 243export function isCollectionNode(node) {244 if (pgAdmin.Browser.Nodes && node in pgAdmin.Browser.Nodes) {245 if (pgAdmin.Browser.Nodes[node].is_collection !== undefined) return pgAdmin.Browser.Nodes[node].is_collection;246 else return false;247 }248 return false;249}250 