highlight selected node on map
This commit is contained in:
parent
725604c7e0
commit
3af099e70b
|
@ -34,7 +34,6 @@
|
|||
"classnames": "^2.2.6",
|
||||
"cross-fetch": "^3.0.4",
|
||||
"cytoscape": "^3.8.1",
|
||||
"cytoscape-cola": "^2.3.0",
|
||||
"lodash": "^4.17.14",
|
||||
"moment": "^2.22.2",
|
||||
"normalize.css": "^8.0.0",
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
import cytoscape from "cytoscape";
|
||||
import * as React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import styled from "styled-components";
|
||||
import { DEFAULT_NODE_COLOR, SELECTED_NODE_COLOR } from "../constants";
|
||||
|
||||
const FullDiv = styled.div`
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
`;
|
||||
|
||||
interface ICytoscapeProps {
|
||||
elements: cytoscape.ElementsDefinition;
|
||||
onInstanceSelect: (domain: string) => void;
|
||||
onInstanceDeselect: () => void;
|
||||
}
|
||||
class Cytoscape extends React.Component<ICytoscapeProps> {
|
||||
public cy?: cytoscape.Core;
|
||||
|
||||
public componentDidMount() {
|
||||
const container = ReactDOM.findDOMNode(this);
|
||||
this.cy = cytoscape({
|
||||
autoungrabify: true,
|
||||
container: container as any,
|
||||
elements: {
|
||||
...this.props.elements,
|
||||
edges: this.props.elements.edges.map(e => ({
|
||||
...e,
|
||||
data: {
|
||||
...e.data,
|
||||
weight: Math.min(Math.max(e.data.weight * 10, 0.5), 5)
|
||||
}
|
||||
})),
|
||||
nodes: this.props.elements.nodes.map(n => ({
|
||||
...n,
|
||||
data: {
|
||||
...n.data,
|
||||
size: Math.min(Math.max(n.data.size * 20, 1), 100)
|
||||
}
|
||||
}))
|
||||
},
|
||||
hideEdgesOnViewport: true,
|
||||
hideLabelsOnViewport: true,
|
||||
layout: {
|
||||
name: "preset"
|
||||
},
|
||||
selectionType: "single"
|
||||
});
|
||||
|
||||
const style = this.cy.style() as any;
|
||||
|
||||
style
|
||||
.clear()
|
||||
.selector("node")
|
||||
.style({
|
||||
"background-color": DEFAULT_NODE_COLOR,
|
||||
height: "data(size)",
|
||||
label: "data(id)",
|
||||
width: "data(size)"
|
||||
})
|
||||
.selector("node:selected")
|
||||
.style({
|
||||
"background-color": SELECTED_NODE_COLOR
|
||||
})
|
||||
.selector("edge")
|
||||
.style({
|
||||
"line-color": DEFAULT_NODE_COLOR,
|
||||
width: "data(weight)"
|
||||
})
|
||||
.selector("node[label]")
|
||||
.style({
|
||||
color: DEFAULT_NODE_COLOR
|
||||
})
|
||||
.update();
|
||||
|
||||
this.cy.nodes().on("select", e => {
|
||||
const instanceId = e.target.data("id");
|
||||
if (instanceId) {
|
||||
this.props.onInstanceSelect(instanceId);
|
||||
}
|
||||
});
|
||||
this.cy.nodes().on("unselect", e => {
|
||||
this.props.onInstanceDeselect();
|
||||
});
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
if (this.cy) {
|
||||
this.cy.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
return <FullDiv />;
|
||||
}
|
||||
}
|
||||
|
||||
export default Cytoscape;
|
|
@ -1,218 +0,0 @@
|
|||
import cytoscape from "cytoscape";
|
||||
// import cola from "cytoscape-cola";
|
||||
import * as React from "react";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import { Dispatch } from "redux";
|
||||
import styled from "styled-components";
|
||||
import { DEFAULT_NODE_COLOR, SELECTED_NODE_COLOR } from "../constants";
|
||||
import { selectAndLoadInstance } from "../redux/actions";
|
||||
import { IAppState, IGraph } from "../redux/types";
|
||||
import { ErrorState } from "./ErrorState";
|
||||
// import { FloatingLayoutSelect } from "./FloatingLayoutSelect";
|
||||
import { FloatingResetButton } from "./FloatingResetButton";
|
||||
|
||||
interface IGraphProps {
|
||||
graph?: IGraph;
|
||||
currentInstanceName: string | null;
|
||||
selectAndLoadInstance: (name: string) => void;
|
||||
}
|
||||
interface IGraphState {
|
||||
layoutAlgorithm: string;
|
||||
isLayouting: boolean;
|
||||
didError: boolean;
|
||||
}
|
||||
class GraphImpl extends React.Component<IGraphProps, IGraphState> {
|
||||
private cy?: cytoscape.Core;
|
||||
// private layout?: cytoscape.Layouts;
|
||||
private cytoscapeDiv: React.RefObject<HTMLElement>;
|
||||
|
||||
public constructor(props: IGraphProps) {
|
||||
super(props);
|
||||
this.cytoscapeDiv = React.createRef();
|
||||
this.state = { layoutAlgorithm: "cola", isLayouting: false, didError: false };
|
||||
}
|
||||
|
||||
public render() {
|
||||
if (this.state.didError) {
|
||||
return <ErrorState />;
|
||||
}
|
||||
|
||||
const FullDiv = styled.div`
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
`;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FullDiv id="cytoscape" ref={this.cytoscapeDiv as any} />
|
||||
{/* <FloatingLayoutSelect
|
||||
onItemSelect={this.handleLayoutSelect}
|
||||
currentLayoutKey={this.state.layoutAlgorithm}
|
||||
startLayout={this.startLayout}
|
||||
stopLayout={this.stopLayout}
|
||||
/> */}
|
||||
<FloatingResetButton onClick={this.resetGraph} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
let { graph } = this.props;
|
||||
if (!graph) {
|
||||
this.setState({ didError: true });
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that all nodes have size & coordinates; otherwise the graph will look messed up
|
||||
const lengthBeforeFilter = graph.nodes.length;
|
||||
graph = { ...graph, nodes: graph.nodes.filter(n => n.data.size && n.position.x && n.position.y) };
|
||||
if (graph.nodes.length !== lengthBeforeFilter) {
|
||||
// tslint:disable-next-line:no-console
|
||||
console.error(
|
||||
"Some nodes were missing details: " +
|
||||
graph.nodes.filter(n => !n.data.size || !n.position.x || !n.position.y).map(n => n.data.label)
|
||||
);
|
||||
this.setState({ didError: true });
|
||||
}
|
||||
|
||||
// cytoscape.use(cola as any);
|
||||
this.initGraph();
|
||||
}
|
||||
|
||||
public componentDidUpdate() {
|
||||
this.initGraph();
|
||||
}
|
||||
|
||||
// private handleLayoutSelect = (layout: string) => {
|
||||
// this.setState({ layoutAlgorithm: layout });
|
||||
// };
|
||||
|
||||
// private startLayout = () => {
|
||||
// if (!this.cy) {
|
||||
// return;
|
||||
// }
|
||||
// const options = {
|
||||
// cola: {
|
||||
// animate: true,
|
||||
// convergenceThreshold: 0.1,
|
||||
// edgeLength: (edge: any) => 1 / edge.data("weight"),
|
||||
// name: "cola"
|
||||
// },
|
||||
// cose: {
|
||||
// animate: false,
|
||||
// idealEdgeLength: (edge: any) => 1 / edge.data("weight"),
|
||||
// name: "cose",
|
||||
// numIter: 100
|
||||
// }
|
||||
// };
|
||||
// this.layout = this.cy.layout(options[this.state.layoutAlgorithm] as any);
|
||||
// this.layout.run();
|
||||
// };
|
||||
|
||||
// private stopLayout = () => {
|
||||
// if (!this.layout) {
|
||||
// return;
|
||||
// }
|
||||
// this.layout.stop();
|
||||
// };
|
||||
|
||||
private initGraph = () => {
|
||||
const { graph } = this.props;
|
||||
if (this.state.didError || !graph) {
|
||||
return;
|
||||
}
|
||||
this.cy = cytoscape({
|
||||
autoungrabify: false,
|
||||
container: this.cytoscapeDiv.current,
|
||||
elements: {
|
||||
edges: graph.edges.map(e => ({
|
||||
...e,
|
||||
data: {
|
||||
...e.data,
|
||||
weight: Math.min(Math.max(e.data.weight * 100, 2), 10)
|
||||
},
|
||||
selectable: false
|
||||
})),
|
||||
nodes: graph.nodes.map(n => ({
|
||||
...n,
|
||||
data: {
|
||||
...n.data,
|
||||
size: Math.min(Math.max(n.data.size * 10, 10), 80)
|
||||
}
|
||||
}))
|
||||
},
|
||||
layout: {
|
||||
name: "preset"
|
||||
},
|
||||
selectionType: "single",
|
||||
style: [
|
||||
{
|
||||
selector: "node:selected",
|
||||
style: {
|
||||
"background-color": SELECTED_NODE_COLOR,
|
||||
label: "data(id)"
|
||||
}
|
||||
},
|
||||
{
|
||||
selector: "node",
|
||||
style: {
|
||||
"background-color": DEFAULT_NODE_COLOR,
|
||||
height: "data(size)",
|
||||
label: "data(id)",
|
||||
width: "data(size)"
|
||||
}
|
||||
},
|
||||
{
|
||||
selector: "edge",
|
||||
style: {
|
||||
width: "data(weight)"
|
||||
}
|
||||
},
|
||||
{
|
||||
selector: "label",
|
||||
style: {
|
||||
color: DEFAULT_NODE_COLOR
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
this.cy.nodes().on("select", e => {
|
||||
const instanceId = e.target.data("id");
|
||||
if (instanceId) {
|
||||
// console.log(`selecting ${instanceId}`);
|
||||
// console.log(`now selected: ${this.cy && this.cy.$(":selected")}`);
|
||||
this.props.selectAndLoadInstance(instanceId);
|
||||
}
|
||||
});
|
||||
this.cy.nodes().on("unselect", e => {
|
||||
const instanceId = e.target.data("id");
|
||||
if (instanceId) {
|
||||
// console.log(`unselecting ${instanceId}`);
|
||||
this.props.selectAndLoadInstance("");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
private resetGraph = () => {
|
||||
if (!this.cy) {
|
||||
return;
|
||||
}
|
||||
this.cy.reset();
|
||||
};
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: IAppState) => ({
|
||||
currentInstanceName: state.currentInstance.currentInstanceName,
|
||||
graph: state.data.graph
|
||||
});
|
||||
const mapDispatchToProps = (dispatch: Dispatch) => ({
|
||||
selectAndLoadInstance: (instanceName: string) => dispatch(selectAndLoadInstance(instanceName) as any)
|
||||
});
|
||||
export const CytoscapeGraph = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(GraphImpl);
|
|
@ -1,53 +0,0 @@
|
|||
import { Button, H6, MenuItem } from "@blueprintjs/core";
|
||||
import { IconNames } from "@blueprintjs/icons";
|
||||
import { ItemRenderer, Select } from "@blueprintjs/select";
|
||||
import * as React from "react";
|
||||
import FloatingCard from "./FloatingCard";
|
||||
|
||||
interface ILayoutToDisplayName {
|
||||
[key: string]: string;
|
||||
}
|
||||
const layouts: ILayoutToDisplayName = {
|
||||
cola: "COLA",
|
||||
cose: "CoSE"
|
||||
};
|
||||
const LayoutSelect = Select.ofType<string>();
|
||||
|
||||
const LayoutItemRenderer: ItemRenderer<string> = (layout, { handleClick, modifiers }) => (
|
||||
<MenuItem active={modifiers.active} key={layout} onClick={handleClick} text={layout} />
|
||||
);
|
||||
|
||||
interface IFloatingLayoutSelectProps {
|
||||
currentLayoutKey: string;
|
||||
onItemSelect: (layout: string) => void;
|
||||
startLayout: () => void;
|
||||
stopLayout: () => void;
|
||||
}
|
||||
export const FloatingLayoutSelect: React.FC<IFloatingLayoutSelectProps> = ({
|
||||
currentLayoutKey,
|
||||
onItemSelect,
|
||||
startLayout,
|
||||
stopLayout
|
||||
}) => {
|
||||
return (
|
||||
<FloatingCard>
|
||||
<H6>Layout</H6>
|
||||
<LayoutSelect
|
||||
items={Object.keys(layouts)}
|
||||
itemRenderer={LayoutItemRenderer}
|
||||
filterable={false}
|
||||
onItemSelect={onItemSelect}
|
||||
popoverProps={{ minimal: true }}
|
||||
>
|
||||
<Button
|
||||
icon="film"
|
||||
rightIcon="caret-down"
|
||||
text={currentLayoutKey ? layouts[currentLayoutKey] : "(No selection)"}
|
||||
/>
|
||||
</LayoutSelect>
|
||||
<br />
|
||||
<Button icon={IconNames.PLAY} onClick={startLayout} />
|
||||
<Button icon={IconNames.STOP} onClick={stopLayout} />
|
||||
</FloatingCard>
|
||||
);
|
||||
};
|
|
@ -1,107 +0,0 @@
|
|||
import * as React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { Sigma, Filter, ForceAtlas2 } from "react-sigma";
|
||||
|
||||
import { selectAndLoadInstance } from "../redux/actions";
|
||||
import { ErrorState } from "./ErrorState";
|
||||
|
||||
const STYLE = {
|
||||
bottom: "0",
|
||||
left: "0",
|
||||
position: "absolute",
|
||||
right: "0",
|
||||
top: "50px"
|
||||
};
|
||||
const DEFAULT_NODE_COLOR = "#CED9E0";
|
||||
const SELECTED_NODE_COLOR = "#48AFF0";
|
||||
const SETTINGS = {
|
||||
defaultEdgeColor: "#5C7080",
|
||||
defaultLabelColor: "#F5F8FA",
|
||||
defaultNodeColor: DEFAULT_NODE_COLOR,
|
||||
drawEdges: true,
|
||||
drawLabels: true,
|
||||
edgeColor: "default",
|
||||
labelColor: "default",
|
||||
labelThreshold: 10,
|
||||
maxEdgeSize: 1,
|
||||
minEdgeSize: 0.3
|
||||
};
|
||||
|
||||
class GraphImpl extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.sigmaComponent = React.createRef();
|
||||
}
|
||||
|
||||
render() {
|
||||
let graph = this.props.graph;
|
||||
if (!graph) {
|
||||
return <ErrorState />;
|
||||
}
|
||||
// Check that all nodes have size & coordinates; otherwise the graph will look messed up
|
||||
const lengthBeforeFilter = graph.nodes.length;
|
||||
graph = { ...graph, nodes: graph.nodes.filter(n => n.size && n.x && n.y) };
|
||||
if (graph.nodes.length !== lengthBeforeFilter) {
|
||||
// tslint:disable-next-line:no-console
|
||||
console.error(
|
||||
"Some nodes were missing details: " +
|
||||
this.props.graph.nodes.filter(n => !n.size || !n.x || !n.y).map(n => n.label)
|
||||
);
|
||||
return <ErrorState />;
|
||||
}
|
||||
return (
|
||||
<Sigma
|
||||
graph={graph}
|
||||
renderer="webgl"
|
||||
settings={SETTINGS}
|
||||
style={STYLE}
|
||||
onClickNode={this.onClickNode}
|
||||
onClickStage={this.onClickStage}
|
||||
ref={this.sigmaComponent}
|
||||
>
|
||||
<Filter neighborsOf={this.props.currentInstanceName} />
|
||||
<ForceAtlas2 iterationsPerRender={1} timeout={10000} />
|
||||
</Sigma>
|
||||
);
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
const sigma = this.sigmaComponent && this.sigmaComponent.current.sigma;
|
||||
// Check if sigma exists s.t. nothing breaks if the graph didn't load (for whatever reason)
|
||||
if (sigma) {
|
||||
sigma.graph.nodes().map(this.colorNodes);
|
||||
sigma.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
onClickNode = e => {
|
||||
this.props.selectAndLoadInstance(e.data.node.label);
|
||||
};
|
||||
|
||||
onClickStage = e => {
|
||||
// Deselect the instance (unless this was a drag event)
|
||||
if (!e.data.captor.isDragging) {
|
||||
this.props.selectAndLoadInstance(null);
|
||||
}
|
||||
};
|
||||
|
||||
colorNodes = n => {
|
||||
if (this.props.currentInstanceName && n.id === this.props.currentInstanceName) {
|
||||
n.color = SELECTED_NODE_COLOR;
|
||||
} else {
|
||||
n.color = DEFAULT_NODE_COLOR;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
currentInstanceName: state.currentInstance.currentInstanceName,
|
||||
graph: state.data.graph
|
||||
});
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
selectAndLoadInstance: instanceName => dispatch(selectAndLoadInstance(instanceName))
|
||||
});
|
||||
export const Graph = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(GraphImpl);
|
|
@ -0,0 +1,125 @@
|
|||
import { get } from "lodash";
|
||||
import * as React from "react";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import { Dispatch } from "redux";
|
||||
import { selectAndLoadInstance } from "../redux/actions";
|
||||
import { IAppState, IGraph } from "../redux/types";
|
||||
import Cytoscape from "./Cytoscape";
|
||||
import { ErrorState } from "./ErrorState";
|
||||
import { FloatingResetButton } from "./FloatingResetButton";
|
||||
|
||||
interface IGraphProps {
|
||||
graph?: IGraph;
|
||||
currentInstanceName: string | null;
|
||||
selectAndLoadInstance: (name: string) => void;
|
||||
}
|
||||
interface IGraphState {
|
||||
didError: boolean;
|
||||
}
|
||||
class GraphImpl extends React.Component<IGraphProps, IGraphState> {
|
||||
private cytoscapeComponent: React.RefObject<Cytoscape>;
|
||||
|
||||
public constructor(props: IGraphProps) {
|
||||
super(props);
|
||||
this.state = { didError: false };
|
||||
this.cytoscapeComponent = React.createRef();
|
||||
}
|
||||
|
||||
public render() {
|
||||
if (this.state.didError || !this.props.graph) {
|
||||
return <ErrorState />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Cytoscape
|
||||
elements={this.props.graph}
|
||||
onInstanceSelect={this.onInstanceSelect}
|
||||
onInstanceDeselect={this.onInstanceDeselect}
|
||||
ref={this.cytoscapeComponent}
|
||||
/>
|
||||
<FloatingResetButton onClick={this.resetGraphPosition} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
let { graph } = this.props;
|
||||
if (!graph) {
|
||||
this.setState({ didError: true });
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that all nodes have size & coordinates; otherwise the graph will look messed up
|
||||
const lengthBeforeFilter = graph.nodes.length;
|
||||
graph = { ...graph, nodes: graph.nodes.filter(n => n.data.size && n.position.x && n.position.y) };
|
||||
if (graph.nodes.length !== lengthBeforeFilter) {
|
||||
// tslint:disable-next-line:no-console
|
||||
console.error(
|
||||
"Some nodes were missing details: " +
|
||||
graph.nodes.filter(n => !n.data.size || !n.position.x || !n.position.y).map(n => n.data.label)
|
||||
);
|
||||
this.setState({ didError: true });
|
||||
}
|
||||
}
|
||||
|
||||
public componentDidUpdate(prevProps: IGraphProps) {
|
||||
const { currentInstanceName } = this.props;
|
||||
if (prevProps.currentInstanceName !== currentInstanceName) {
|
||||
const cy = this.getCytoscape();
|
||||
cy.$(":selected").unselect();
|
||||
if (currentInstanceName) {
|
||||
// Select instance
|
||||
cy.$id(`${currentInstanceName}`).select();
|
||||
// Center it
|
||||
const selected = cy.$(":selected");
|
||||
cy.center(selected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private resetGraphPosition = () => {
|
||||
const cy = this.getCytoscape();
|
||||
const { currentInstanceName } = this.props;
|
||||
if (currentInstanceName) {
|
||||
cy.zoom({
|
||||
level: 0.5,
|
||||
position: cy.$id(currentInstanceName).position()
|
||||
});
|
||||
} else {
|
||||
cy.zoom({
|
||||
level: 0.5,
|
||||
position: { x: 0, y: 0 }
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
private onInstanceSelect = (domain: string) => {
|
||||
this.props.selectAndLoadInstance(domain);
|
||||
};
|
||||
|
||||
private onInstanceDeselect = () => {
|
||||
this.props.selectAndLoadInstance("");
|
||||
};
|
||||
|
||||
private getCytoscape = () => {
|
||||
const cy = get(this.cytoscapeComponent, "current.cy");
|
||||
if (!cy) {
|
||||
throw new Error("Expected cytoscape component but did not find one.");
|
||||
}
|
||||
return cy;
|
||||
};
|
||||
}
|
||||
const mapStateToProps = (state: IAppState) => ({
|
||||
currentInstanceName: state.currentInstance.currentInstanceName,
|
||||
graph: state.data.graph
|
||||
});
|
||||
const mapDispatchToProps = (dispatch: Dispatch) => ({
|
||||
selectAndLoadInstance: (instanceName: string) => dispatch(selectAndLoadInstance(instanceName) as any)
|
||||
});
|
||||
const Graph = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(GraphImpl);
|
||||
export default Graph;
|
|
@ -6,8 +6,8 @@ import { NonIdealState, Spinner } from "@blueprintjs/core";
|
|||
|
||||
import { fetchGraph, fetchInstances } from "../../redux/actions";
|
||||
import { IAppState, IGraph, IInstance } from "../../redux/types";
|
||||
import { CytoscapeGraph } from "../CytoscapeGraph";
|
||||
import { ErrorState } from "../ErrorState";
|
||||
import Graph from "../Graph";
|
||||
import { Sidebar } from "../Sidebar";
|
||||
|
||||
interface IGraphScreenProps {
|
||||
|
@ -48,7 +48,7 @@ class GraphScreenImpl extends React.Component<IGraphScreenProps> {
|
|||
};
|
||||
|
||||
private graphState = () => {
|
||||
const content = this.props.graphLoadError ? <ErrorState /> : <CytoscapeGraph />;
|
||||
const content = this.props.graphLoadError ? <ErrorState /> : <Graph />;
|
||||
return (
|
||||
<div>
|
||||
<Sidebar />
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
declare module "cytoscape-cola" {
|
||||
const prototype: {};
|
||||
}
|
|
@ -4,7 +4,10 @@
|
|||
"allowSyntheticDefaultImports": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"jsx": "preserve",
|
||||
"lib": ["esnext", "dom"],
|
||||
"lib": [
|
||||
"es2015",
|
||||
"dom"
|
||||
],
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"noImplicitAny": true,
|
||||
|
@ -20,11 +23,19 @@
|
|||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"strict": true,
|
||||
"typeRoots": ["./node_modules/@types", "./src/typings"],
|
||||
"typeRoots": [
|
||||
"./node_modules/@types",
|
||||
"./src/typings"
|
||||
],
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true
|
||||
},
|
||||
"exclude": ["node_modules", "build"],
|
||||
"include": ["src"]
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"build"
|
||||
],
|
||||
"include": [
|
||||
"src"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -3413,13 +3413,6 @@ cyclist@~0.2.2:
|
|||
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640"
|
||||
integrity sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=
|
||||
|
||||
cytoscape-cola@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/cytoscape-cola/-/cytoscape-cola-2.3.0.tgz#24104eaab46e0a88dfeedb02199610450525208d"
|
||||
integrity sha512-xblxlCH8JXGLdH6XMUBJY3xBUJuL1rLy8bLMGvqkvoPHSbBfV+/klMWoqwervVKWOmFHPwUdihtxy8stG4RM5g==
|
||||
dependencies:
|
||||
webcola "^3.3.6"
|
||||
|
||||
cytoscape@^3.8.1:
|
||||
version "3.8.1"
|
||||
resolved "https://registry.yarnpkg.com/cytoscape/-/cytoscape-3.8.1.tgz#0b87f646054ea3e86f347e9c53a2fc64df1be31b"
|
||||
|
@ -3428,29 +3421,6 @@ cytoscape@^3.8.1:
|
|||
heap "^0.2.6"
|
||||
lodash.debounce "^4.0.8"
|
||||
|
||||
d3-dispatch@1, d3-dispatch@^1.0.3:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-1.0.5.tgz#e25c10a186517cd6c82dd19ea018f07e01e39015"
|
||||
integrity sha512-vwKx+lAqB1UuCeklr6Jh1bvC4SZgbSqbkGBLClItFBIYH4vqDJCA7qfoy14lXmJdnBOdxndAMxjCbImJYW7e6g==
|
||||
|
||||
d3-drag@^1.0.4:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-1.2.3.tgz#46e206ad863ec465d88c588098a1df444cd33c64"
|
||||
integrity sha512-8S3HWCAg+ilzjJsNtWW1Mutl74Nmzhb9yU6igspilaJzeZVFktmY6oO9xOh5TDk+BM2KrNFjttZNoJJmDnkjkg==
|
||||
dependencies:
|
||||
d3-dispatch "1"
|
||||
d3-selection "1"
|
||||
|
||||
d3-selection@1:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-1.4.0.tgz#ab9ac1e664cf967ebf1b479cc07e28ce9908c474"
|
||||
integrity sha512-EYVwBxQGEjLCKF2pJ4+yrErskDnz5v403qvAid96cNdCMr8rmCYfY5RGzWz24mdIbxmDf6/4EAH+K9xperD5jg==
|
||||
|
||||
d3-timer@^1.0.5:
|
||||
version "1.0.9"
|
||||
resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-1.0.9.tgz#f7bb8c0d597d792ff7131e1c24a36dd471a471ba"
|
||||
integrity sha512-rT34J5HnQUHhcLvhSB9GjCkN0Ddd5Y8nCwDBG2u6wQEeYxT/Lf51fTFFkldeib/sE/J0clIe0pnCfs6g/lRbyg==
|
||||
|
||||
damerau-levenshtein@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz#03191c432cb6eea168bb77f3a55ffdccb8978514"
|
||||
|
@ -10930,15 +10900,6 @@ web-namespaces@^1.1.2:
|
|||
resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.2.tgz#c8dc267ab639505276bae19e129dbd6ae72b22b4"
|
||||
integrity sha512-II+n2ms4mPxK+RnIxRPOw3zwF2jRscdJIUE9BfkKHm4FYEg9+biIoTMnaZF5MpemE3T+VhMLrhbyD4ilkPCSbg==
|
||||
|
||||
webcola@^3.3.6:
|
||||
version "3.3.9"
|
||||
resolved "https://registry.yarnpkg.com/webcola/-/webcola-3.3.9.tgz#a54cae07478f1b25968d280b0d4a369c0b4352b3"
|
||||
integrity sha512-hjE23yiRU+7AGajxuDdUDW8txyMVgXHCW71erA0UVKYx0lruqs1o4QFQ0OSpSdNS6wlAwgk0IPxhuEiQq1MXfQ==
|
||||
dependencies:
|
||||
d3-dispatch "^1.0.3"
|
||||
d3-drag "^1.0.4"
|
||||
d3-timer "^1.0.5"
|
||||
|
||||
webidl-conversions@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
|
||||
|
|
Loading…
Reference in New Issue