From 042888f5d7a9125f5cf3a8772aa47b2d5c5720df Mon Sep 17 00:00:00 2001 From: Aditya Toshniwal Date: Fri, 22 Nov 2024 16:26:50 +0530 Subject: [PATCH] Fixed an issue where ERD auto-layout should: #6592 (#8167) - Always generate right-angled links - Switch port to Left/Right for the best link route. --- web/.eslintrc.js | 15 ++++++++++++++- web/package.json | 1 + .../tools/erd/static/js/erd_tool/ERDCore.js | 18 +++++++++++------- .../static/js/erd_tool/components/ERDTool.jsx | 12 ++++++++---- .../static/js/erd_tool/links/OneToManyLink.jsx | 4 ++-- .../javascript/__mocks__/@mui/material.jsx | 2 +- .../javascript/__mocks__/react-data-grid.jsx | 2 +- web/regression/javascript/erd/erd_core_spec.js | 7 +------ web/yarn.lock | 14 ++++++++++++++ 9 files changed, 53 insertions(+), 22 deletions(-) diff --git a/web/.eslintrc.js b/web/.eslintrc.js index 86ae79332..abd470d43 100644 --- a/web/.eslintrc.js +++ b/web/.eslintrc.js @@ -13,6 +13,7 @@ const jest = require('eslint-plugin-jest'); const babel = require('@babel/eslint-plugin'); const babelParser = require('@babel/eslint-parser'); const ts = require('typescript-eslint'); +const unusedImports = require('eslint-plugin-unused-imports'); module.exports = [ @@ -63,6 +64,7 @@ module.exports = [ 'plugins': { 'react': reactjs, '@babel': babel, + 'unused-imports': unusedImports, }, 'rules': { 'indent': [ @@ -91,7 +93,18 @@ module.exports = [ ...reactjs.configs.recommended.rules, ...reactjs.configs['jsx-runtime'].rules, 'react/jsx-uses-react': 'error', - 'react/jsx-uses-vars': 'error' + 'react/jsx-uses-vars': 'error', + 'no-unused-vars': 'off', + 'unused-imports/no-unused-imports': 'error', + 'unused-imports/no-unused-vars': [ + 'warn', + { + 'vars': 'all', + 'varsIgnorePattern': '^_', + 'args': 'after-used', + 'argsIgnorePattern': '^_', + }, + ] }, 'settings': { 'react': { diff --git a/web/package.json b/web/package.json index 8f610dde1..ca6c806da 100644 --- a/web/package.json +++ b/web/package.json @@ -37,6 +37,7 @@ "eslint": "^9.11.1", "eslint-plugin-jest": "^28.8.0", "eslint-plugin-react": "^7.34.3", + "eslint-plugin-unused-imports": "^4.1.4", "exports-loader": "^5.0.0", "globals": "^15.8.0", "html-react-parser": "^5.0.6", diff --git a/web/pgadmin/tools/erd/static/js/erd_tool/ERDCore.js b/web/pgadmin/tools/erd/static/js/erd_tool/ERDCore.js index 456d4fa7c..a017e6466 100644 --- a/web/pgadmin/tools/erd/static/js/erd_tool/ERDCore.js +++ b/web/pgadmin/tools/erd/static/js/erd_tool/ERDCore.js @@ -49,7 +49,7 @@ export default class ERDCore { marginx: 5, marginy: 5, }, - includeLinks: true, + includeLinks: false, }); this.engine.getNodeFactories().registerFactory(new TableNodeFactory()); @@ -645,12 +645,10 @@ export default class ERDCore { }); } }); - - setTimeout(this.dagreDistributeNodes.bind(this), 250); } - repaint() { - this.getEngine().repaintCanvas(); + async repaint() { + await this.getEngine().repaintCanvas(true); } clearSelection() { @@ -679,9 +677,15 @@ export default class ERDCore { .filter(entity => entity instanceof OneToManyLinkModel); } - dagreDistributeNodes() { + async dagreDistributeNodes() { this.dagre_engine.redistribute(this.getModel()); - this.repaint(); + + // Swith left/right ports. + this.getModel().getNodes().forEach((node)=>{ + this.optimizePortsPosition(node); + }); + + await this.repaint(); } zoomIn() { diff --git a/web/pgadmin/tools/erd/static/js/erd_tool/components/ERDTool.jsx b/web/pgadmin/tools/erd/static/js/erd_tool/components/ERDTool.jsx index 3db38752a..c0b40a4ce 100644 --- a/web/pgadmin/tools/erd/static/js/erd_tool/components/ERDTool.jsx +++ b/web/pgadmin/tools/erd/static/js/erd_tool/components/ERDTool.jsx @@ -512,7 +512,7 @@ export default class ERDTool extends React.Component { }); if (this.diagram.getNodesData().length === 0){ this.setState({dirty: false}); - this.eventBus.fireEvent(ERD_EVENTS.DIRTY, false); + this.eventBus.fireEvent(ERD_EVENTS.DIRTY, false); } this.diagram.repaint(); }, @@ -520,8 +520,10 @@ export default class ERDTool extends React.Component { ); } - onAutoDistribute() { - this.diagram.dagreDistributeNodes(); + async onAutoDistribute() { + this.setLoading('Auto distributing...'); + await this.diagram.dagreDistributeNodes(); + this.setLoading(); } onChangeColors(fillColor, textColor) { @@ -883,7 +885,9 @@ export default class ERDTool extends React.Component { } catch (error) { this.handleAxiosCatch(error); } - this.setLoading(null); + setTimeout(()=>{ + this.onAutoDistribute(); + }, 250); } render() { diff --git a/web/pgadmin/tools/erd/static/js/erd_tool/links/OneToManyLink.jsx b/web/pgadmin/tools/erd/static/js/erd_tool/links/OneToManyLink.jsx index 5bf7d80f3..bc3e90d39 100644 --- a/web/pgadmin/tools/erd/static/js/erd_tool/links/OneToManyLink.jsx +++ b/web/pgadmin/tools/erd/static/js/erd_tool/links/OneToManyLink.jsx @@ -281,7 +281,7 @@ export class OneToManyLinkWidget extends RightAngleLinkWidget { } // If there is existing link which has two points add one - if (points.length === 2 && !this.state.canDrag) { + if (points.length === 2 && !this.state.canDrag && onePoint.point.getX() != manyPoint.point.getX()) { this.props.link.addPoint( new PointModel({ link: this.props.link, @@ -291,6 +291,7 @@ export class OneToManyLinkWidget extends RightAngleLinkWidget { } paths.push(this.generateCustomEndWidget(onePoint)); + for (let j = 0; j < points.length - 1; j++) { paths.push( this.generateLink( @@ -319,7 +320,6 @@ export class OneToManyLinkWidget extends RightAngleLinkWidget { } paths.push(this.generateCustomEndWidget(manyPoint)); - this.refPaths = []; return {paths}; } diff --git a/web/regression/javascript/__mocks__/@mui/material.jsx b/web/regression/javascript/__mocks__/@mui/material.jsx index 8907b5669..109132668 100644 --- a/web/regression/javascript/__mocks__/@mui/material.jsx +++ b/web/regression/javascript/__mocks__/@mui/material.jsx @@ -3,7 +3,7 @@ import CustomPropTypes from '../../../../pgadmin/static/js/custom_prop_types'; export * from '@mui/material'; // mock popper -// eslint-disable-next-line no-unused-vars + export const Popper = React.forwardRef((props, _ref)=>{ const ele = useRef(); return
{props.children}
; diff --git a/web/regression/javascript/__mocks__/react-data-grid.jsx b/web/regression/javascript/__mocks__/react-data-grid.jsx index 772f11f89..16ee3538a 100644 --- a/web/regression/javascript/__mocks__/react-data-grid.jsx +++ b/web/regression/javascript/__mocks__/react-data-grid.jsx @@ -2,7 +2,7 @@ import React, { useRef } from 'react'; import PropTypes from 'prop-types'; export * from 'react-data-grid'; -// eslint-disable-next-line no-unused-vars + const ReactDataGrid = React.forwardRef((props, _ref)=>{ const ele = useRef(); return
; diff --git a/web/regression/javascript/erd/erd_core_spec.js b/web/regression/javascript/erd/erd_core_spec.js index a930adeeb..7aeaceafc 100644 --- a/web/regression/javascript/erd/erd_core_spec.js +++ b/web/regression/javascript/erd/erd_core_spec.js @@ -230,7 +230,7 @@ describe('ERDCore', ()=>{ })); }); - it('deserializeData', (done)=>{ + it('deserializeData', ()=>{ let nodesDict = {}; TEST_TABLES_DATA.forEach((table)=>{ nodesDict[`id-${table.name}`] = { @@ -269,11 +269,6 @@ describe('ERDCore', ()=>{ erdCoreObj.deserializeData(TEST_TABLES_DATA); expect(erdCoreObj.addNode).toHaveBeenCalledTimes(TEST_TABLES_DATA.length); expect(erdCoreObj.addLink).toHaveBeenCalledTimes(1); - - setTimeout(()=>{ - expect(erdCoreObj.dagreDistributeNodes).toHaveBeenCalled(); - done(); - }, 500); }); it('clearSelection', ()=>{ diff --git a/web/yarn.lock b/web/yarn.lock index 1f66003fd..d488cfba3 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -6845,6 +6845,19 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-unused-imports@npm:^4.1.4": + version: 4.1.4 + resolution: "eslint-plugin-unused-imports@npm:4.1.4" + peerDependencies: + "@typescript-eslint/eslint-plugin": ^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0 + eslint: ^9.0.0 || ^8.0.0 + peerDependenciesMeta: + "@typescript-eslint/eslint-plugin": + optional: true + checksum: 1f4ce3e3972699345513840f3af1b783033dbc3a3e85b62ce12b3f6a89fd8c92afe46d0c00af40bacb14465445983ba0ccc326a6fd5132553061fb0e47bcba19 + languageName: node + linkType: hard + "eslint-rule-composer@npm:^0.3.0": version: 0.3.0 resolution: "eslint-rule-composer@npm:0.3.0" @@ -13320,6 +13333,7 @@ __metadata: eslint: ^9.11.1 eslint-plugin-jest: ^28.8.0 eslint-plugin-react: ^7.34.3 + eslint-plugin-unused-imports: ^4.1.4 exports-loader: ^5.0.0 globals: ^15.8.0 hotkeys-js: ^3.13.3