diff --git a/docs/en_US/release_notes_5_0.rst b/docs/en_US/release_notes_5_0.rst index 9d546c346..d3179c80c 100644 --- a/docs/en_US/release_notes_5_0.rst +++ b/docs/en_US/release_notes_5_0.rst @@ -22,6 +22,7 @@ Bug fixes | `Issue #6087 `_ - Fixed an issue where the dependencies tab showing multiple owners for the objects having shared dependencies. | `Issue #6163 `_ - Fixed an issue where Zoom to fit button only works if the diagram is larger than the canvas. | `Issue #6164 `_ - Ensure that the diagram should not vanish entirely if zooming out too far in ERD. +| `Issue #6177 `_ - Fixed an issue while downloading ERD images in Safari and Firefox. | `Issue #6179 `_ - Fixed an issue where Generate SQL displayed twice in the ERD tool. | `Issue #6180 `_ - Updated missing documentation for the 'Download Image' option in ERD. diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/static/img/schema.svg b/web/pgadmin/browser/server_groups/servers/databases/schemas/static/img/schema.svg index f19b03b20..8a1bdf1b1 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/static/img/schema.svg +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/static/img/schema.svg @@ -1 +1 @@ -coll-schema \ No newline at end of file +coll-schema diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/static/img/column.svg b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/static/img/column.svg index 28e8020b8..5afb75a99 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/static/img/column.svg +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/static/img/column.svg @@ -1 +1 @@ -column \ No newline at end of file +column diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/static/img/foreign_key.svg b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/static/img/foreign_key.svg index 7cc75851c..23d7d1ee8 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/static/img/foreign_key.svg +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/static/img/foreign_key.svg @@ -1 +1 @@ -foreign_key \ No newline at end of file +foreign_key diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/img/primary_key.svg b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/img/primary_key.svg index 2bb374f44..e1864243c 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/img/primary_key.svg +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/img/primary_key.svg @@ -1 +1 @@ -primary_key \ No newline at end of file +primary_key diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/img/table.svg b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/img/table.svg index 8848103c2..4f8b2d624 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/img/table.svg +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/img/table.svg @@ -1 +1 @@ -table \ No newline at end of file +table 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 865fc120f..f2de8edb9 100644 --- a/web/pgadmin/tools/erd/static/js/erd_tool/ERDCore.js +++ b/web/pgadmin/tools/erd/static/js/erd_tool/ERDCore.js @@ -303,7 +303,7 @@ export default class ERDCore { this.addLink(newData, 'onetomany'); }); - setTimeout(this.dagreDistributeNodes.bind(this), 0); + setTimeout(this.dagreDistributeNodes.bind(this), 250); } repaint() { 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 37b456825..0121804d8 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 @@ -94,7 +94,7 @@ const CustomLinkEndWidget = props => { return ( - + {svgForType(type)} diff --git a/web/pgadmin/tools/erd/static/js/erd_tool/nodes/TableNode.jsx b/web/pgadmin/tools/erd/static/js/erd_tool/nodes/TableNode.jsx index 383c621ce..95a624d81 100644 --- a/web/pgadmin/tools/erd/static/js/erd_tool/nodes/TableNode.jsx +++ b/web/pgadmin/tools/erd/static/js/erd_tool/nodes/TableNode.jsx @@ -12,6 +12,11 @@ import { DefaultNodeModel, PortWidget } from '@projectstorm/react-diagrams'; import { AbstractReactFactory } from '@projectstorm/react-canvas-core'; import _ from 'lodash'; import { IconButton, DetailsToggleButton } from '../ui_components/ToolBar'; +import SchemaIcon from 'top/browser/server_groups/servers/databases/schemas/static/img/schema.svg'; +import TableIcon from 'top/browser/server_groups/servers/databases/schemas/tables/static/img/table.svg'; +import PrimaryKeyIcon from 'top/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/img/primary_key.svg'; +import ForeignKeyIcon from 'top/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/static/img/foreign_key.svg'; +import ColumnIcon from 'top/browser/server_groups/servers/databases/schemas/tables/columns/static/img/column.svg'; const TYPE = 'table'; @@ -114,6 +119,14 @@ export class TableNodeModel extends DefaultNodeModel { } } +function RowIcon({icon}) { + return ( +
+ +
+ ); +} + export class TableNodeWidget extends React.Component { constructor(props) { super(props); @@ -131,11 +144,17 @@ export class TableNodeWidget extends React.Component { generateColumn(col) { let port = this.props.node.getPort(this.props.node.getPortName(col.attnum)); + let icon = ColumnIcon; + if(col.is_primary_key) { + icon = PrimaryKeyIcon; + } else if(port && port.getSubtype() == 'many') { + icon = ForeignKeyIcon; + } return (
-
-
+ +
{col.name}  {this.state.show_details && {col.cltype}{col.attlen ? ('('+ col.attlen + (col.attprecision ? ','+col.attprecision : '') +')') : ''}} @@ -172,12 +191,12 @@ export class TableNodeWidget extends React.Component { }} title="Check note" />}
-
-
{node_data.schema}
+ +
{node_data.schema}
-
-
{node_data.name}
+ +
{node_data.name}
{_.map(node_data.columns, (col)=>this.generateColumn(col))} diff --git a/web/pgadmin/tools/erd/static/js/erd_tool/ui_components/BodyWidget.jsx b/web/pgadmin/tools/erd/static/js/erd_tool/ui_components/BodyWidget.jsx index c36d87e03..90c284ab8 100644 --- a/web/pgadmin/tools/erd/static/js/erd_tool/ui_components/BodyWidget.jsx +++ b/web/pgadmin/tools/erd/static/js/erd_tool/ui_components/BodyWidget.jsx @@ -542,6 +542,35 @@ export default class BodyWidget extends React.Component { this.canvasEle.style.width = this.canvasEle.scrollWidth + 'px'; this.canvasEle.style.height = this.canvasEle.scrollHeight + 'px'; + /* html2canvas ignores CSS styles, set the CSS styles to inline */ + const setSvgInlineStyles = (targetElem) => { + const transformProperties = [ + 'fill', + 'color', + 'font-size', + 'stroke', + 'font' + ]; + let svgElems = Array.from(targetElem.getElementsByTagName("svg")); + for (let svgElement of svgElems) { + svgElement.setAttribute('width', svgElement.clientWidth); + svgElement.setAttribute('height', svgElement.clientHeight); + recurseElementChildren(svgElement); + } + function recurseElementChildren(node) { + if (!node.style) + return; + + let styles = getComputedStyle(node); + for (let transformProperty of transformProperties) { + node.style[transformProperty] = styles[transformProperty]; + } + for (let child of Array.from(node.childNodes)) { + recurseElementChildren(child); + } + } + } + html2canvas(this.canvasEle, { width: this.canvasEle.scrollWidth + 10, height: this.canvasEle.scrollHeight + 10, @@ -550,11 +579,16 @@ export default class BodyWidget extends React.Component { useCORS: true, allowTaint: true, backgroundColor: window.getComputedStyle(this.canvasEle).backgroundColor, + onclone: (clonedEle)=>{ + setSvgInlineStyles(clonedEle); + return clonedEle; + }, }).then((canvas)=>{ let link = document.createElement('a'); link.setAttribute('href', canvas.toDataURL('image/png')); link.setAttribute('download', this.getCurrentProjectName() + '.png'); link.click(); + link.remove(); }).catch((err)=>{ console.error(err); let msg = gettext('Unknown error. Check console logs'); diff --git a/web/pgadmin/tools/erd/static/scss/_erd.scss b/web/pgadmin/tools/erd/static/scss/_erd.scss index 4fffcf4be..a54df1284 100644 --- a/web/pgadmin/tools/erd/static/scss/_erd.scss +++ b/web/pgadmin/tools/erd/static/scss/_erd.scss @@ -97,20 +97,8 @@ width: 175px; font-size: 0.8em; - .table-icon-schema { - background-image: url('~top/browser/server_groups/servers/databases/schemas/static/img/schema.svg') !important; - // background-repeat: no-repeat; - // // background-size: 20px !important; - // align-content: center; - // vertical-align: middle; - // height: 100%; - // background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDIwLjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCA2NCA2NCIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNjQgNjQ7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KCS5zdDB7ZmlsbDpub25lO3N0cm9rZTojOTk5OTk5O3N0cm9rZS13aWR0aDoyO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1taXRlcmxpbWl0OjEwO30KPC9zdHlsZT4KPHBhdGggY2xhc3M9InN0MCIgZD0iTTIxLjksMjIuMmMwLDMuNS0yLjksNi40LTYuNCw2LjRzLTYuNC0yLjktNi40LTYuNHMyLjktNi40LDYuNC02LjRTMjEuOSwxOC43LDIxLjksMjIuMnogTTQuMiw1MWwyMi4xLTE5CgkgTTQ2LjUsNTEuMUwyNi40LDMyIE0zNy42LDQyLjZsMTEuNi0xMCBNNjIuNCw0NS4xTDQ5LjIsMzIuNyBNNjMsMUgxdjYyaDYyVjF6IE0xLDUxLjRoNjIiLz4KPC9zdmc+Cg=='); - - width: 20px; - height: 20px; - // background: transparent url('~top/browser/server_groups/servers/databases/schemas/static/img/schema.svg') no-repeat center center; - // height: 100%; - // width: 20px; + .table-icon { + padding: 0rem 0.125rem; } &.selected { @@ -175,6 +163,7 @@ .svg-link-ele.path { pointer-events: all; + cursor: move; } @keyframes svg-link-ele-selected { diff --git a/web/regression/javascript/erd/erd_core_spec.js b/web/regression/javascript/erd/erd_core_spec.js index c42d4732b..b26a5fc05 100644 --- a/web/regression/javascript/erd/erd_core_spec.js +++ b/web/regression/javascript/erd/erd_core_spec.js @@ -304,7 +304,7 @@ describe('ERDCore', ()=>{ setTimeout(()=>{ expect(erdCoreObj.dagreDistributeNodes).toHaveBeenCalled(); done(); - }, 10); + }, 500); }); it('clearSelection', ()=>{ diff --git a/web/regression/javascript/erd/table_node_spec.js b/web/regression/javascript/erd/table_node_spec.js index 4818d2a7a..37d45e99b 100644 --- a/web/regression/javascript/erd/table_node_spec.js +++ b/web/regression/javascript/erd/table_node_spec.js @@ -275,13 +275,6 @@ describe('ERD TableNodeWidget', ()=>{ expect(nodeWidget.find('.table-node .table-cols .col-row').length).toBe(3); }); - it('icons', ()=>{ - let cols = nodeWidget.find('.table-node .table-cols .col-row-data'); - expect(cols.at(0).find('.wcTabIcon').hasClass('icon-primary_key')).toBeTruthy(); - expect(cols.at(1).find('.wcTabIcon').hasClass('icon-column')).toBeTruthy(); - expect(cols.at(2).find('.wcTabIcon').hasClass('icon-column')).toBeTruthy(); - }); - it('column names', ()=>{ let cols = nodeWidget.find('.table-node .table-cols .col-row-data'); expect(cols.at(0).find('.col-name').text()).toBe('id'); diff --git a/web/webpack.test.config.js b/web/webpack.test.config.js index 7cc1923e9..5ca7f52c0 100644 --- a/web/webpack.test.config.js +++ b/web/webpack.test.config.js @@ -44,6 +44,35 @@ module.exports = { }, { test: /\.css$/, use: [ 'style-loader', 'raw-loader' ], + }, { + test: /\.(jpe?g|png|gif|svg)$/i, + loaders: [{ + loader: 'url-loader', + options: { + emitFile: true, + name: 'img/[name].[ext]', + limit: 4096, + }, + }, { + loader: 'image-webpack-loader', + query: { + bypassOnDebug: true, + mozjpeg: { + progressive: true, + }, + gifsicle: { + interlaced: false, + }, + optipng: { + optimizationLevel: 7, + }, + pngquant: { + quality: '75-90', + speed: 3, + }, + }, + }], + exclude: /vendor/, }, { test: /.*slickgrid[\\\/]+slick\.(?!core)*/, loader: 'imports-loader?' +