Fixed following issues in ERD:
1) After opening an existing project, the first table is already selected but the edit, clone, delete buttons are disabled. 2) ERD project title gets changed when 2 ERD projects are open & anyone of it edited. 3) Closing the ERD tab does not ask for a confirmation pop-up. 4) Shortcut for 'Show more/Fewer details' is missing. 5) Deleting the primary key does not delete associated links. 6) The long table & schema name are getting out of the box. 7) The long table name in the notes pop-up needs re-alignment. 8) The same table name present in ERD/canvas is allowed in Add Table dialogue. Added validation in the dialog. 9) Download image option is added, but it is not perfect yet. Image icons (table, schema, etc.) are not showing up. 10) Rename panel option should be disabled by default. It should be enabled for the tools which implement rename functionality. 11) The Toolbar is not visible in Safari for the ERD tool. refs #1802pull/39/head
parent
446c2a19a5
commit
13db981445
|
@ -46,6 +46,7 @@
|
||||||
"prop-types": "^15.7.2",
|
"prop-types": "^15.7.2",
|
||||||
"raw-loader": "^3.1.0",
|
"raw-loader": "^3.1.0",
|
||||||
"resize-observer-polyfill": "^1.5.1",
|
"resize-observer-polyfill": "^1.5.1",
|
||||||
|
"resolve-url-loader": "^3.1.2",
|
||||||
"sass": "^1.24.4",
|
"sass": "^1.24.4",
|
||||||
"sass-loader": "^7.1.0",
|
"sass-loader": "^7.1.0",
|
||||||
"sass-resources-loader": "^2.0.0",
|
"sass-resources-loader": "^2.0.0",
|
||||||
|
@ -87,6 +88,7 @@
|
||||||
"dagre": "^0.8.4",
|
"dagre": "^0.8.4",
|
||||||
"dropzone": "^5.5.1",
|
"dropzone": "^5.5.1",
|
||||||
"exports-loader": "~0.7.0",
|
"exports-loader": "~0.7.0",
|
||||||
|
"html2canvas": "^1.0.0-rc.7",
|
||||||
"immutability-helper": "^3.0.0",
|
"immutability-helper": "^3.0.0",
|
||||||
"imports-loader": "^0.8.0",
|
"imports-loader": "^0.8.0",
|
||||||
"ip-address": "^5.8.9",
|
"ip-address": "^5.8.9",
|
||||||
|
|
|
@ -30,7 +30,7 @@ define([
|
||||||
height: 600,
|
height: 600,
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
isClosable: true,
|
isClosable: true,
|
||||||
isRenamable: true,
|
isRenamable: false,
|
||||||
isPrivate: false,
|
isPrivate: false,
|
||||||
url: '',
|
url: '',
|
||||||
icon: '',
|
icon: '',
|
||||||
|
|
|
@ -41,11 +41,11 @@ export default function BaseChart({type='line', id, options, data, redraw=false,
|
||||||
options: optionsMerged,
|
options: optionsMerged,
|
||||||
});
|
});
|
||||||
props.onInit && props.onInit(chartObj.current);
|
props.onInit && props.onInit(chartObj.current);
|
||||||
}
|
};
|
||||||
|
|
||||||
const destroyChart = function() {
|
const destroyChart = function() {
|
||||||
chartObj.current && chartObj.current.destroy();
|
chartObj.current && chartObj.current.destroy();
|
||||||
}
|
};
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
initChart();
|
initChart();
|
||||||
|
@ -72,7 +72,7 @@ export default function BaseChart({type='line', id, options, data, redraw=false,
|
||||||
destroyChart();
|
destroyChart();
|
||||||
initChart();
|
initChart();
|
||||||
}
|
}
|
||||||
}, [redraw])
|
}, [redraw]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<canvas id={id} ref={chartRef}></canvas>
|
<canvas id={id} ref={chartRef}></canvas>
|
||||||
|
|
|
@ -180,7 +180,7 @@ define('pgadmin.datagrid', [
|
||||||
name: 'frm_datagrid',
|
name: 'frm_datagrid',
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
isCloseable: true,
|
isCloseable: true,
|
||||||
isRenameable: true,
|
isRenamable: true,
|
||||||
isPrivate: true,
|
isPrivate: true,
|
||||||
url: 'about:blank',
|
url: 'about:blank',
|
||||||
});
|
});
|
||||||
|
|
|
@ -78,11 +78,11 @@ export function setQueryToolDockerTitle(panel, is_query_tool, panel_title, is_fi
|
||||||
|
|
||||||
export function set_renamable_option(panel, is_file) {
|
export function set_renamable_option(panel, is_file) {
|
||||||
if(is_file || is_file == 'true') {
|
if(is_file || is_file == 'true') {
|
||||||
panel._isRenamable = false;
|
panel.renamable(false);
|
||||||
$('.conn-info-dd').hide();
|
$('.conn-info-dd').hide();
|
||||||
$('.connection-data').css({pointerEvents: 'none', cursor: 'arrow'});
|
$('.connection-data').css({pointerEvents: 'none', cursor: 'arrow'});
|
||||||
} else {
|
} else {
|
||||||
panel._isRenamable = true;
|
panel.renamable(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -288,6 +288,24 @@ class ERDModule(PgAdminModule):
|
||||||
fields=shortcut_fields
|
fields=shortcut_fields
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.preference.register(
|
||||||
|
'keyboard_shortcuts',
|
||||||
|
'show_details',
|
||||||
|
gettext('Show more/fewer details'),
|
||||||
|
'keyboardshortcut',
|
||||||
|
{
|
||||||
|
'alt': True,
|
||||||
|
'shift': False,
|
||||||
|
'control': True,
|
||||||
|
'key': {
|
||||||
|
'key_code': 84,
|
||||||
|
'char': 't'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
category_label=PREF_LABEL_KEYBOARD_SHORTCUTS,
|
||||||
|
fields=shortcut_fields
|
||||||
|
)
|
||||||
|
|
||||||
self.preference.register(
|
self.preference.register(
|
||||||
'keyboard_shortcuts',
|
'keyboard_shortcuts',
|
||||||
'zoom_to_fit',
|
'zoom_to_fit',
|
||||||
|
|
|
@ -212,14 +212,14 @@ export default class ERDCore {
|
||||||
let sourcePort = sourceNode.getPort(portName);
|
let sourcePort = sourceNode.getPort(portName);
|
||||||
/* Create the port if not there */
|
/* Create the port if not there */
|
||||||
if(!sourcePort) {
|
if(!sourcePort) {
|
||||||
sourcePort = sourceNode.addPort(this.getNewPort(type, null, {name:portName, alignment:PortModelAlignment.RIGHT}));
|
sourcePort = sourceNode.addPort(this.getNewPort(type, null, {name:portName, subtype: 'one', alignment:PortModelAlignment.RIGHT}));
|
||||||
}
|
}
|
||||||
|
|
||||||
portName = targetNode.getPortName(data.local_column_attnum);
|
portName = targetNode.getPortName(data.local_column_attnum);
|
||||||
let targetPort = targetNode.getPort(portName);
|
let targetPort = targetNode.getPort(portName);
|
||||||
/* Create the port if not there */
|
/* Create the port if not there */
|
||||||
if(!targetPort) {
|
if(!targetPort) {
|
||||||
targetPort = targetNode.addPort(this.getNewPort(type, null, {name:portName, alignment:PortModelAlignment.RIGHT}));
|
targetPort = targetNode.addPort(this.getNewPort(type, null, {name:portName, subtype: 'many', alignment:PortModelAlignment.RIGHT}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Link the ports */
|
/* Link the ports */
|
||||||
|
|
|
@ -50,7 +50,7 @@ export default class TableDialog {
|
||||||
return 'entity_dialog';
|
return 'entity_dialog';
|
||||||
}
|
}
|
||||||
|
|
||||||
getDataModel(attributes, colTypes, schemas, sVersion) {
|
getDataModel(attributes, existingTables, colTypes, schemas, sVersion) {
|
||||||
let dialogObj = this;
|
let dialogObj = this;
|
||||||
let columnsModel = this.pgBrowser.DataModel.extend({
|
let columnsModel = this.pgBrowser.DataModel.extend({
|
||||||
idAttribute: 'attnum',
|
idAttribute: 'attnum',
|
||||||
|
@ -694,6 +694,10 @@ export default class TableDialog {
|
||||||
msg = gettext('Table name cannot be empty.');
|
msg = gettext('Table name cannot be empty.');
|
||||||
this.errorModel.set('name', msg);
|
this.errorModel.set('name', msg);
|
||||||
return msg;
|
return msg;
|
||||||
|
} else if(_.findIndex(existingTables, (table)=>table[0]==schema&&table[1]==name) >= 0) {
|
||||||
|
msg = gettext('Table name already exists.');
|
||||||
|
this.errorModel.set('name', msg);
|
||||||
|
return msg;
|
||||||
}
|
}
|
||||||
this.errorModel.unset('name');
|
this.errorModel.unset('name');
|
||||||
if (
|
if (
|
||||||
|
@ -705,6 +709,8 @@ export default class TableDialog {
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
this.errorModel.unset('schema');
|
this.errorModel.unset('schema');
|
||||||
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -731,9 +737,9 @@ export default class TableDialog {
|
||||||
return Alertify[dialogName];
|
return Alertify[dialogName];
|
||||||
}
|
}
|
||||||
|
|
||||||
show(title, attributes, colTypes, schemas, sVersion, callback) {
|
show(title, attributes, existingTables, colTypes, schemas, sVersion, callback) {
|
||||||
let dialogTitle = title || gettext('Unknown');
|
let dialogTitle = title || gettext('Unknown');
|
||||||
const dialog = this.createOrGetDialog('table_dialog');
|
const dialog = this.createOrGetDialog('table_dialog');
|
||||||
dialog(dialogTitle, this.getDataModel(attributes, colTypes, schemas, sVersion), callback).resizeTo(this.pgBrowser.stdW.md, this.pgBrowser.stdH.md);
|
dialog(dialogTitle, this.getDataModel(attributes, existingTables, colTypes, schemas, sVersion), callback).resizeTo(this.pgBrowser.stdW.md, this.pgBrowser.stdH.md);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,13 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
import BodyWidget from './ui_components/BodyWidget';
|
import BodyWidget from './ui_components/BodyWidget';
|
||||||
import getDialog, {transformToSupported} from './dialogs';
|
import getDialog, {transformToSupported} from './dialogs';
|
||||||
import Alertify from 'pgadmin.alertifyjs';
|
import Alertify from 'pgadmin.alertifyjs';
|
||||||
import pgWindow from 'sources/window';
|
import pgWindow from 'sources/window';
|
||||||
|
import pgAdmin from 'sources/pgadmin';
|
||||||
|
|
||||||
export default class ERDTool {
|
export default class ERDTool {
|
||||||
constructor(container, params) {
|
constructor(container, params) {
|
||||||
|
@ -20,10 +23,28 @@ export default class ERDTool {
|
||||||
this.params = params;
|
this.params = params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getPreferencesForModule() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
/* Mount the React ERD tool to the container */
|
/* Mount the React ERD tool to the container */
|
||||||
|
let panel = null;
|
||||||
|
_.each(pgWindow.pgAdmin.Browser.docker.findPanels('frm_erdtool'), function(p) {
|
||||||
|
if (p.isVisible()) {
|
||||||
|
panel = p;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<BodyWidget params={this.params} getDialog={getDialog} transformToSupported={transformToSupported} pgAdmin={pgWindow.pgAdmin} alertify={Alertify} />,
|
<BodyWidget
|
||||||
|
params={this.params}
|
||||||
|
getDialog={getDialog}
|
||||||
|
transformToSupported={transformToSupported}
|
||||||
|
pgWindow={pgWindow}
|
||||||
|
pgAdmin={pgAdmin}
|
||||||
|
panel={panel}
|
||||||
|
alertify={Alertify} />,
|
||||||
this.container
|
this.container
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,12 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {
|
import {
|
||||||
RightAngleLinkModel,
|
RightAngleLinkModel,
|
||||||
RightAngleLinkWidget,
|
RightAngleLinkWidget,
|
||||||
DefaultLinkFactory,
|
DefaultLinkFactory,
|
||||||
PortModelAlignment,
|
PortModelAlignment,
|
||||||
LinkWidget,
|
LinkWidget,
|
||||||
PointModel
|
PointModel,
|
||||||
} from '@projectstorm/react-diagrams';
|
} from '@projectstorm/react-diagrams';
|
||||||
import {Point} from '@projectstorm/geometry';
|
import {Point} from '@projectstorm/geometry';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
@ -24,7 +24,7 @@ export const OneToManyModel = {
|
||||||
local_column_attnum: undefined,
|
local_column_attnum: undefined,
|
||||||
referenced_table_uid: undefined,
|
referenced_table_uid: undefined,
|
||||||
referenced_column_attnum: undefined,
|
referenced_column_attnum: undefined,
|
||||||
}
|
};
|
||||||
|
|
||||||
export class OneToManyLinkModel extends RightAngleLinkModel {
|
export class OneToManyLinkModel extends RightAngleLinkModel {
|
||||||
constructor({data, ...options}) {
|
constructor({data, ...options}) {
|
||||||
|
@ -33,7 +33,7 @@ export class OneToManyLinkModel extends RightAngleLinkModel {
|
||||||
width: 1,
|
width: 1,
|
||||||
class: 'link-onetomany',
|
class: 'link-onetomany',
|
||||||
locked: true,
|
locked: true,
|
||||||
...options
|
...options,
|
||||||
});
|
});
|
||||||
|
|
||||||
this._data = {
|
this._data = {
|
||||||
|
@ -62,13 +62,13 @@ export class OneToManyLinkModel extends RightAngleLinkModel {
|
||||||
'local_column': _.find(target.columns, (col)=>data.local_column_attnum == col.attnum).name,
|
'local_column': _.find(target.columns, (col)=>data.local_column_attnum == col.attnum).name,
|
||||||
'referenced': _.find(source.columns, (col)=>data.referenced_column_attnum == col.attnum).name,
|
'referenced': _.find(source.columns, (col)=>data.referenced_column_attnum == col.attnum).name,
|
||||||
}],
|
}],
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
serialize() {
|
serialize() {
|
||||||
return {
|
return {
|
||||||
...super.serialize(),
|
...super.serialize(),
|
||||||
data: this.getData()
|
data: this.getData(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,13 +83,13 @@ const CustomLinkEndWidget = props => {
|
||||||
<circle className="svg-link-ele svg-otom-circle" cx="0" cy="16" r={props.width*1.75} strokeWidth={props.width} />
|
<circle className="svg-link-ele svg-otom-circle" cx="0" cy="16" r={props.width*1.75} strokeWidth={props.width} />
|
||||||
<polyline className="svg-link-ele" points="-8,0 0,15 0,0 0,30 0,15 8,0" fill="none" strokeWidth={props.width} />
|
<polyline className="svg-link-ele" points="-8,0 0,15 0,0 0,30 0,15 8,0" fill="none" strokeWidth={props.width} />
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
} else if (type == 'one') {
|
} else if (type == 'one') {
|
||||||
return (
|
return (
|
||||||
<polyline className="svg-link-ele" points="-8,15 0,15 0,0 0,30 0,15 8,15" fill="none" strokeWidth={props.width} />
|
<polyline className="svg-link-ele" points="-8,15 0,15 0,0 0,30 0,15 8,15" fill="none" strokeWidth={props.width} />
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<g transform={'translate(' + point.getPosition().x + ', ' + point.getPosition().y + ')'}>
|
<g transform={'translate(' + point.getPosition().x + ', ' + point.getPosition().y + ')'}>
|
||||||
|
@ -111,21 +111,21 @@ export class OneToManyLinkWidget extends RightAngleLinkWidget {
|
||||||
let degree = 0;
|
let degree = 0;
|
||||||
let tx = 0, ty = 0;
|
let tx = 0, ty = 0;
|
||||||
switch(alignment) {
|
switch(alignment) {
|
||||||
case PortModelAlignment.BOTTOM:
|
case PortModelAlignment.BOTTOM:
|
||||||
ty = -offset;
|
ty = -offset;
|
||||||
break;
|
break;
|
||||||
case PortModelAlignment.LEFT:
|
case PortModelAlignment.LEFT:
|
||||||
degree = 90;
|
degree = 90;
|
||||||
tx = offset
|
tx = offset;
|
||||||
break;
|
break;
|
||||||
case PortModelAlignment.TOP:
|
case PortModelAlignment.TOP:
|
||||||
degree = 180;
|
degree = 180;
|
||||||
ty = offset;
|
ty = offset;
|
||||||
break;
|
break;
|
||||||
case PortModelAlignment.RIGHT:
|
case PortModelAlignment.RIGHT:
|
||||||
degree = -90;
|
degree = -90;
|
||||||
tx = -offset;
|
tx = -offset;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return [degree, tx, ty];
|
return [degree, tx, ty];
|
||||||
}
|
}
|
||||||
|
@ -146,8 +146,8 @@ export class OneToManyLinkWidget extends RightAngleLinkWidget {
|
||||||
point: point,
|
point: point,
|
||||||
rotation: rotation,
|
rotation: rotation,
|
||||||
tx: tx,
|
tx: tx,
|
||||||
ty: ty
|
ty: ty,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
generateCustomEndWidget({type, point, rotation, tx, ty}) {
|
generateCustomEndWidget({type, point, rotation, tx, ty}) {
|
||||||
|
@ -183,7 +183,7 @@ export class OneToManyLinkWidget extends RightAngleLinkWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMove = function(event) {
|
handleMove = function(event) {
|
||||||
this.props.link.getTargetPort()
|
this.props.link.getTargetPort();
|
||||||
this.draggingEvent(event, this.dragging_index);
|
this.draggingEvent(event, this.dragging_index);
|
||||||
this.props.link.fireEvent({}, 'positionChanged');
|
this.props.link.fireEvent({}, 'positionChanged');
|
||||||
}.bind(this);
|
}.bind(this);
|
||||||
|
@ -220,7 +220,7 @@ export class OneToManyLinkWidget extends RightAngleLinkWidget {
|
||||||
this.props.link.addPoint(
|
this.props.link.addPoint(
|
||||||
new PointModel({
|
new PointModel({
|
||||||
link: this.props.link,
|
link: this.props.link,
|
||||||
position: new Point(onePoint.point.getX(), manyPoint.point.getY())
|
position: new Point(onePoint.point.getX(), manyPoint.point.getY()),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -246,7 +246,7 @@ export class OneToManyLinkWidget extends RightAngleLinkWidget {
|
||||||
onMouseEnter: (event) => {
|
onMouseEnter: (event) => {
|
||||||
this.setState({ selected: true });
|
this.setState({ selected: true });
|
||||||
this.props.link.lastHoverIndexOfPath = j;
|
this.props.link.lastHoverIndexOfPath = j;
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
j
|
j
|
||||||
)
|
)
|
||||||
|
|
|
@ -19,7 +19,7 @@ export class TableNodeModel extends DefaultNodeModel {
|
||||||
constructor({otherInfo, ...options}) {
|
constructor({otherInfo, ...options}) {
|
||||||
super({
|
super({
|
||||||
...options,
|
...options,
|
||||||
type: TYPE
|
type: TYPE,
|
||||||
});
|
});
|
||||||
|
|
||||||
this._note = otherInfo.note || '';
|
this._note = otherInfo.note || '';
|
||||||
|
@ -60,22 +60,22 @@ export class TableNodeModel extends DefaultNodeModel {
|
||||||
|
|
||||||
cloneData(name) {
|
cloneData(name) {
|
||||||
let newData = {
|
let newData = {
|
||||||
...this.getData()
|
...this.getData(),
|
||||||
};
|
};
|
||||||
if(name) {
|
if(name) {
|
||||||
newData['name'] = name
|
newData['name'] = name;
|
||||||
}
|
}
|
||||||
return newData;
|
return newData;
|
||||||
}
|
}
|
||||||
|
|
||||||
setData(data) {
|
setData(data) {
|
||||||
let self = this;
|
let self = this;
|
||||||
/* Remove the links if column dropped */
|
/* Remove the links if column dropped or primary key removed */
|
||||||
_.differenceWith(this._data.columns, data.columns, function(existing, incoming) {
|
_.differenceWith(this._data.columns, data.columns, function(existing, incoming) {
|
||||||
return existing.attnum == incoming.attnum;
|
return existing.attnum == incoming.attnum && incoming.is_primary_key == true;
|
||||||
}).forEach((col)=>{
|
}).forEach((col)=>{
|
||||||
let existPort = self.getPort(self.getPortName(col.attnum));
|
let existPort = self.getPort(self.getPortName(col.attnum));
|
||||||
if(existPort) {
|
if(existPort && existPort.getSubtype() == 'one') {
|
||||||
existPort.removeAllLinks();
|
existPort.removeAllLinks();
|
||||||
self.removePort(existPort);
|
self.removePort(existPort);
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,7 @@ export class TableNodeModel extends DefaultNodeModel {
|
||||||
otherInfo: {
|
otherInfo: {
|
||||||
data: this.getData(),
|
data: this.getData(),
|
||||||
note: this.getNote(),
|
note: this.getNote(),
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,8 +119,8 @@ export class TableNodeWidget extends React.Component {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
show_details: true
|
show_details: true,
|
||||||
}
|
};
|
||||||
|
|
||||||
this.props.node.registerListener({
|
this.props.node.registerListener({
|
||||||
toggleDetails: (event) => {
|
toggleDetails: (event) => {
|
||||||
|
@ -143,13 +143,13 @@ export class TableNodeWidget extends React.Component {
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-auto col-row-port">{this.generatePort(port)}</div>
|
<div className="ml-auto col-row-port">{this.generatePort(port)}</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
generatePort = port => {
|
generatePort = port => {
|
||||||
if(port) {
|
if(port) {
|
||||||
return (
|
return (
|
||||||
<PortWidget engine={this.props.engine} port={port} key={port.getID()} className={"port-" + port.options.alignment} />
|
<PortWidget engine={this.props.engine} port={port} key={port.getID()} className={'port-' + port.options.alignment} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return <></>;
|
return <></>;
|
||||||
|
@ -163,21 +163,21 @@ export class TableNodeWidget extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
let node_data = this.props.node.getData();
|
let node_data = this.props.node.getData();
|
||||||
return (
|
return (
|
||||||
<div className={"table-node " + (this.props.node.isSelected() ? 'selected': '') } onDoubleClick={()=>{this.props.node.fireEvent({}, 'editNode')}}>
|
<div className={'table-node ' + (this.props.node.isSelected() ? 'selected': '') } onDoubleClick={()=>{this.props.node.fireEvent({}, 'editNode');}}>
|
||||||
<div className="table-toolbar">
|
<div className="table-toolbar">
|
||||||
<DetailsToggleButton className='btn-xs' showDetails={this.state.show_details} onClick={this.toggleShowDetails} onDoubleClick={(e)=>{e.stopPropagation();}} />
|
<DetailsToggleButton className='btn-xs' showDetails={this.state.show_details} onClick={this.toggleShowDetails} onDoubleClick={(e)=>{e.stopPropagation();}} />
|
||||||
{this.props.node.getNote() &&
|
{this.props.node.getNote() &&
|
||||||
<IconButton icon="far fa-sticky-note" className="btn-xs btn-warning ml-auto" onClick={()=>{
|
<IconButton icon="far fa-sticky-note" className="btn-xs btn-warning ml-auto" onClick={()=>{
|
||||||
this.props.node.fireEvent({}, 'showNote')
|
this.props.node.fireEvent({}, 'showNote');
|
||||||
}} title="Check note" />}
|
}} title="Check note" />}
|
||||||
</div>
|
</div>
|
||||||
<div className="table-schema">
|
<div className="d-flex table-schema-data">
|
||||||
<span className="wcTabIcon icon-schema"></span>
|
<div className="table-icon-schema"></div>
|
||||||
{node_data.schema}
|
<div className="table-schema">{node_data.schema}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="table-name">
|
<div className="d-flex table-name-data">
|
||||||
<span className="wcTabIcon icon-table"></span>
|
<div><span className="wcTabIcon icon-table"></span></div>
|
||||||
{node_data.name}
|
<div className="table-name">{node_data.name}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="table-cols">
|
<div className="table-cols">
|
||||||
{_.map(node_data.columns, (col)=>this.generateColumn(col))}
|
{_.map(node_data.columns, (col)=>this.generateColumn(col))}
|
||||||
|
|
|
@ -16,6 +16,7 @@ const TYPE = 'onetomany';
|
||||||
export default class OneToManyPortModel extends PortModel {
|
export default class OneToManyPortModel extends PortModel {
|
||||||
constructor({options}) {
|
constructor({options}) {
|
||||||
super({
|
super({
|
||||||
|
subtype: 'notset',
|
||||||
...options,
|
...options,
|
||||||
type: TYPE,
|
type: TYPE,
|
||||||
});
|
});
|
||||||
|
@ -30,6 +31,22 @@ export default class OneToManyPortModel extends PortModel {
|
||||||
createLinkModel() {
|
createLinkModel() {
|
||||||
return new OneToManyLinkModel({});
|
return new OneToManyLinkModel({});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getSubtype() {
|
||||||
|
return this.options.subtype;
|
||||||
|
}
|
||||||
|
|
||||||
|
deserialize(event) {
|
||||||
|
super.deserialize(event);
|
||||||
|
this.options.subtype = event.data.subtype || 'notset';
|
||||||
|
}
|
||||||
|
|
||||||
|
serialize() {
|
||||||
|
return {
|
||||||
|
...super.serialize(),
|
||||||
|
subtype: this.options.subtype,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class OneToManyPortFactory extends AbstractModelFactory {
|
export class OneToManyPortFactory extends AbstractModelFactory {
|
||||||
|
|
|
@ -12,6 +12,8 @@ import { CanvasWidget } from '@projectstorm/react-canvas-core';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { Action, InputType } from '@projectstorm/react-canvas-core';
|
import { Action, InputType } from '@projectstorm/react-canvas-core';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import _ from 'lodash';
|
||||||
|
import html2canvas from 'html2canvas';
|
||||||
|
|
||||||
import ERDCore from '../ERDCore';
|
import ERDCore from '../ERDCore';
|
||||||
import ToolBar, {IconButton, DetailsToggleButton, ButtonGroup} from './ToolBar';
|
import ToolBar, {IconButton, DetailsToggleButton, ButtonGroup} from './ToolBar';
|
||||||
|
@ -22,22 +24,25 @@ import {setPanelTitle} from '../../erd_module';
|
||||||
import gettext from 'sources/gettext';
|
import gettext from 'sources/gettext';
|
||||||
import url_for from 'sources/url_for';
|
import url_for from 'sources/url_for';
|
||||||
import {showERDSqlTool} from 'tools/datagrid/static/js/show_query_tool';
|
import {showERDSqlTool} from 'tools/datagrid/static/js/show_query_tool';
|
||||||
|
import 'wcdocker';
|
||||||
|
|
||||||
/* Custom react-diagram action for keyboard events */
|
/* Custom react-diagram action for keyboard events */
|
||||||
export class KeyboardShortcutAction extends Action {
|
export class KeyboardShortcutAction extends Action {
|
||||||
constructor(shortcut_handlers=[]) {
|
constructor(shortcut_handlers=[]) {
|
||||||
super({
|
super({
|
||||||
type: InputType.KEY_DOWN,
|
type: InputType.KEY_DOWN,
|
||||||
fire: ({ event })=>{
|
fire: ({ event })=>{
|
||||||
this.callHandler(event);
|
this.callHandler(event);
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
this.shortcuts = {};
|
this.shortcuts = {};
|
||||||
|
|
||||||
for(let i=0; i<shortcut_handlers.length; i++){
|
for(let i=0; i<shortcut_handlers.length; i++){
|
||||||
let [key, handler] = shortcut_handlers[i];
|
let [key, handler] = shortcut_handlers[i];
|
||||||
|
if(key) {
|
||||||
this.shortcuts[this.shortcutKey(key.alt, key.control, key.shift, false, key.key.key_code)] = handler;
|
this.shortcuts[this.shortcutKey(key.alt, key.control, key.shift, false, key.key.key_code)] = handler;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shortcutKey(altKey, ctrlKey, shiftKey, metaKey, keyCode) {
|
shortcutKey(altKey, ctrlKey, shiftKey, metaKey, keyCode) {
|
||||||
|
@ -69,9 +74,12 @@ export default class BodyWidget extends React.Component {
|
||||||
current_file: null,
|
current_file: null,
|
||||||
dirty: false,
|
dirty: false,
|
||||||
show_details: true,
|
show_details: true,
|
||||||
|
is_new_tab: false,
|
||||||
preferences: {},
|
preferences: {},
|
||||||
}
|
};
|
||||||
this.diagram = new ERDCore();
|
this.diagram = new ERDCore();
|
||||||
|
/* Flag for checking if user has opted for save before close */
|
||||||
|
this.closeOnSave = React.createRef();
|
||||||
this.fileInputRef = React.createRef();
|
this.fileInputRef = React.createRef();
|
||||||
this.diagramContainerRef = React.createRef();
|
this.diagramContainerRef = React.createRef();
|
||||||
this.canvasEle = null;
|
this.canvasEle = null;
|
||||||
|
@ -83,6 +91,7 @@ export default class BodyWidget extends React.Component {
|
||||||
this.onSaveDiagram = this.onSaveDiagram.bind(this);
|
this.onSaveDiagram = this.onSaveDiagram.bind(this);
|
||||||
this.onSaveAsDiagram = this.onSaveAsDiagram.bind(this);
|
this.onSaveAsDiagram = this.onSaveAsDiagram.bind(this);
|
||||||
this.onSQLClick = this.onSQLClick.bind(this);
|
this.onSQLClick = this.onSQLClick.bind(this);
|
||||||
|
this.onImageClick = this.onImageClick.bind(this);
|
||||||
this.onAddNewNode = this.onAddNewNode.bind(this);
|
this.onAddNewNode = this.onAddNewNode.bind(this);
|
||||||
this.onEditNode = this.onEditNode.bind(this);
|
this.onEditNode = this.onEditNode.bind(this);
|
||||||
this.onCloneNode = this.onCloneNode.bind(this);
|
this.onCloneNode = this.onCloneNode.bind(this);
|
||||||
|
@ -133,7 +142,7 @@ export default class BodyWidget extends React.Component {
|
||||||
},
|
},
|
||||||
'editNode': (event) => {
|
'editNode': (event) => {
|
||||||
this.addEditNode(event.node);
|
this.addEditNode(event.node);
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
Object.keys(diagramEvents).forEach(eventName => {
|
Object.keys(diagramEvents).forEach(eventName => {
|
||||||
this.diagram.registerModelEvent(eventName, diagramEvents[eventName]);
|
this.diagram.registerModelEvent(eventName, diagramEvents[eventName]);
|
||||||
|
@ -157,9 +166,10 @@ export default class BodyWidget extends React.Component {
|
||||||
[this.state.preferences.one_to_many, this.onOneToManyClick],
|
[this.state.preferences.one_to_many, this.onOneToManyClick],
|
||||||
[this.state.preferences.many_to_many, this.onManyToManyClick],
|
[this.state.preferences.many_to_many, this.onManyToManyClick],
|
||||||
[this.state.preferences.auto_align, this.onAutoDistribute],
|
[this.state.preferences.auto_align, this.onAutoDistribute],
|
||||||
|
[this.state.preferences.show_details, this.onDetailsToggle],
|
||||||
[this.state.preferences.zoom_to_fit, this.diagram.zoomToFit],
|
[this.state.preferences.zoom_to_fit, this.diagram.zoomToFit],
|
||||||
[this.state.preferences.zoom_in, this.diagram.zoomIn],
|
[this.state.preferences.zoom_in, this.diagram.zoomIn],
|
||||||
[this.state.preferences.zoom_out, this.diagram.zoomOut]
|
[this.state.preferences.zoom_out, this.diagram.zoomOut],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
this.diagram.registerKeyAction(this.keyboardActionObj);
|
this.diagram.registerKeyAction(this.keyboardActionObj);
|
||||||
|
@ -182,11 +192,16 @@ export default class BodyWidget extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
this.setLoading('Preparing');
|
this.setLoading(gettext('Preparing...'));
|
||||||
this.setTitle(this.state.current_file);
|
|
||||||
this.setState({
|
this.setState({
|
||||||
preferences: this.props.pgAdmin.Browser.get_preferences_for_module('erd')
|
preferences: this.props.pgWindow.pgAdmin.Browser.get_preferences_for_module('erd'),
|
||||||
}, this.registerKeyboardShortcuts);
|
is_new_tab: (this.props.pgWindow.pgAdmin.Browser.get_preferences_for_module('browser').new_browser_tab_open || '')
|
||||||
|
.includes('erd_tool'),
|
||||||
|
}, ()=>{
|
||||||
|
this.registerKeyboardShortcuts();
|
||||||
|
this.setTitle(this.state.current_file);
|
||||||
|
});
|
||||||
this.registerModelEvents();
|
this.registerModelEvents();
|
||||||
this.realignGrid({
|
this.realignGrid({
|
||||||
backgroundSize: '45px 45px',
|
backgroundSize: '45px 45px',
|
||||||
|
@ -197,10 +212,19 @@ export default class BodyWidget extends React.Component {
|
||||||
this.props.pgAdmin.Browser.Events.on('pgadmin-storage:finish_btn:create_file', this.saveFile, this);
|
this.props.pgAdmin.Browser.Events.on('pgadmin-storage:finish_btn:create_file', this.saveFile, this);
|
||||||
this.props.pgAdmin.Browser.onPreferencesChange('erd', () => {
|
this.props.pgAdmin.Browser.onPreferencesChange('erd', () => {
|
||||||
this.setState({
|
this.setState({
|
||||||
preferences: this.props.pgAdmin.Browser.get_preferences_for_module('erd')
|
preferences: this.props.pgWindow.pgAdmin.Browser.get_preferences_for_module('erd'),
|
||||||
}, ()=>this.registerKeyboardShortcuts());
|
}, ()=>this.registerKeyboardShortcuts());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.props.panel?.on(window.wcDocker?.EVENT.CLOSING, () => {
|
||||||
|
if(this.state.dirty) {
|
||||||
|
this.closeOnSave = false;
|
||||||
|
this.confirmBeforeClose();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
let done = await this.initConnection();
|
let done = await this.initConnection();
|
||||||
if(!done) return;
|
if(!done) return;
|
||||||
|
|
||||||
|
@ -218,18 +242,78 @@ export default class BodyWidget extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
confirmBeforeClose() {
|
||||||
|
let bodyObj = this;
|
||||||
|
this.props.alertify.confirmSave || this.props.alertify.dialog('confirmSave', function() {
|
||||||
|
return {
|
||||||
|
main: function(title, message) {
|
||||||
|
this.setHeader(title);
|
||||||
|
this.setContent(message);
|
||||||
|
},
|
||||||
|
setup: function() {
|
||||||
|
return {
|
||||||
|
buttons: [{
|
||||||
|
text: gettext('Cancel'),
|
||||||
|
key: 27, // ESC
|
||||||
|
invokeOnClose: true,
|
||||||
|
className: 'btn btn-secondary fa fa-lg fa-times pg-alertify-button',
|
||||||
|
}, {
|
||||||
|
text: gettext('Don\'t save'),
|
||||||
|
className: 'btn btn-secondary fa fa-lg fa-trash-alt pg-alertify-button',
|
||||||
|
}, {
|
||||||
|
text: gettext('Save'),
|
||||||
|
className: 'btn btn-primary fa fa-lg fa-save pg-alertify-button',
|
||||||
|
}],
|
||||||
|
focus: {
|
||||||
|
element: 0,
|
||||||
|
select: false,
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
maximizable: false,
|
||||||
|
resizable: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
callback: function(closeEvent) {
|
||||||
|
switch (closeEvent.index) {
|
||||||
|
case 0: // Cancel
|
||||||
|
//Do nothing.
|
||||||
|
break;
|
||||||
|
case 1: // Don't Save
|
||||||
|
bodyObj.closePanel();
|
||||||
|
break;
|
||||||
|
case 2: //Save
|
||||||
|
bodyObj.onSaveDiagram(false, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
this.props.alertify.confirmSave(gettext('Save changes?'), gettext('The diagram has changed. Do you want to save changes?'));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
closePanel() {
|
||||||
|
window.onbeforeunload = null;
|
||||||
|
this.props.panel.off(wcDocker.EVENT.CLOSING);
|
||||||
|
this.props.pgWindow.pgAdmin.Browser.docker.removePanel(this.props.panel);
|
||||||
|
}
|
||||||
|
|
||||||
getDialog(dialogName) {
|
getDialog(dialogName) {
|
||||||
if(dialogName === 'entity_dialog') {
|
if(dialogName === 'entity_dialog') {
|
||||||
|
let existingTables = this.diagram.getModel().getNodes().map((node)=>{
|
||||||
|
return node.getSchemaTableName();
|
||||||
|
});
|
||||||
return (title, attributes, callback)=>{
|
return (title, attributes, callback)=>{
|
||||||
this.props.getDialog(dialogName).show(
|
this.props.getDialog(dialogName).show(
|
||||||
title, attributes, this.diagram.getCache('colTypes'), this.diagram.getCache('schemas'), this.state.server_version, callback
|
title, attributes, existingTables, this.diagram.getCache('colTypes'), this.diagram.getCache('schemas'), this.state.server_version, callback
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
} else if(dialogName === 'onetomany_dialog' || dialogName === 'manytomany_dialog') {
|
} else if(dialogName === 'onetomany_dialog' || dialogName === 'manytomany_dialog') {
|
||||||
return (title, attributes, callback)=>{
|
return (title, attributes, callback)=>{
|
||||||
this.props.getDialog(dialogName).show(
|
this.props.getDialog(dialogName).show(
|
||||||
title, attributes, this.diagram.getModel().getNodesDict(), this.state.server_version, callback
|
title, attributes, this.diagram.getModel().getNodesDict(), this.state.server_version, callback
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -289,20 +373,20 @@ export default class BodyWidget extends React.Component {
|
||||||
gettext('Delete ?'),
|
gettext('Delete ?'),
|
||||||
gettext('You have selected %s tables and %s links.', this.diagram.getSelectedNodes().length, this.diagram.getSelectedLinks().length)
|
gettext('You have selected %s tables and %s links.', this.diagram.getSelectedNodes().length, this.diagram.getSelectedLinks().length)
|
||||||
+ '<br />' + gettext('Are you sure you want to delete ?'),
|
+ '<br />' + gettext('Are you sure you want to delete ?'),
|
||||||
() => {
|
() => {
|
||||||
this.diagram.getSelectedNodes().forEach((node)=>{
|
this.diagram.getSelectedNodes().forEach((node)=>{
|
||||||
node.setSelected(false);
|
node.setSelected(false);
|
||||||
node.remove();
|
node.remove();
|
||||||
});
|
});
|
||||||
this.diagram.getSelectedLinks().forEach((link)=>{
|
this.diagram.getSelectedLinks().forEach((link)=>{
|
||||||
link.getTargetPort().remove();
|
link.getTargetPort().remove();
|
||||||
link.getSourcePort().remove();
|
link.getSourcePort().remove();
|
||||||
link.setSelected(false);
|
link.setSelected(false);
|
||||||
link.remove();
|
link.remove();
|
||||||
});
|
});
|
||||||
this.diagram.repaint();
|
this.diagram.repaint();
|
||||||
},
|
},
|
||||||
() => {}
|
() => {}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,11 +396,11 @@ export default class BodyWidget extends React.Component {
|
||||||
|
|
||||||
onDetailsToggle() {
|
onDetailsToggle() {
|
||||||
this.setState((prevState)=>({
|
this.setState((prevState)=>({
|
||||||
show_details: !prevState.show_details
|
show_details: !prevState.show_details,
|
||||||
}), ()=>{
|
}), ()=>{
|
||||||
this.diagram.getModel().getNodes().forEach((node)=>{
|
this.diagram.getModel().getNodes().forEach((node)=>{
|
||||||
node.fireEvent({show_details: this.state.show_details}, 'toggleDetails');
|
node.fireEvent({show_details: this.state.show_details}, 'toggleDetails');
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,8 +419,9 @@ export default class BodyWidget extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
openFile(fileName) {
|
openFile(fileName) {
|
||||||
|
this.setLoading(gettext('Loading project...'));
|
||||||
axios.post(url_for('sqleditor.load_file'), {
|
axios.post(url_for('sqleditor.load_file'), {
|
||||||
'file_name': decodeURI(fileName)
|
'file_name': decodeURI(fileName),
|
||||||
}).then((res)=>{
|
}).then((res)=>{
|
||||||
this.setState({
|
this.setState({
|
||||||
current_file: fileName,
|
current_file: fileName,
|
||||||
|
@ -344,13 +429,17 @@ export default class BodyWidget extends React.Component {
|
||||||
});
|
});
|
||||||
this.setTitle(fileName);
|
this.setTitle(fileName);
|
||||||
this.diagram.deserialize(res.data);
|
this.diagram.deserialize(res.data);
|
||||||
|
this.diagram.clearSelection();
|
||||||
this.registerModelEvents();
|
this.registerModelEvents();
|
||||||
}).catch((err)=>{
|
}).catch((err)=>{
|
||||||
this.handleAxiosCatch(err);
|
this.handleAxiosCatch(err);
|
||||||
|
}).then(()=>{
|
||||||
|
this.setLoading(null);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onSaveDiagram(isSaveAs=false) {
|
onSaveDiagram(isSaveAs=false, closeOnSave=false) {
|
||||||
|
this.closeOnSave = closeOnSave;
|
||||||
if(this.state.current_file && !isSaveAs) {
|
if(this.state.current_file && !isSaveAs) {
|
||||||
this.saveFile(this.state.current_file);
|
this.saveFile(this.state.current_file);
|
||||||
} else {
|
} else {
|
||||||
|
@ -370,9 +459,10 @@ export default class BodyWidget extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
saveFile(fileName) {
|
saveFile(fileName) {
|
||||||
|
this.setLoading(gettext('Saving...'));
|
||||||
axios.post(url_for('sqleditor.save_file'), {
|
axios.post(url_for('sqleditor.save_file'), {
|
||||||
'file_name': decodeURI(fileName),
|
'file_name': decodeURI(fileName),
|
||||||
'file_content': JSON.stringify(this.diagram.serialize(this.props.pgAdmin.Browser.utils.app_version_int))
|
'file_content': JSON.stringify(this.diagram.serialize(this.props.pgAdmin.Browser.utils.app_version_int)),
|
||||||
}).then(()=>{
|
}).then(()=>{
|
||||||
this.props.alertify.success(gettext('Project saved successfully.'));
|
this.props.alertify.success(gettext('Project saved successfully.'));
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -380,7 +470,12 @@ export default class BodyWidget extends React.Component {
|
||||||
dirty: false,
|
dirty: false,
|
||||||
});
|
});
|
||||||
this.setTitle(fileName);
|
this.setTitle(fileName);
|
||||||
|
this.setLoading(null);
|
||||||
|
if(this.closeOnSave) {
|
||||||
|
this.closePanel.call(this);
|
||||||
|
}
|
||||||
}).catch((err)=>{
|
}).catch((err)=>{
|
||||||
|
this.setLoading(null);
|
||||||
this.handleAxiosCatch(err);
|
this.handleAxiosCatch(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -395,14 +490,10 @@ export default class BodyWidget extends React.Component {
|
||||||
title = 'Untitled';
|
title = 'Untitled';
|
||||||
}
|
}
|
||||||
title = this.getCurrentProjectName(title) + (dirty ? '*': '');
|
title = this.getCurrentProjectName(title) + (dirty ? '*': '');
|
||||||
if (this.new_browser_tab) {
|
if (this.state.is_new_tab) {
|
||||||
window.document.title = title;
|
window.document.title = title;
|
||||||
} else {
|
} else {
|
||||||
_.each(this.props.pgAdmin.Browser.docker.findPanels('frm_erdtool'), function(p) {
|
setPanelTitle(this.props.panel, title);
|
||||||
if (p.isVisible()) {
|
|
||||||
setPanelTitle(p, title);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,7 +505,7 @@ export default class BodyWidget extends React.Component {
|
||||||
trans_id: this.props.params.trans_id,
|
trans_id: this.props.params.trans_id,
|
||||||
sgid: this.props.params.sgid,
|
sgid: this.props.params.sgid,
|
||||||
sid: this.props.params.sid,
|
sid: this.props.params.sid,
|
||||||
did: this.props.params.did
|
did: this.props.params.did,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.setLoading(gettext('Preparing the SQL...'));
|
this.setLoading(gettext('Preparing the SQL...'));
|
||||||
|
@ -428,18 +519,53 @@ export default class BodyWidget extends React.Component {
|
||||||
sid: this.props.params.sid,
|
sid: this.props.params.sid,
|
||||||
did: this.props.params.did,
|
did: this.props.params.did,
|
||||||
stype: this.props.params.server_type,
|
stype: this.props.params.server_type,
|
||||||
}
|
};
|
||||||
|
|
||||||
let sqlId = `erd${this.props.params.trans_id}`;
|
let sqlId = `erd${this.props.params.trans_id}`;
|
||||||
localStorage.setItem(sqlId, sqlScript);
|
localStorage.setItem(sqlId, sqlScript);
|
||||||
showERDSqlTool(parentData, sqlId, this.props.params.title, this.props.pgAdmin.DataGrid, this.props.alertify);
|
showERDSqlTool(parentData, sqlId, this.props.params.title, this.props.pgWindow.pgAdmin.DataGrid, this.props.alertify);
|
||||||
})
|
})
|
||||||
.catch((error)=>{
|
.catch((error)=>{
|
||||||
this.handleAxiosCatch(error);
|
this.handleAxiosCatch(error);
|
||||||
})
|
})
|
||||||
.then(()=>{
|
.then(()=>{
|
||||||
this.setLoading(null);
|
this.setLoading(null);
|
||||||
})
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onImageClick() {
|
||||||
|
this.setLoading(gettext('Preparing the image...'));
|
||||||
|
|
||||||
|
/* Change the styles for suiting html2canvas */
|
||||||
|
this.canvasEle.classList.add('html2canvas-reset');
|
||||||
|
this.canvasEle.style.width = this.canvasEle.scrollWidth + 'px';
|
||||||
|
this.canvasEle.style.height = this.canvasEle.scrollHeight + 'px';
|
||||||
|
|
||||||
|
html2canvas(this.canvasEle, {
|
||||||
|
width: this.canvasEle.scrollWidth + 10,
|
||||||
|
height: this.canvasEle.scrollHeight + 10,
|
||||||
|
scrollX: 0,
|
||||||
|
scrollY: 0,
|
||||||
|
useCORS: true,
|
||||||
|
allowTaint: true,
|
||||||
|
backgroundColor: window.getComputedStyle(this.canvasEle).backgroundColor,
|
||||||
|
}).then((canvas)=>{
|
||||||
|
let link = document.createElement('a');
|
||||||
|
link.setAttribute('href', canvas.toDataURL('image/png'));
|
||||||
|
link.setAttribute('download', this.getCurrentProjectName() + '.png');
|
||||||
|
link.click();
|
||||||
|
}).catch((err)=>{
|
||||||
|
console.error(err);
|
||||||
|
this.props.alertify.alert()
|
||||||
|
.set('title', gettext('Error'))
|
||||||
|
.set('message', err).show();
|
||||||
|
}).then(()=>{
|
||||||
|
/* Revert back to the original CSS styles */
|
||||||
|
this.canvasEle.classList.remove('html2canvas-reset');
|
||||||
|
this.canvasEle.style.width = '';
|
||||||
|
this.canvasEle.style.height = '';
|
||||||
|
this.setLoading(null);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onOneToManyClick() {
|
onOneToManyClick() {
|
||||||
|
@ -473,8 +599,8 @@ export default class BodyWidget extends React.Component {
|
||||||
'name': `${right_table.getData().name}_${right_table.getColumnAt(newData.right_table_column_attnum).name}`,
|
'name': `${right_table.getData().name}_${right_table.getColumnAt(newData.right_table_column_attnum).name}`,
|
||||||
'is_primary_key': false,
|
'is_primary_key': false,
|
||||||
'attnum': 1,
|
'attnum': 1,
|
||||||
}]
|
}],
|
||||||
}
|
};
|
||||||
let newNode = this.diagram.addNode(tableData);
|
let newNode = this.diagram.addNode(tableData);
|
||||||
this.diagram.clearSelection();
|
this.diagram.clearSelection();
|
||||||
newNode.setSelected(true);
|
newNode.setSelected(true);
|
||||||
|
@ -484,7 +610,7 @@ export default class BodyWidget extends React.Component {
|
||||||
local_column_attnum: newNode.getColumns()[0].attnum,
|
local_column_attnum: newNode.getColumns()[0].attnum,
|
||||||
referenced_table_uid: newData.left_table_uid,
|
referenced_table_uid: newData.left_table_uid,
|
||||||
referenced_column_attnum : newData.left_table_column_attnum,
|
referenced_column_attnum : newData.left_table_column_attnum,
|
||||||
}
|
};
|
||||||
this.diagram.addLink(linkData, 'onetomany');
|
this.diagram.addLink(linkData, 'onetomany');
|
||||||
|
|
||||||
linkData = {
|
linkData = {
|
||||||
|
@ -492,7 +618,7 @@ export default class BodyWidget extends React.Component {
|
||||||
local_column_attnum: newNode.getColumns()[1].attnum,
|
local_column_attnum: newNode.getColumns()[1].attnum,
|
||||||
referenced_table_uid: newData.right_table_uid,
|
referenced_table_uid: newData.right_table_uid,
|
||||||
referenced_column_attnum : newData.right_table_column_attnum,
|
referenced_column_attnum : newData.right_table_column_attnum,
|
||||||
}
|
};
|
||||||
|
|
||||||
this.diagram.addLink(linkData, 'onetomany');
|
this.diagram.addLink(linkData, 'onetomany');
|
||||||
|
|
||||||
|
@ -505,7 +631,7 @@ export default class BodyWidget extends React.Component {
|
||||||
this.noteRefEle = this.diagram.getEngine().getNodeElement(noteNode);
|
this.noteRefEle = this.diagram.getEngine().getNodeElement(noteNode);
|
||||||
this.setState({
|
this.setState({
|
||||||
note_node: noteNode,
|
note_node: noteNode,
|
||||||
note_open: true
|
note_open: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -528,14 +654,14 @@ export default class BodyWidget extends React.Component {
|
||||||
trans_id: this.props.params.trans_id,
|
trans_id: this.props.params.trans_id,
|
||||||
sgid: this.props.params.sgid,
|
sgid: this.props.params.sgid,
|
||||||
sid: this.props.params.sid,
|
sid: this.props.params.sid,
|
||||||
did: this.props.params.did
|
did: this.props.params.did,
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let response = await axios.post(initUrl);
|
let response = await axios.post(initUrl);
|
||||||
this.setState({
|
this.setState({
|
||||||
conn_status: CONNECT_STATUS.CONNECTED,
|
conn_status: CONNECT_STATUS.CONNECTED,
|
||||||
server_version: response.data.data.serverVersion
|
server_version: response.data.data.serverVersion,
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -556,7 +682,7 @@ export default class BodyWidget extends React.Component {
|
||||||
trans_id: this.props.params.trans_id,
|
trans_id: this.props.params.trans_id,
|
||||||
sgid: this.props.params.sgid,
|
sgid: this.props.params.sgid,
|
||||||
sid: this.props.params.sid,
|
sid: this.props.params.sid,
|
||||||
did: this.props.params.did
|
did: this.props.params.did,
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -579,7 +705,7 @@ export default class BodyWidget extends React.Component {
|
||||||
trans_id: this.props.params.trans_id,
|
trans_id: this.props.params.trans_id,
|
||||||
sgid: this.props.params.sgid,
|
sgid: this.props.params.sgid,
|
||||||
sid: this.props.params.sid,
|
sid: this.props.params.sid,
|
||||||
did: this.props.params.did
|
did: this.props.params.did,
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -604,7 +730,7 @@ export default class BodyWidget extends React.Component {
|
||||||
<ButtonGroup>
|
<ButtonGroup>
|
||||||
<IconButton id="open-file" icon="fa fa-folder-open" onClick={this.onLoadDiagram} title={gettext('Load from file')}
|
<IconButton id="open-file" icon="fa fa-folder-open" onClick={this.onLoadDiagram} title={gettext('Load from file')}
|
||||||
shortcut={this.state.preferences.open_project}/>
|
shortcut={this.state.preferences.open_project}/>
|
||||||
<IconButton id="save-erd" icon="fa fa-save" onClick={()=>{this.onSaveDiagram()}} title={gettext('Save project')}
|
<IconButton id="save-erd" icon="fa fa-save" onClick={()=>{this.onSaveDiagram();}} title={gettext('Save project')}
|
||||||
shortcut={this.state.preferences.save_project} disabled={!this.state.dirty}/>
|
shortcut={this.state.preferences.save_project} disabled={!this.state.dirty}/>
|
||||||
<IconButton id="save-as-erd" icon="fa fa-share-square" onClick={this.onSaveAsDiagram} title={gettext('Save as')}
|
<IconButton id="save-as-erd" icon="fa fa-share-square" onClick={this.onSaveAsDiagram} title={gettext('Save as')}
|
||||||
shortcut={this.state.preferences.save_project_as}/>
|
shortcut={this.state.preferences.save_project_as}/>
|
||||||
|
@ -612,6 +738,8 @@ export default class BodyWidget extends React.Component {
|
||||||
<ButtonGroup>
|
<ButtonGroup>
|
||||||
<IconButton id="save-sql" icon="fa fa-file-code" onClick={this.onSQLClick} title={gettext('Generate SQL')}
|
<IconButton id="save-sql" icon="fa fa-file-code" onClick={this.onSQLClick} title={gettext('Generate SQL')}
|
||||||
shortcut={this.state.preferences.generate_sql}/>
|
shortcut={this.state.preferences.generate_sql}/>
|
||||||
|
<IconButton id="save-image" icon="fa fa-file-image" onClick={this.onImageClick} title={gettext('Generate SQL')}
|
||||||
|
shortcut={this.state.preferences.generate_sql}/>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
<ButtonGroup>
|
<ButtonGroup>
|
||||||
<IconButton id="add-node" icon="fa fa-plus-square" onClick={this.onAddNewNode} title={gettext('Add table')}
|
<IconButton id="add-node" icon="fa fa-plus-square" onClick={this.onAddNewNode} title={gettext('Add table')}
|
||||||
|
@ -634,7 +762,8 @@ export default class BodyWidget extends React.Component {
|
||||||
shortcut={this.state.preferences.add_edit_note} disabled={!this.state.single_node_selected || this.state.single_link_selected}/>
|
shortcut={this.state.preferences.add_edit_note} disabled={!this.state.single_node_selected || this.state.single_link_selected}/>
|
||||||
<IconButton id="auto-align" icon="fa fa-magic" onClick={this.onAutoDistribute} title={gettext('Auto align')}
|
<IconButton id="auto-align" icon="fa fa-magic" onClick={this.onAutoDistribute} title={gettext('Auto align')}
|
||||||
shortcut={this.state.preferences.auto_align} />
|
shortcut={this.state.preferences.auto_align} />
|
||||||
<DetailsToggleButton id="more-details" onClick={this.onDetailsToggle} showDetails={this.state.show_details} />
|
<DetailsToggleButton id="more-details" onClick={this.onDetailsToggle} showDetails={this.state.show_details}
|
||||||
|
shortcut={this.state.preferences.show_details} />
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
<ButtonGroup>
|
<ButtonGroup>
|
||||||
<IconButton id="zoom-to-fit" icon="fa fa-compress" onClick={this.diagram.zoomToFit} title={gettext('Zoom to fit')}
|
<IconButton id="zoom-to-fit" icon="fa fa-compress" onClick={this.diagram.zoomToFit} title={gettext('Zoom to fit')}
|
||||||
|
@ -654,7 +783,7 @@ export default class BodyWidget extends React.Component {
|
||||||
reference={this.noteRefEle} noteNode={this.state.note_node} appendTo={this.diagramContainerRef.current} rows={8}/>
|
reference={this.noteRefEle} noteNode={this.state.note_node} appendTo={this.diagramContainerRef.current} rows={8}/>
|
||||||
<div className="diagram-container" ref={this.diagramContainerRef}>
|
<div className="diagram-container" ref={this.diagramContainerRef}>
|
||||||
<Loader message={this.state.loading_msg} autoEllipsis={true}/>
|
<Loader message={this.state.loading_msg} autoEllipsis={true}/>
|
||||||
<CanvasWidget className="diagram-canvas flex-grow-1" ref={(ele)=>{this.canvasEle = ele?.ref?.current}} engine={this.diagram.getEngine()} />
|
<CanvasWidget className="diagram-canvas flex-grow-1" ref={(ele)=>{this.canvasEle = ele?.ref?.current;}} engine={this.diagram.getEngine()} />
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -672,10 +801,11 @@ BodyWidget.propTypes = {
|
||||||
title: PropTypes.string.isRequired,
|
title: PropTypes.string.isRequired,
|
||||||
bgcolor: PropTypes.string,
|
bgcolor: PropTypes.string,
|
||||||
fgcolor: PropTypes.string,
|
fgcolor: PropTypes.string,
|
||||||
gen: PropTypes.bool.isRequired
|
gen: PropTypes.bool.isRequired,
|
||||||
}),
|
}),
|
||||||
getDialog: PropTypes.func.isRequired,
|
getDialog: PropTypes.func.isRequired,
|
||||||
transformToSupported: PropTypes.func.isRequired,
|
transformToSupported: PropTypes.func.isRequired,
|
||||||
|
pgWindow: PropTypes.object.isRequired,
|
||||||
pgAdmin: PropTypes.object.isRequired,
|
pgAdmin: PropTypes.object.isRequired,
|
||||||
alertify: PropTypes.object.isRequired
|
alertify: PropTypes.object.isRequired,
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,7 +16,7 @@ export const STATUS = {
|
||||||
DISCONNECTED: 2,
|
DISCONNECTED: 2,
|
||||||
CONNECTING: 3,
|
CONNECTING: 3,
|
||||||
FAILED: 4,
|
FAILED: 4,
|
||||||
}
|
};
|
||||||
|
|
||||||
/* The connection bar component */
|
/* The connection bar component */
|
||||||
export default function ConnectionBar({statusId, status, bgcolor, fgcolor, title}) {
|
export default function ConnectionBar({statusId, status, bgcolor, fgcolor, title}) {
|
||||||
|
@ -33,19 +33,19 @@ export default function ConnectionBar({statusId, status, bgcolor, fgcolor, title
|
||||||
+ (status == STATUS.CONNECTED ? 'icon-query-tool-connected' : '')
|
+ (status == STATUS.CONNECTED ? 'icon-query-tool-connected' : '')
|
||||||
+ (status == (STATUS.DISCONNECTED || STATUS.FAILED) ? 'icon-query-tool-disconnected ' : '')
|
+ (status == (STATUS.DISCONNECTED || STATUS.FAILED) ? 'icon-query-tool-disconnected ' : '')
|
||||||
+ (status == STATUS.CONNECTING ? 'obtaining-conn' : '')}
|
+ (status == STATUS.CONNECTING ? 'obtaining-conn' : '')}
|
||||||
aria-hidden="true" title="" role="img">
|
aria-hidden="true" title="" role="img">
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="connection-info btn-group" role="group" aria-label="">
|
<div className="connection-info btn-group" role="group" aria-label="">
|
||||||
<div className="editor-title"
|
<div className="editor-title"
|
||||||
style={{backgroundColor: bgcolor, color: fgcolor}}>
|
style={{backgroundColor: bgcolor, color: fgcolor}}>
|
||||||
{status == STATUS.CONNECTING ? '(' + gettext('Obtaining connection...') + ') ' : ''}
|
{status == STATUS.CONNECTING ? '(' + gettext('Obtaining connection...') + ') ' : ''}
|
||||||
{status == STATUS.FAILED ? '(' + gettext('Connection failed') + ') ' : ''}
|
{status == STATUS.FAILED ? '(' + gettext('Connection failed') + ') ' : ''}
|
||||||
{title}
|
{title}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectionBar.propTypes = {
|
ConnectionBar.propTypes = {
|
||||||
|
|
|
@ -51,13 +51,13 @@ export default function FloatingNote({open, onClose, reference, rows, noteNode,
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
visible={open}
|
visible={open}
|
||||||
interactive={true}
|
interactive={true}
|
||||||
animation={false}
|
animation={false}
|
||||||
reference={reference}
|
reference={reference}
|
||||||
placement='auto-end'
|
placement='auto-end'
|
||||||
{...tippyProps}
|
{...tippyProps}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ BaseIconButton.propTypes = {
|
||||||
text: PropTypes.string,
|
text: PropTypes.string,
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
ref: CustomPropTypes.ref,
|
ref: CustomPropTypes.ref,
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
/* The tooltip content to show shortcut details */
|
/* The tooltip content to show shortcut details */
|
||||||
|
@ -47,10 +47,10 @@ export function Shortcut({shortcut}) {
|
||||||
return (
|
return (
|
||||||
<div style={{justifyContent: 'center', marginTop: '0.125rem'}} className="d-flex">
|
<div style={{justifyContent: 'center', marginTop: '0.125rem'}} className="d-flex">
|
||||||
{keys.map((key, i)=>{
|
{keys.map((key, i)=>{
|
||||||
return <div key={i} className="shortcut-key">{key}</div>
|
return <div key={i} className="shortcut-key">{key}</div>;
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const shortcutPropType = PropTypes.shape({
|
const shortcutPropType = PropTypes.shape({
|
||||||
|
@ -85,7 +85,7 @@ export const IconButton = forwardRef((props, ref) => {
|
||||||
</Tippy>
|
</Tippy>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return <BaseIconButton ref={ref} className='btn btn-sm btn-primary-icon' {...otherProps}/>
|
return <BaseIconButton ref={ref} className='btn btn-sm btn-primary-icon' {...otherProps}/>;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -93,21 +93,21 @@ IconButton.propTypes = {
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
shortcut: shortcutPropType,
|
shortcut: shortcutPropType,
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
}
|
};
|
||||||
|
|
||||||
/* Toggle button, icon changes based on value */
|
/* Toggle button, icon changes based on value */
|
||||||
export function DetailsToggleButton({showDetails, ...props}) {
|
export function DetailsToggleButton({showDetails, ...props}) {
|
||||||
return (
|
return (
|
||||||
<IconButton
|
<IconButton
|
||||||
icon={showDetails ? 'far fa-eye' : 'fas fa-low-vision'}
|
icon={showDetails ? 'far fa-eye' : 'fas fa-low-vision'}
|
||||||
title={showDetails ? gettext('Show fewer details') : gettext("Show more details") }
|
title={showDetails ? gettext('Show fewer details') : gettext('Show more details') }
|
||||||
{...props} />
|
{...props} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
DetailsToggleButton.propTypes = {
|
DetailsToggleButton.propTypes = {
|
||||||
showDetails: PropTypes.bool,
|
showDetails: PropTypes.bool,
|
||||||
}
|
};
|
||||||
|
|
||||||
/* Button group container */
|
/* Button group container */
|
||||||
export function ButtonGroup({className, children}) {
|
export function ButtonGroup({className, children}) {
|
||||||
|
@ -115,12 +115,12 @@ export function ButtonGroup({className, children}) {
|
||||||
<div className={'btn-group mr-1 ' + (className ? className : '')} role="group" aria-label="save group">
|
<div className={'btn-group mr-1 ' + (className ? className : '')} role="group" aria-label="save group">
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ButtonGroup.propTypes = {
|
ButtonGroup.propTypes = {
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
}
|
};
|
||||||
|
|
||||||
/* Toolbar container */
|
/* Toolbar container */
|
||||||
export default function ToolBar({id, children}) {
|
export default function ToolBar({id, children}) {
|
||||||
|
@ -128,9 +128,9 @@ export default function ToolBar({id, children}) {
|
||||||
<div id={id} className="editor-toolbar d-flex" role="toolbar" aria-label="">
|
<div id={id} className="editor-toolbar d-flex" role="toolbar" aria-label="">
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ButtonGroup.propTypes = {
|
ButtonGroup.propTypes = {
|
||||||
id: PropTypes.string,
|
id: PropTypes.string,
|
||||||
}
|
};
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.floating-note {
|
.floating-note {
|
||||||
|
@ -56,6 +57,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.note-body {
|
.note-body {
|
||||||
|
word-break: break-all;
|
||||||
& textarea {
|
& textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: none;
|
border: none;
|
||||||
|
@ -69,11 +71,21 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.html2canvas-reset {
|
||||||
|
background-image: none !important;
|
||||||
|
overflow: auto !important;
|
||||||
|
|
||||||
|
& > svg, & > div {
|
||||||
|
transform: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.diagram-canvas{
|
.diagram-canvas{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
color: $color-fg;
|
color: $color-fg;
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
|
background-color: $erd-canvas-bg;
|
||||||
background-image: $erd-bg-grid;
|
background-image: $erd-bg-grid;
|
||||||
cursor: unset;
|
cursor: unset;
|
||||||
|
|
||||||
|
@ -85,6 +97,22 @@
|
||||||
width: 175px;
|
width: 175px;
|
||||||
font-size: 0.8em;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
&.selected {
|
&.selected {
|
||||||
border-color: $input-focus-border-color;
|
border-color: $input-focus-border-color;
|
||||||
box-shadow: $input-btn-focus-box-shadow;
|
box-shadow: $input-btn-focus-box-shadow;
|
||||||
|
@ -105,16 +133,24 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-schema {
|
.table-schema-data {
|
||||||
border-bottom: $border-width solid $erd-node-border-color;
|
border-bottom: $border-width solid $erd-node-border-color;
|
||||||
padding: $erd-row-padding;
|
padding: $erd-row-padding;
|
||||||
font-weight: bold;
|
|
||||||
|
& .table-schema {
|
||||||
|
font-weight: bold;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-name {
|
.table-name-data {
|
||||||
border-bottom: $border-width*2 solid $erd-node-border-color;
|
border-bottom: $border-width*2 solid $erd-node-border-color;
|
||||||
padding: $erd-row-padding;
|
padding: $erd-row-padding;
|
||||||
font-weight: bold;
|
|
||||||
|
& .table-name {
|
||||||
|
font-weight: bold;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-cols {
|
.table-cols {
|
||||||
|
@ -123,10 +159,7 @@
|
||||||
.col-row-data {
|
.col-row-data {
|
||||||
padding: $erd-row-padding;
|
padding: $erd-row-padding;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
word-break: break-all;
|
||||||
.col-name {
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.col-row-port {
|
.col-row-port {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
|
@ -73,7 +73,10 @@ describe('ERD TableNodeModel', ()=>{
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('setData', ()=>{
|
describe('setData', ()=>{
|
||||||
let existPort = jasmine.createSpyObj('port', ['removeAllLinks']);
|
let existPort = jasmine.createSpyObj('port', {
|
||||||
|
'removeAllLinks': jasmine.createSpy('removeAllLinks'),
|
||||||
|
'getSubtype': 'notset',
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(()=>{
|
beforeEach(()=>{
|
||||||
modelObj._data.columns = [
|
modelObj._data.columns = [
|
||||||
|
@ -93,6 +96,7 @@ describe('ERD TableNodeModel', ()=>{
|
||||||
});
|
});
|
||||||
|
|
||||||
it('add columns', ()=>{
|
it('add columns', ()=>{
|
||||||
|
spyOn(existPort, 'getSubtype').and.returnValue('many');
|
||||||
existPort.removeAllLinks.calls.reset();
|
existPort.removeAllLinks.calls.reset();
|
||||||
modelObj.setData({
|
modelObj.setData({
|
||||||
name: 'noname',
|
name: 'noname',
|
||||||
|
@ -118,29 +122,31 @@ describe('ERD TableNodeModel', ()=>{
|
||||||
});
|
});
|
||||||
|
|
||||||
it('update columns', ()=>{
|
it('update columns', ()=>{
|
||||||
|
spyOn(existPort, 'getSubtype').and.returnValue('many');
|
||||||
existPort.removeAllLinks.calls.reset();
|
existPort.removeAllLinks.calls.reset();
|
||||||
modelObj.setData({
|
modelObj.setData({
|
||||||
name: 'noname',
|
name: 'noname',
|
||||||
schema: 'erd',
|
schema: 'erd',
|
||||||
columns: [
|
columns: [
|
||||||
{name: 'col1', not_null:false, attnum: 0},
|
{name: 'col1', not_null:false, attnum: 0, is_primary_key: false},
|
||||||
{name: 'col2updated', not_null:false, attnum: 1},
|
{name: 'col2updated', not_null:false, attnum: 1, is_primary_key: false},
|
||||||
{name: 'col3', not_null:true, attnum: 2},
|
{name: 'col3', not_null:true, attnum: 2, is_primary_key: false},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
expect(modelObj.getData()).toEqual({
|
expect(modelObj.getData()).toEqual({
|
||||||
name: 'noname',
|
name: 'noname',
|
||||||
schema: 'erd',
|
schema: 'erd',
|
||||||
columns: [
|
columns: [
|
||||||
{name: 'col1', not_null:false, attnum: 0},
|
{name: 'col1', not_null:false, attnum: 0, is_primary_key: false},
|
||||||
{name: 'col2updated', not_null:false, attnum: 1},
|
{name: 'col2updated', not_null:false, attnum: 1, is_primary_key: false},
|
||||||
{name: 'col3', not_null:true, attnum: 2},
|
{name: 'col3', not_null:true, attnum: 2, is_primary_key: false},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
expect(existPort.removeAllLinks).not.toHaveBeenCalled();
|
expect(existPort.removeAllLinks).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('remove columns', ()=>{
|
it('remove columns', ()=>{
|
||||||
|
spyOn(existPort, 'getSubtype').and.returnValue('one');
|
||||||
existPort.removeAllLinks.calls.reset();
|
existPort.removeAllLinks.calls.reset();
|
||||||
modelObj.setData({
|
modelObj.setData({
|
||||||
name: 'noname',
|
name: 'noname',
|
||||||
|
|
|
@ -41,6 +41,10 @@ let pgAdmin = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let pgWindow = {
|
||||||
|
pgAdmin: pgAdmin,
|
||||||
|
};
|
||||||
|
|
||||||
let alertify = jasmine.createSpyObj('alertify', {
|
let alertify = jasmine.createSpyObj('alertify', {
|
||||||
'success': null,
|
'success': null,
|
||||||
'error': null,
|
'error': null,
|
||||||
|
@ -124,7 +128,7 @@ describe('ERD BodyWidget', ()=>{
|
||||||
|
|
||||||
beforeEach(()=>{
|
beforeEach(()=>{
|
||||||
jasmineEnzyme();
|
jasmineEnzyme();
|
||||||
body = mount(<BodyWidget params={params} pgAdmin={pgAdmin} getDialog={getDialog} transformToSupported={()=>{}} alertify={alertify}/>);
|
body = mount(<BodyWidget params={params} pgAdmin={pgAdmin} pgWindow={pgWindow} getDialog={getDialog} transformToSupported={()=>{}} alertify={alertify}/>);
|
||||||
bodyInstance = body.instance();
|
bodyInstance = body.instance();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -248,7 +252,7 @@ describe('ERD BodyWidget', ()=>{
|
||||||
bodyInstance.addEditNode();
|
bodyInstance.addEditNode();
|
||||||
expect(tableDialog.show).toHaveBeenCalled();
|
expect(tableDialog.show).toHaveBeenCalled();
|
||||||
|
|
||||||
let saveCallback = tableDialog.show.calls.mostRecent().args[5];
|
let saveCallback = tableDialog.show.calls.mostRecent().args[6];
|
||||||
let newData = {key: 'value'};
|
let newData = {key: 'value'};
|
||||||
saveCallback(newData);
|
saveCallback(newData);
|
||||||
expect(bodyInstance.diagram.addNode).toHaveBeenCalledWith(newData);
|
expect(bodyInstance.diagram.addNode).toHaveBeenCalledWith(newData);
|
||||||
|
@ -263,7 +267,7 @@ describe('ERD BodyWidget', ()=>{
|
||||||
bodyInstance.addEditNode(node);
|
bodyInstance.addEditNode(node);
|
||||||
expect(tableDialog.show).toHaveBeenCalled();
|
expect(tableDialog.show).toHaveBeenCalled();
|
||||||
|
|
||||||
saveCallback = tableDialog.show.calls.mostRecent().args[5];
|
saveCallback = tableDialog.show.calls.mostRecent().args[6];
|
||||||
newData = {key: 'value'};
|
newData = {key: 'value'};
|
||||||
saveCallback(newData);
|
saveCallback(newData);
|
||||||
expect(node.setData).toHaveBeenCalledWith(newData);
|
expect(node.setData).toHaveBeenCalledWith(newData);
|
||||||
|
|
191
web/yarn.lock
191
web/yarn.lock
|
@ -1281,6 +1281,14 @@ acorn@^7.0.0, acorn@^7.1.0, acorn@^7.1.1:
|
||||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
|
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
|
||||||
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
|
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
|
||||||
|
|
||||||
|
adjust-sourcemap-loader@3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/adjust-sourcemap-loader/-/adjust-sourcemap-loader-3.0.0.tgz#5ae12fb5b7b1c585e80bbb5a63ec163a1a45e61e"
|
||||||
|
integrity sha512-YBrGyT2/uVQ/c6Rr+t6ZJXniY03YtHGMJQYal368burRGYKqhx9qGTWqcBU5s1CwYY9E/ri63RYyG1IacMZtqw==
|
||||||
|
dependencies:
|
||||||
|
loader-utils "^2.0.0"
|
||||||
|
regex-parser "^2.2.11"
|
||||||
|
|
||||||
after@0.8.2:
|
after@0.8.2:
|
||||||
version "0.8.2"
|
version "0.8.2"
|
||||||
resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
|
resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
|
||||||
|
@ -1432,6 +1440,11 @@ argparse@^1.0.6, argparse@^1.0.7:
|
||||||
dependencies:
|
dependencies:
|
||||||
sprintf-js "~1.0.2"
|
sprintf-js "~1.0.2"
|
||||||
|
|
||||||
|
arity-n@^1.0.4:
|
||||||
|
version "1.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/arity-n/-/arity-n-1.0.4.tgz#d9e76b11733e08569c0847ae7b39b2860b30b745"
|
||||||
|
integrity sha1-2edrEXM+CFacCEeuezmyhgswt0U=
|
||||||
|
|
||||||
arr-diff@^4.0.0:
|
arr-diff@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
|
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
|
||||||
|
@ -1813,6 +1826,11 @@ base64-arraybuffer@0.1.5:
|
||||||
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8"
|
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8"
|
||||||
integrity sha1-c5JncZI7Whl0etZmqlzUv5xunOg=
|
integrity sha1-c5JncZI7Whl0etZmqlzUv5xunOg=
|
||||||
|
|
||||||
|
base64-arraybuffer@^0.2.0:
|
||||||
|
version "0.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.2.0.tgz#4b944fac0191aa5907afe2d8c999ccc57ce80f45"
|
||||||
|
integrity sha512-7emyCsu1/xiBXgQZrscw/8KPRT44I4Yq9Pe6EGs3aPRTsWuggML1/1DTuZUuIaJPIm1FTDUVXl4x/yW8s0kQDQ==
|
||||||
|
|
||||||
base64-js@^1.0.2, base64-js@^1.3.1:
|
base64-js@^1.0.2, base64-js@^1.3.1:
|
||||||
version "1.5.1"
|
version "1.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
||||||
|
@ -2437,16 +2455,16 @@ camelcase-keys@^2.0.0:
|
||||||
camelcase "^2.0.0"
|
camelcase "^2.0.0"
|
||||||
map-obj "^1.0.0"
|
map-obj "^1.0.0"
|
||||||
|
|
||||||
|
camelcase@5.3.1, camelcase@^5.0.0:
|
||||||
|
version "5.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
|
||||||
|
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
|
||||||
|
|
||||||
camelcase@^2.0.0:
|
camelcase@^2.0.0:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
|
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
|
||||||
integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=
|
integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=
|
||||||
|
|
||||||
camelcase@^5.0.0:
|
|
||||||
version "5.3.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
|
|
||||||
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
|
|
||||||
|
|
||||||
caniuse-api@^3.0.0:
|
caniuse-api@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0"
|
resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0"
|
||||||
|
@ -2797,6 +2815,13 @@ component-inherit@0.0.3:
|
||||||
resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143"
|
resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143"
|
||||||
integrity sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=
|
integrity sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=
|
||||||
|
|
||||||
|
compose-function@3.0.3:
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/compose-function/-/compose-function-3.0.3.tgz#9ed675f13cc54501d30950a486ff6a7ba3ab185f"
|
||||||
|
integrity sha1-ntZ18TzFRQHTCVCkhv9qe6OrGF8=
|
||||||
|
dependencies:
|
||||||
|
arity-n "^1.0.4"
|
||||||
|
|
||||||
concat-map@0.0.1:
|
concat-map@0.0.1:
|
||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||||
|
@ -2857,13 +2882,18 @@ content-type@~1.0.4:
|
||||||
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
|
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
|
||||||
integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
|
integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
|
||||||
|
|
||||||
convert-source-map@^1.1.3, convert-source-map@^1.5.0, convert-source-map@^1.7.0:
|
convert-source-map@1.7.0, convert-source-map@^1.1.3, convert-source-map@^1.5.0, convert-source-map@^1.7.0:
|
||||||
version "1.7.0"
|
version "1.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
|
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
|
||||||
integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==
|
integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==
|
||||||
dependencies:
|
dependencies:
|
||||||
safe-buffer "~5.1.1"
|
safe-buffer "~5.1.1"
|
||||||
|
|
||||||
|
convert-source-map@^0.3.3:
|
||||||
|
version "0.3.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-0.3.5.tgz#f1d802950af7dd2631a1febe0596550c86ab3190"
|
||||||
|
integrity sha1-8dgClQr33SYxof6+BZZVDIarMZA=
|
||||||
|
|
||||||
convert-source-map@~1.1.0:
|
convert-source-map@~1.1.0:
|
||||||
version "1.1.3"
|
version "1.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.1.3.tgz#4829c877e9fe49b3161f3bf3673888e204699860"
|
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.1.3.tgz#4829c877e9fe49b3161f3bf3673888e204699860"
|
||||||
|
@ -3051,6 +3081,13 @@ css-declaration-sorter@^4.0.1:
|
||||||
postcss "^7.0.1"
|
postcss "^7.0.1"
|
||||||
timsort "^0.3.0"
|
timsort "^0.3.0"
|
||||||
|
|
||||||
|
css-line-break@1.1.1:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/css-line-break/-/css-line-break-1.1.1.tgz#d5e9bdd297840099eb0503c7310fd34927a026ef"
|
||||||
|
integrity sha512-1feNVaM4Fyzdj4mKPIQNL2n70MmuYzAXZ1aytlROFX1JsOo070OsugwGjj7nl6jnDJWHDM8zRZswkmeYVWZJQA==
|
||||||
|
dependencies:
|
||||||
|
base64-arraybuffer "^0.2.0"
|
||||||
|
|
||||||
css-loader@2.1.0:
|
css-loader@2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-2.1.0.tgz#42952ac22bca5d076978638e9813abce49b8f0cc"
|
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-2.1.0.tgz#42952ac22bca5d076978638e9813abce49b8f0cc"
|
||||||
|
@ -3119,6 +3156,16 @@ css-what@^4.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/css-what/-/css-what-4.0.0.tgz#35e73761cab2eeb3d3661126b23d7aa0e8432233"
|
resolved "https://registry.yarnpkg.com/css-what/-/css-what-4.0.0.tgz#35e73761cab2eeb3d3661126b23d7aa0e8432233"
|
||||||
integrity sha512-teijzG7kwYfNVsUh2H/YN62xW3KK9YhXEgSlbxMlcyjPNvdKJqFx5lrwlJgoFP1ZHlB89iGDlo/JyshKeRhv5A==
|
integrity sha512-teijzG7kwYfNVsUh2H/YN62xW3KK9YhXEgSlbxMlcyjPNvdKJqFx5lrwlJgoFP1ZHlB89iGDlo/JyshKeRhv5A==
|
||||||
|
|
||||||
|
css@^2.0.0:
|
||||||
|
version "2.2.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929"
|
||||||
|
integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==
|
||||||
|
dependencies:
|
||||||
|
inherits "^2.0.3"
|
||||||
|
source-map "^0.6.1"
|
||||||
|
source-map-resolve "^0.5.2"
|
||||||
|
urix "^0.1.0"
|
||||||
|
|
||||||
cssesc@^3.0.0:
|
cssesc@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
|
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
|
||||||
|
@ -3235,6 +3282,14 @@ cyclist@^1.0.1:
|
||||||
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
|
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
|
||||||
integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=
|
integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=
|
||||||
|
|
||||||
|
d@1, d@^1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a"
|
||||||
|
integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==
|
||||||
|
dependencies:
|
||||||
|
es5-ext "^0.10.50"
|
||||||
|
type "^1.0.1"
|
||||||
|
|
||||||
dagre@^0.8.4:
|
dagre@^0.8.4:
|
||||||
version "0.8.5"
|
version "0.8.5"
|
||||||
resolved "https://registry.yarnpkg.com/dagre/-/dagre-0.8.5.tgz#ba30b0055dac12b6c1fcc247817442777d06afee"
|
resolved "https://registry.yarnpkg.com/dagre/-/dagre-0.8.5.tgz#ba30b0055dac12b6c1fcc247817442777d06afee"
|
||||||
|
@ -3664,6 +3719,11 @@ emoji-regex@^7.0.1:
|
||||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
|
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
|
||||||
integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
|
integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
|
||||||
|
|
||||||
|
emojis-list@^2.0.0:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
|
||||||
|
integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k=
|
||||||
|
|
||||||
emojis-list@^3.0.0:
|
emojis-list@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78"
|
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78"
|
||||||
|
@ -3870,6 +3930,32 @@ es-to-primitive@^1.2.1:
|
||||||
is-date-object "^1.0.1"
|
is-date-object "^1.0.1"
|
||||||
is-symbol "^1.0.2"
|
is-symbol "^1.0.2"
|
||||||
|
|
||||||
|
es5-ext@^0.10.35, es5-ext@^0.10.50:
|
||||||
|
version "0.10.53"
|
||||||
|
resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1"
|
||||||
|
integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==
|
||||||
|
dependencies:
|
||||||
|
es6-iterator "~2.0.3"
|
||||||
|
es6-symbol "~3.1.3"
|
||||||
|
next-tick "~1.0.0"
|
||||||
|
|
||||||
|
es6-iterator@2.0.3, es6-iterator@~2.0.3:
|
||||||
|
version "2.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7"
|
||||||
|
integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c=
|
||||||
|
dependencies:
|
||||||
|
d "1"
|
||||||
|
es5-ext "^0.10.35"
|
||||||
|
es6-symbol "^3.1.1"
|
||||||
|
|
||||||
|
es6-symbol@^3.1.1, es6-symbol@~3.1.3:
|
||||||
|
version "3.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18"
|
||||||
|
integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==
|
||||||
|
dependencies:
|
||||||
|
d "^1.0.1"
|
||||||
|
ext "^1.1.2"
|
||||||
|
|
||||||
escalade@^3.1.1:
|
escalade@^3.1.1:
|
||||||
version "3.1.1"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
|
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
|
||||||
|
@ -4176,6 +4262,13 @@ ext-name@^5.0.0:
|
||||||
ext-list "^2.0.0"
|
ext-list "^2.0.0"
|
||||||
sort-keys-length "^1.0.0"
|
sort-keys-length "^1.0.0"
|
||||||
|
|
||||||
|
ext@^1.1.2:
|
||||||
|
version "1.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/ext/-/ext-1.4.0.tgz#89ae7a07158f79d35517882904324077e4379244"
|
||||||
|
integrity sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==
|
||||||
|
dependencies:
|
||||||
|
type "^2.0.0"
|
||||||
|
|
||||||
extend-shallow@^2.0.1:
|
extend-shallow@^2.0.1:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f"
|
resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f"
|
||||||
|
@ -4982,6 +5075,13 @@ html-escaper@^2.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453"
|
resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453"
|
||||||
integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==
|
integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==
|
||||||
|
|
||||||
|
html2canvas@^1.0.0-rc.7:
|
||||||
|
version "1.0.0-rc.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/html2canvas/-/html2canvas-1.0.0-rc.7.tgz#70c159ce0e63954a91169531894d08ad5627ac98"
|
||||||
|
integrity sha512-yvPNZGejB2KOyKleZspjK/NruXVQuowu8NnV2HYG7gW7ytzl+umffbtUI62v2dCHQLDdsK6HIDtyJZ0W3neerA==
|
||||||
|
dependencies:
|
||||||
|
css-line-break "1.1.1"
|
||||||
|
|
||||||
htmlescape@^1.1.0:
|
htmlescape@^1.1.0:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/htmlescape/-/htmlescape-1.1.1.tgz#3a03edc2214bca3b66424a3e7959349509cb0351"
|
resolved "https://registry.yarnpkg.com/htmlescape/-/htmlescape-1.1.1.tgz#3a03edc2214bca3b66424a3e7959349509cb0351"
|
||||||
|
@ -6167,6 +6267,15 @@ loader-runner@^2.4.0:
|
||||||
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"
|
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"
|
||||||
integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==
|
integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==
|
||||||
|
|
||||||
|
loader-utils@1.2.3:
|
||||||
|
version "1.2.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7"
|
||||||
|
integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==
|
||||||
|
dependencies:
|
||||||
|
big.js "^5.2.2"
|
||||||
|
emojis-list "^2.0.0"
|
||||||
|
json5 "^1.0.1"
|
||||||
|
|
||||||
loader-utils@1.4.0, loader-utils@^1.0.1, loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.1, loader-utils@^1.2.3, loader-utils@^1.4.0:
|
loader-utils@1.4.0, loader-utils@^1.0.1, loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.1, loader-utils@^1.2.3, loader-utils@^1.4.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613"
|
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613"
|
||||||
|
@ -6837,6 +6946,11 @@ neo-async@^2.5.0, neo-async@^2.6.1:
|
||||||
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
|
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
|
||||||
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
|
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
|
||||||
|
|
||||||
|
next-tick@~1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c"
|
||||||
|
integrity sha1-yobR/ogoFpsBICCOPchCS524NCw=
|
||||||
|
|
||||||
nice-try@^1.0.4:
|
nice-try@^1.0.4:
|
||||||
version "1.0.5"
|
version "1.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
|
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
|
||||||
|
@ -7854,6 +7968,15 @@ postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0:
|
||||||
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb"
|
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb"
|
||||||
integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==
|
integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==
|
||||||
|
|
||||||
|
postcss@7.0.21:
|
||||||
|
version "7.0.21"
|
||||||
|
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.21.tgz#06bb07824c19c2021c5d056d5b10c35b989f7e17"
|
||||||
|
integrity sha512-uIFtJElxJo29QC753JzhidoAhvp/e/Exezkdhfmt8AymWT6/5B7W1WmponYWkHk2eg6sONyTch0A3nkMPun3SQ==
|
||||||
|
dependencies:
|
||||||
|
chalk "^2.4.2"
|
||||||
|
source-map "^0.6.1"
|
||||||
|
supports-color "^6.1.0"
|
||||||
|
|
||||||
postcss@7.0.27:
|
postcss@7.0.27:
|
||||||
version "7.0.27"
|
version "7.0.27"
|
||||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.27.tgz#cc67cdc6b0daa375105b7c424a85567345fc54d9"
|
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.27.tgz#cc67cdc6b0daa375105b7c424a85567345fc54d9"
|
||||||
|
@ -8260,6 +8383,11 @@ regex-not@^1.0.0, regex-not@^1.0.2:
|
||||||
extend-shallow "^3.0.2"
|
extend-shallow "^3.0.2"
|
||||||
safe-regex "^1.1.0"
|
safe-regex "^1.1.0"
|
||||||
|
|
||||||
|
regex-parser@^2.2.11:
|
||||||
|
version "2.2.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/regex-parser/-/regex-parser-2.2.11.tgz#3b37ec9049e19479806e878cabe7c1ca83ccfe58"
|
||||||
|
integrity sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==
|
||||||
|
|
||||||
regexp.prototype.flags@^1.3.0:
|
regexp.prototype.flags@^1.3.0:
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75"
|
resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75"
|
||||||
|
@ -8374,6 +8502,22 @@ resolve-from@^4.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
|
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
|
||||||
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
|
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
|
||||||
|
|
||||||
|
resolve-url-loader@^3.1.2:
|
||||||
|
version "3.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-3.1.2.tgz#235e2c28e22e3e432ba7a5d4e305c59a58edfc08"
|
||||||
|
integrity sha512-QEb4A76c8Mi7I3xNKXlRKQSlLBwjUV/ULFMP+G7n3/7tJZ8MG5wsZ3ucxP1Jz8Vevn6fnJsxDx9cIls+utGzPQ==
|
||||||
|
dependencies:
|
||||||
|
adjust-sourcemap-loader "3.0.0"
|
||||||
|
camelcase "5.3.1"
|
||||||
|
compose-function "3.0.3"
|
||||||
|
convert-source-map "1.7.0"
|
||||||
|
es6-iterator "2.0.3"
|
||||||
|
loader-utils "1.2.3"
|
||||||
|
postcss "7.0.21"
|
||||||
|
rework "1.0.1"
|
||||||
|
rework-visit "1.0.0"
|
||||||
|
source-map "0.6.1"
|
||||||
|
|
||||||
resolve-url@^0.2.1:
|
resolve-url@^0.2.1:
|
||||||
version "0.2.1"
|
version "0.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
|
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
|
||||||
|
@ -8412,6 +8556,19 @@ ret@~0.1.10:
|
||||||
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
|
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
|
||||||
integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==
|
integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==
|
||||||
|
|
||||||
|
rework-visit@1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/rework-visit/-/rework-visit-1.0.0.tgz#9945b2803f219e2f7aca00adb8bc9f640f842c9a"
|
||||||
|
integrity sha1-mUWygD8hni96ygCtuLyfZA+ELJo=
|
||||||
|
|
||||||
|
rework@1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/rework/-/rework-1.0.1.tgz#30806a841342b54510aa4110850cd48534144aa7"
|
||||||
|
integrity sha1-MIBqhBNCtUUQqkEQhQzUhTQUSqc=
|
||||||
|
dependencies:
|
||||||
|
convert-source-map "^0.3.3"
|
||||||
|
css "^2.0.0"
|
||||||
|
|
||||||
rfdc@^1.1.4:
|
rfdc@^1.1.4:
|
||||||
version "1.1.4"
|
version "1.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.4.tgz#ba72cc1367a0ccd9cf81a870b3b58bd3ad07f8c2"
|
resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.4.tgz#ba72cc1367a0ccd9cf81a870b3b58bd3ad07f8c2"
|
||||||
|
@ -8890,7 +9047,7 @@ source-list-map@^2.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
|
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
|
||||||
integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==
|
integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==
|
||||||
|
|
||||||
source-map-resolve@^0.5.0:
|
source-map-resolve@^0.5.0, source-map-resolve@^0.5.2:
|
||||||
version "0.5.3"
|
version "0.5.3"
|
||||||
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"
|
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"
|
||||||
integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==
|
integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==
|
||||||
|
@ -8919,16 +9076,16 @@ source-map@0.5.0:
|
||||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.0.tgz#0fe96503ac86a5adb5de63f4e412ae4872cdbe86"
|
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.0.tgz#0fe96503ac86a5adb5de63f4e412ae4872cdbe86"
|
||||||
integrity sha1-D+llA6yGpa213mP05BKuSHLNvoY=
|
integrity sha1-D+llA6yGpa213mP05BKuSHLNvoY=
|
||||||
|
|
||||||
|
source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
|
||||||
|
version "0.6.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||||
|
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||||
|
|
||||||
source-map@^0.5.0, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.3:
|
source-map@^0.5.0, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.3:
|
||||||
version "0.5.7"
|
version "0.5.7"
|
||||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
|
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
|
||||||
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
|
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
|
||||||
|
|
||||||
source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
|
|
||||||
version "0.6.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
|
||||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
|
||||||
|
|
||||||
source-map@^0.7.3:
|
source-map@^0.7.3:
|
||||||
version "0.7.3"
|
version "0.7.3"
|
||||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
|
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
|
||||||
|
@ -9653,6 +9810,16 @@ type-is@~1.6.17, type-is@~1.6.18:
|
||||||
media-typer "0.3.0"
|
media-typer "0.3.0"
|
||||||
mime-types "~2.1.24"
|
mime-types "~2.1.24"
|
||||||
|
|
||||||
|
type@^1.0.1:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0"
|
||||||
|
integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==
|
||||||
|
|
||||||
|
type@^2.0.0:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/type/-/type-2.1.0.tgz#9bdc22c648cf8cf86dd23d32336a41cfb6475e3f"
|
||||||
|
integrity sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==
|
||||||
|
|
||||||
typedarray@^0.0.6:
|
typedarray@^0.0.6:
|
||||||
version "0.0.6"
|
version "0.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||||
|
|
Loading…
Reference in New Issue