mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Allow changing cardinality notation in ERD to use Chen notation. #5832
This commit is contained in:
parent
696cb0fa05
commit
1806866bf5
@ -135,18 +135,21 @@ Utility Options
|
|||||||
:class: longtable
|
:class: longtable
|
||||||
:widths: 1 4 1
|
:widths: 1 4 1
|
||||||
|
|
||||||
+----------------------+---------------------------------------------------------------------------------------------------+----------------+
|
+-------------------------+------------------------------------------------------------------------------------------------+----------------+
|
||||||
| Icon | Behavior | Shortcut |
|
| Icon | Behavior | Shortcut |
|
||||||
+======================+===================================================================================================+================+
|
+=========================+================================================================================================+================+
|
||||||
| *Add/Edit note* | Click this button to make notes on tables nodes while designing the database. | Option/Alt + |
|
| *Add/Edit note* | Click this button to make notes on tables nodes while designing the database. | Option/Alt + |
|
||||||
| | | Ctrl + N |
|
| | | Ctrl + N |
|
||||||
+----------------------+---------------------------------------------------------------------------------------------------+----------------+
|
+-------------------------+------------------------------------------------------------------------------------------------+----------------+
|
||||||
| *Auto align* | Click this button to auto align all tables and links to make it look more cleaner. | Option/Alt + |
|
| *Auto align* | Click this button to auto align all tables and links to make it look more cleaner. | Option/Alt + |
|
||||||
| | | Ctrl + L |
|
| | | Ctrl + L |
|
||||||
+----------------------+---------------------------------------------------------------------------------------------------+----------------+
|
+-------------------------+------------------------------------------------------------------------------------------------+----------------+
|
||||||
| *Show details* | Click this button to toggle the column details visibility. It allows you to show few or more | Option/Alt + |
|
| *Show details* | Click this button to toggle the column details visibility. It allows you to show few or more | Option/Alt + |
|
||||||
| | column details. | Shift + D |
|
| | column details. | Shift + D |
|
||||||
+----------------------+---------------------------------------------------------------------------------------------------+----------------+
|
+-------------------------+------------------------------------------------------------------------------------------------+----------------+
|
||||||
|
| *Cardinality Notation* | Change the cardinality notation format used to present relationship links. Options available | |
|
||||||
|
| | are - Crow's Foot Notation and Chen Notation. | |
|
||||||
|
+-------------------------+------------------------------------------------------------------------------------------------+----------------+
|
||||||
|
|
||||||
Zoom Options
|
Zoom Options
|
||||||
************
|
************
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 185 KiB After Width: | Height: | Size: 340 KiB |
Binary file not shown.
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 22 KiB |
@ -400,6 +400,31 @@ class ERDModule(PgAdminModule):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.preference.register(
|
||||||
|
'options', 'cardinality_notation',
|
||||||
|
gettext('Cardinality Notation'), 'radioModern', 'crows',
|
||||||
|
category_label=PREF_LABEL_OPTIONS, options=[
|
||||||
|
{'label': gettext('Crow\'s foot'), 'value': 'crows'},
|
||||||
|
{'label': gettext('Chen'), 'value': 'chen'},
|
||||||
|
],
|
||||||
|
help_str=gettext(
|
||||||
|
'Notation to be used to present cardinality.'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.preference.register(
|
||||||
|
'options',
|
||||||
|
'sql_with_drop',
|
||||||
|
gettext('SQL With DROP Table'),
|
||||||
|
'boolean',
|
||||||
|
False,
|
||||||
|
category_label=PREF_LABEL_OPTIONS,
|
||||||
|
help_str=gettext(
|
||||||
|
'If enabled, the SQL generated by the ERD Tool will add '
|
||||||
|
'DROP table DDL before each CREATE table DDL.'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
blueprint = ERDModule(MODULE_NAME, __name__, static_url_path='/static')
|
blueprint = ERDModule(MODULE_NAME, __name__, static_url_path='/static')
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ class ERDTool extends React.Component {
|
|||||||
_.bindAll(this, ['onLoadDiagram', 'onSaveDiagram', 'onSaveAsDiagram', 'onSQLClick',
|
_.bindAll(this, ['onLoadDiagram', 'onSaveDiagram', 'onSaveAsDiagram', 'onSQLClick',
|
||||||
'onImageClick', 'onAddNewNode', 'onEditTable', 'onCloneNode', 'onDeleteNode', 'onNoteClick',
|
'onImageClick', 'onAddNewNode', 'onEditTable', 'onCloneNode', 'onDeleteNode', 'onNoteClick',
|
||||||
'onNoteClose', 'onOneToManyClick', 'onManyToManyClick', 'onAutoDistribute', 'onDetailsToggle',
|
'onNoteClose', 'onOneToManyClick', 'onManyToManyClick', 'onAutoDistribute', 'onDetailsToggle',
|
||||||
'onDetailsToggle', 'onChangeColors', 'onHelpClick', 'onDropNode', 'onBeforeUnload',
|
'onChangeColors', 'onHelpClick', 'onDropNode', 'onBeforeUnload', 'onNotationChange',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
this.diagram.zoomToFit = this.diagram.zoomToFit.bind(this.diagram);
|
this.diagram.zoomToFit = this.diagram.zoomToFit.bind(this.diagram);
|
||||||
@ -293,11 +293,13 @@ class ERDTool extends React.Component {
|
|||||||
this.setLoading(gettext('Preparing...'));
|
this.setLoading(gettext('Preparing...'));
|
||||||
this.registerEvents();
|
this.registerEvents();
|
||||||
|
|
||||||
|
const erdPref = this.props.pgWindow.pgAdmin.Browser.get_preferences_for_module('erd');
|
||||||
this.setState({
|
this.setState({
|
||||||
preferences: this.props.pgWindow.pgAdmin.Browser.get_preferences_for_module('erd'),
|
preferences: erdPref,
|
||||||
is_new_tab: (this.props.pgWindow.pgAdmin.Browser.get_preferences_for_module('browser').new_browser_tab_open || '')
|
is_new_tab: (this.props.pgWindow.pgAdmin.Browser.get_preferences_for_module('browser').new_browser_tab_open || '')
|
||||||
.includes('erd_tool'),
|
.includes('erd_tool'),
|
||||||
is_close_tab_warning: this.props.pgWindow.pgAdmin.Browser.get_preferences_for_module('browser').confirm_on_refresh_close,
|
is_close_tab_warning: this.props.pgWindow.pgAdmin.Browser.get_preferences_for_module('browser').confirm_on_refresh_close,
|
||||||
|
cardinality_notation: erdPref.cardinality_notation,
|
||||||
}, ()=>{
|
}, ()=>{
|
||||||
this.registerKeyboardShortcuts();
|
this.registerKeyboardShortcuts();
|
||||||
this.setTitle(this.state.current_file);
|
this.setTitle(this.state.current_file);
|
||||||
@ -559,6 +561,10 @@ class ERDTool extends React.Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onNotationChange(e) {
|
||||||
|
this.setState({cardinality_notation: e.value});
|
||||||
|
}
|
||||||
|
|
||||||
onHelpClick() {
|
onHelpClick() {
|
||||||
let url = url_for('help.static', {'filename': 'erd_tool.html'});
|
let url = url_for('help.static', {'filename': 'erd_tool.html'});
|
||||||
if (this.props.pgWindow) {
|
if (this.props.pgWindow) {
|
||||||
@ -948,12 +954,17 @@ class ERDTool extends React.Component {
|
|||||||
fgcolor={this.props.params.fgcolor} title={this.props.params.title}/>
|
fgcolor={this.props.params.fgcolor} title={this.props.params.title}/>
|
||||||
<MainToolBar preferences={this.state.preferences} eventBus={this.eventBus}
|
<MainToolBar preferences={this.state.preferences} eventBus={this.eventBus}
|
||||||
fillColor={this.state.fill_color} textColor={this.state.text_color}
|
fillColor={this.state.fill_color} textColor={this.state.text_color}
|
||||||
|
notation={this.state.cardinality_notation} onNotationChange={this.onNotationChange}
|
||||||
/>
|
/>
|
||||||
<FloatingNote open={this.state.note_open} onClose={this.onNoteClose}
|
<FloatingNote open={this.state.note_open} onClose={this.onNoteClose}
|
||||||
anchorEl={this.noteRefEle} noteNode={this.state.note_node} appendTo={this.diagramContainerRef.current} rows={8}/>
|
anchorEl={this.noteRefEle} noteNode={this.state.note_node} appendTo={this.diagramContainerRef.current} rows={8}/>
|
||||||
<div className={this.props.classes.diagramContainer} data-test="diagram-container" ref={this.diagramContainerRef} onDrop={this.onDropNode} onDragOver={e => {e.preventDefault();}}>
|
<div className={this.props.classes.diagramContainer} data-test="diagram-container" ref={this.diagramContainerRef} onDrop={this.onDropNode} onDragOver={e => {e.preventDefault();}}>
|
||||||
<Loader message={this.state.loading_msg} autoEllipsis={true}/>
|
<Loader message={this.state.loading_msg} autoEllipsis={true}/>
|
||||||
|
<ERDCanvasSettings.Provider value={{
|
||||||
|
cardinality_notation: this.state.cardinality_notation
|
||||||
|
}}>
|
||||||
<CanvasWidget className={this.props.classes.diagramCanvas} ref={(ele)=>{this.canvasEle = ele?.ref?.current;}} engine={this.diagram.getEngine()} />
|
<CanvasWidget className={this.props.classes.diagramCanvas} ref={(ele)=>{this.canvasEle = ele?.ref?.current;}} engine={this.diagram.getEngine()} />
|
||||||
|
</ERDCanvasSettings.Provider>
|
||||||
</div>
|
</div>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
@ -981,3 +992,5 @@ ERDTool.propTypes = {
|
|||||||
panel: PropTypes.object,
|
panel: PropTypes.object,
|
||||||
classes: PropTypes.object,
|
classes: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const ERDCanvasSettings = React.createContext({});
|
||||||
|
@ -27,6 +27,7 @@ import VisibilityOffRoundedIcon from '@material-ui/icons/VisibilityOffRounded';
|
|||||||
import ImageRoundedIcon from '@material-ui/icons/ImageRounded';
|
import ImageRoundedIcon from '@material-ui/icons/ImageRounded';
|
||||||
import FormatColorFillRoundedIcon from '@material-ui/icons/FormatColorFillRounded';
|
import FormatColorFillRoundedIcon from '@material-ui/icons/FormatColorFillRounded';
|
||||||
import FormatColorTextRoundedIcon from '@material-ui/icons/FormatColorTextRounded';
|
import FormatColorTextRoundedIcon from '@material-ui/icons/FormatColorTextRounded';
|
||||||
|
import AccountTreeOutlinedIcon from '@material-ui/icons/AccountTreeOutlined';
|
||||||
|
|
||||||
import { PgMenu, PgMenuItem, usePgMenuGroup } from '../../../../../../static/js/components/Menu';
|
import { PgMenu, PgMenuItem, usePgMenuGroup } from '../../../../../../static/js/components/Menu';
|
||||||
import gettext from 'sources/gettext';
|
import gettext from 'sources/gettext';
|
||||||
@ -69,7 +70,7 @@ const useStyles = makeStyles((theme)=>({
|
|||||||
}),
|
}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export function MainToolBar({preferences, eventBus, fillColor, textColor}) {
|
export function MainToolBar({preferences, eventBus, fillColor, textColor, notation, onNotationChange}) {
|
||||||
const classes = useStyles({fillColor,textColor});
|
const classes = useStyles({fillColor,textColor});
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const [buttonsDisabled, setButtonsDisabled] = useState({
|
const [buttonsDisabled, setButtonsDisabled] = useState({
|
||||||
@ -86,6 +87,7 @@ export function MainToolBar({preferences, eventBus, fillColor, textColor}) {
|
|||||||
const {openMenuName, toggleMenu, onMenuClose} = usePgMenuGroup();
|
const {openMenuName, toggleMenu, onMenuClose} = usePgMenuGroup();
|
||||||
const saveAsMenuRef = React.useRef(null);
|
const saveAsMenuRef = React.useRef(null);
|
||||||
const sqlMenuRef = React.useRef(null);
|
const sqlMenuRef = React.useRef(null);
|
||||||
|
const notationMenuRef = React.useRef(null);
|
||||||
const isDirtyRef = React.useRef(null);
|
const isDirtyRef = React.useRef(null);
|
||||||
const [checkedMenuItems, setCheckedMenuItems] = React.useState({});
|
const [checkedMenuItems, setCheckedMenuItems] = React.useState({});
|
||||||
const modal = useModal();
|
const modal = useModal();
|
||||||
@ -283,6 +285,9 @@ export function MainToolBar({preferences, eventBus, fillColor, textColor}) {
|
|||||||
eventBus.fireEvent(ERD_EVENTS.TOGGLE_DETAILS);
|
eventBus.fireEvent(ERD_EVENTS.TOGGLE_DETAILS);
|
||||||
setShowDetails((prev)=>!prev);
|
setShowDetails((prev)=>!prev);
|
||||||
}} />
|
}} />
|
||||||
|
<PgIconButton title={gettext('Cardinality Notation')} icon={
|
||||||
|
<><AccountTreeOutlinedIcon /><KeyboardArrowDownIcon style={{marginLeft: '-10px'}} /></>}
|
||||||
|
name="menu-notation" ref={notationMenuRef} onClick={toggleMenu} />
|
||||||
</PgButtonGroup>
|
</PgButtonGroup>
|
||||||
<PgButtonGroup size="small">
|
<PgButtonGroup size="small">
|
||||||
<PgIconButton title={gettext('Zoom In')} icon={<ZoomInIcon />}
|
<PgIconButton title={gettext('Zoom In')} icon={<ZoomInIcon />}
|
||||||
@ -323,6 +328,16 @@ export function MainToolBar({preferences, eventBus, fillColor, textColor}) {
|
|||||||
>
|
>
|
||||||
<PgMenuItem hasCheck value="sql_with_drop" checked={checkedMenuItems['sql_with_drop']} onClick={checkMenuClick}>{gettext('With DROP Table')}</PgMenuItem>
|
<PgMenuItem hasCheck value="sql_with_drop" checked={checkedMenuItems['sql_with_drop']} onClick={checkMenuClick}>{gettext('With DROP Table')}</PgMenuItem>
|
||||||
</PgMenu>
|
</PgMenu>
|
||||||
|
<PgMenu
|
||||||
|
anchorRef={notationMenuRef}
|
||||||
|
open={openMenuName=='menu-notation'}
|
||||||
|
onClose={onMenuClose}
|
||||||
|
label={gettext('Cardinality Notation')}
|
||||||
|
|
||||||
|
>
|
||||||
|
<PgMenuItem hasCheck closeOnCheck value="crows" checked={notation == 'crows'} onClick={onNotationChange}>{gettext('Crow\'s Foot Notation')}</PgMenuItem>
|
||||||
|
<PgMenuItem hasCheck closeOnCheck value="chen" checked={notation == 'chen'} onClick={onNotationChange}>{gettext('Chen Notation')}</PgMenuItem>
|
||||||
|
</PgMenu>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -332,6 +347,8 @@ MainToolBar.propTypes = {
|
|||||||
eventBus: PropTypes.object,
|
eventBus: PropTypes.object,
|
||||||
fillColor: PropTypes.string,
|
fillColor: PropTypes.string,
|
||||||
textColor: PropTypes.string,
|
textColor: PropTypes.string,
|
||||||
|
notation: PropTypes.string,
|
||||||
|
onNotationChange: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
const ColorButton = withColorPicker(PgIconButton);
|
const ColorButton = withColorPicker(PgIconButton);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
//
|
//
|
||||||
//////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
import React, { forwardRef } from 'react';
|
import React, { forwardRef, useContext } from 'react';
|
||||||
import {
|
import {
|
||||||
RightAngleLinkModel,
|
RightAngleLinkModel,
|
||||||
RightAngleLinkWidget,
|
RightAngleLinkWidget,
|
||||||
@ -21,6 +21,7 @@ import _ from 'lodash';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { makeStyles } from '@material-ui/core';
|
import { makeStyles } from '@material-ui/core';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
import { ERDCanvasSettings } from '../components/ERDTool';
|
||||||
|
|
||||||
export const POINTER_SIZE = 30;
|
export const POINTER_SIZE = 30;
|
||||||
|
|
||||||
@ -81,6 +82,7 @@ export class OneToManyLinkModel extends RightAngleLinkModel {
|
|||||||
const useStyles = makeStyles((theme)=>({
|
const useStyles = makeStyles((theme)=>({
|
||||||
svgLink: {
|
svgLink: {
|
||||||
stroke: theme.palette.text.primary,
|
stroke: theme.palette.text.primary,
|
||||||
|
fontSize: '0.8em',
|
||||||
},
|
},
|
||||||
'@keyframes svgLinkSelected': {
|
'@keyframes svgLinkSelected': {
|
||||||
'from': { strokeDashoffset: 24},
|
'from': { strokeDashoffset: 24},
|
||||||
@ -99,15 +101,37 @@ const useStyles = makeStyles((theme)=>({
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const CustomLinkEndWidget = props => {
|
function ChenNotation({rotation, type}) {
|
||||||
|
const classes = useStyles();
|
||||||
|
const textX = Math.sign(rotation) > 0 ? -14 : 8;
|
||||||
|
const textY = -5;
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<text className={classes.svgLink} x={textX} y={textY} transform={'rotate(' + -rotation + ')' }>
|
||||||
|
{type == 'one' ? '1' : 'N'}
|
||||||
|
</text>
|
||||||
|
<line className={classes.svgLink} x1="0" y1="0" x2="0" y2="30"></line>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
ChenNotation.propTypes = {
|
||||||
|
rotation: PropTypes.number,
|
||||||
|
type: PropTypes.string,
|
||||||
|
};
|
||||||
|
|
||||||
|
function CustomLinkEndWidget(props) {
|
||||||
const { point, rotation, tx, ty, type } = props;
|
const { point, rotation, tx, ty, type } = props;
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
const settings = useContext(ERDCanvasSettings);
|
||||||
|
|
||||||
const svgForType = (itype) => {
|
const svgForType = (itype) => {
|
||||||
|
if(settings.cardinality_notation == 'chen') {
|
||||||
|
return <ChenNotation rotation={rotation} type={itype} />;
|
||||||
|
}
|
||||||
if(itype == 'many') {
|
if(itype == 'many') {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<circle className={clsx(classes.svgLink, classes.svgLinkCircle)} cx="0" cy="16" r={props.width*1.75} strokeWidth={props.width} />
|
<circle className={clsx(classes.svgLink, classes.svgLinkCircle)} cx="0" cy="16" r={props.width*2.5} strokeWidth={props.width} />
|
||||||
<polyline className={classes.svgLink} points="-8,0 0,15 0,0 0,30 0,15 8,0" fill="none" strokeWidth={props.width} />
|
<polyline className={classes.svgLink} points="-8,0 0,15 0,0 0,30 0,15 8,0" fill="none" strokeWidth={props.width} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@ -127,7 +151,7 @@ const CustomLinkEndWidget = props => {
|
|||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
CustomLinkEndWidget.propTypes = {
|
CustomLinkEndWidget.propTypes = {
|
||||||
point: PropTypes.instanceOf(PointModel).isRequired,
|
point: PropTypes.instanceOf(PointModel).isRequired,
|
||||||
|
@ -202,6 +202,17 @@ const styles = (theme)=>({
|
|||||||
padding: '0.125rem 0.25rem',
|
padding: '0.125rem 0.25rem',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
},
|
},
|
||||||
|
columnSection: {
|
||||||
|
display:'flex',
|
||||||
|
width: '100%' ,
|
||||||
|
...theme.mixins.panelBorder.bottom,
|
||||||
|
},
|
||||||
|
columnName: {
|
||||||
|
display:'flex',
|
||||||
|
width: '100%' ,
|
||||||
|
padding: '0.125rem 0.25rem',
|
||||||
|
wordBreak: 'break-all',
|
||||||
|
},
|
||||||
tableToolbar: {
|
tableToolbar: {
|
||||||
background: theme.otherVars.editorToolbarBg,
|
background: theme.otherVars.editorToolbarBg,
|
||||||
borderTopLeftRadius: 'inherit',
|
borderTopLeftRadius: 'inherit',
|
||||||
@ -269,11 +280,11 @@ class TableNodeWidgetRaw extends React.Component {
|
|||||||
|
|
||||||
const {classes} = this.props;
|
const {classes} = this.props;
|
||||||
return (
|
return (
|
||||||
<div className={classes.tableSection} key={col.attnum} data-test="column-row">
|
<Box className={classes.columnSection} key={col.attnum} data-test="column-row">
|
||||||
<Box marginRight="auto" padding="0" minHeight="0" display="flex" alignItems="center">
|
<Box marginRight="auto" padding="0" minHeight="0" display="flex" alignItems="center">
|
||||||
{this.generatePort(leftPort)}
|
{this.generatePort(leftPort)}
|
||||||
</Box>
|
</Box>
|
||||||
<Box display="flex" width="100%" style={{wordBreak: 'break-all'}}>
|
<Box className={classes.columnName}>
|
||||||
<RowIcon icon={icon} />
|
<RowIcon icon={icon} />
|
||||||
<Box margin="auto 0">
|
<Box margin="auto 0">
|
||||||
<span data-test="column-name">{col.name}</span>
|
<span data-test="column-name">{col.name}</span>
|
||||||
@ -284,7 +295,7 @@ class TableNodeWidgetRaw extends React.Component {
|
|||||||
<Box marginLeft="auto" padding="0" minHeight="0" display="flex" alignItems="center">
|
<Box marginLeft="auto" padding="0" minHeight="0" display="flex" alignItems="center">
|
||||||
{this.generatePort(rightPort)}
|
{this.generatePort(rightPort)}
|
||||||
</Box>
|
</Box>
|
||||||
</div>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,13 +291,6 @@ describe('ERDCore', ()=>{
|
|||||||
]));
|
]));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('dagreDistributeNodes', ()=>{
|
|
||||||
spyOn(erdCoreObj.dagre_engine, 'redistribute');
|
|
||||||
erdCoreObj.dagreDistributeNodes();
|
|
||||||
expect(erdEngine.getLinkFactories().getFactory().calculateRoutingMatrix).toHaveBeenCalled();
|
|
||||||
expect(erdCoreObj.dagre_engine.redistribute).toHaveBeenCalledWith(erdEngine.getModel());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('zoomIn', ()=>{
|
it('zoomIn', ()=>{
|
||||||
spyOn(erdEngine.getModel(), 'getZoomLevel').and.returnValue(100);
|
spyOn(erdEngine.getModel(), 'getZoomLevel').and.returnValue(100);
|
||||||
spyOn(erdCoreObj, 'repaint');
|
spyOn(erdCoreObj, 'repaint');
|
||||||
|
Loading…
Reference in New Issue
Block a user