Factor out NodeTypeConfig (#763)
This factors `NodeTypeConfig` out of the `WeightConfig` component. The scope for a `NodeTypeConfig` is that it configures a single node type. Right now it just renders a single `WeightSlider`, but I like factoring out both for consistency with the `EdgeTypeConfig` (see #749) and because I expect we may want to add more complexity later. Test plan: The new component has some tests, also I manually tested the frontend.
This commit is contained in:
parent
44407b5520
commit
4cd45c77fc
|
@ -6,9 +6,14 @@ import sortBy from "lodash.sortby";
|
|||
import {type EdgeEvaluator} from "../../core/attribution/pagerank";
|
||||
import {byEdgeType, byNodeType} from "./edgeWeights";
|
||||
import {defaultStaticAdapters} from "../adapters/defaultPlugins";
|
||||
import type {NodeType, EdgeType} from "../adapters/pluginAdapter";
|
||||
import type {EdgeType} from "../adapters/pluginAdapter";
|
||||
import {WeightSlider} from "./weights/WeightSlider";
|
||||
import {DirectionalitySlider} from "./weights/DirectionalitySlider";
|
||||
import {
|
||||
NodeTypeConfig,
|
||||
defaultWeightedNodeType,
|
||||
type WeightedNodeType,
|
||||
} from "./weights/NodeTypeConfig";
|
||||
|
||||
type Props = {|
|
||||
+onChange: (EdgeEvaluator) => void,
|
||||
|
@ -28,19 +33,9 @@ const defaultEdgeWeights = (): EdgeWeights => {
|
|||
return result;
|
||||
};
|
||||
|
||||
type NodeWeights = WeightedNodeType[];
|
||||
type WeightedNodeType = {|+type: NodeType, +weight: number|};
|
||||
const defaultNodeWeights = (): NodeWeights => {
|
||||
const result = [];
|
||||
for (const type of defaultStaticAdapters().nodeTypes()) {
|
||||
result.push({type, weight: type.defaultWeight});
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
type State = {
|
||||
edgeWeights: EdgeWeights,
|
||||
nodeWeights: NodeWeights,
|
||||
nodeWeights: $ReadOnlyArray<WeightedNodeType>,
|
||||
expanded: boolean,
|
||||
};
|
||||
|
||||
|
@ -49,7 +44,9 @@ export class WeightConfig extends React.Component<Props, State> {
|
|||
super(props);
|
||||
this.state = {
|
||||
edgeWeights: defaultEdgeWeights(),
|
||||
nodeWeights: defaultNodeWeights(),
|
||||
nodeWeights: defaultStaticAdapters()
|
||||
.nodeTypes()
|
||||
.map(defaultWeightedNodeType),
|
||||
expanded: false,
|
||||
};
|
||||
}
|
||||
|
@ -175,36 +172,30 @@ class EdgeConfig extends React.Component<{
|
|||
}
|
||||
|
||||
class NodeConfig extends React.Component<{
|
||||
nodeWeights: NodeWeights,
|
||||
onChange: (NodeWeights) => void,
|
||||
nodeWeights: $ReadOnlyArray<WeightedNodeType>,
|
||||
onChange: ($ReadOnlyArray<WeightedNodeType>) => void,
|
||||
}> {
|
||||
render() {
|
||||
const sortedWeights = sortBy(
|
||||
this.props.nodeWeights,
|
||||
({type}) => type.prefix
|
||||
);
|
||||
|
||||
const controls = sortedWeights.map(({type, weight}) => {
|
||||
const onChange = (value) => {
|
||||
const nodeWeights = this.props.nodeWeights.filter(
|
||||
(x) => x.type.prefix !== type.prefix
|
||||
_renderControls() {
|
||||
return sortBy(this.props.nodeWeights, ({type}) => type.prefix).map(
|
||||
(weightedType) => {
|
||||
const onChange = (newType) => {
|
||||
const nodeWeights = this.props.nodeWeights.filter(
|
||||
(x) => x.type.prefix !== weightedType.type.prefix
|
||||
);
|
||||
nodeWeights.push(newType);
|
||||
this.props.onChange(nodeWeights);
|
||||
};
|
||||
return (
|
||||
<NodeTypeConfig weightedType={weightedType} onChange={onChange} />
|
||||
);
|
||||
nodeWeights.push({type, weight: value});
|
||||
this.props.onChange(nodeWeights);
|
||||
};
|
||||
return (
|
||||
<WeightSlider
|
||||
key={type.prefix}
|
||||
weight={weight}
|
||||
name={type.name}
|
||||
onChange={onChange}
|
||||
/>
|
||||
);
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<h2>Node weights</h2>
|
||||
{controls}
|
||||
{this._renderControls()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
// @flow
|
||||
|
||||
import React from "react";
|
||||
import {WeightSlider} from "./WeightSlider";
|
||||
import {type NodeType} from "../../adapters/pluginAdapter";
|
||||
|
||||
export type WeightedNodeType = {|+type: NodeType, +weight: number|};
|
||||
|
||||
export function defaultWeightedNodeType(type: NodeType): WeightedNodeType {
|
||||
return {
|
||||
type,
|
||||
weight: type.defaultWeight,
|
||||
};
|
||||
}
|
||||
|
||||
export class NodeTypeConfig extends React.Component<{
|
||||
+weightedType: WeightedNodeType,
|
||||
+onChange: (WeightedNodeType) => void,
|
||||
}> {
|
||||
render() {
|
||||
return (
|
||||
<WeightSlider
|
||||
name={this.props.weightedType.type.name}
|
||||
weight={this.props.weightedType.weight}
|
||||
onChange={(weight) => {
|
||||
this.props.onChange({
|
||||
...this.props.weightedType,
|
||||
weight,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
// @flow
|
||||
|
||||
import React from "react";
|
||||
import {shallow} from "enzyme";
|
||||
|
||||
import {WeightSlider} from "./WeightSlider";
|
||||
import {defaultWeightedNodeType, NodeTypeConfig} from "./NodeTypeConfig";
|
||||
import {inserterNodeType} from "../../adapters/demoAdapters";
|
||||
|
||||
require("../../testUtil").configureEnzyme();
|
||||
|
||||
describe("app/credExplorer/weights/NodeTypeConfig", () => {
|
||||
describe("defaultWeightedNodeType", () => {
|
||||
it("sets default weight as specified in type", () => {
|
||||
const wnt = defaultWeightedNodeType(inserterNodeType);
|
||||
expect(wnt.weight).toEqual(wnt.type.defaultWeight);
|
||||
});
|
||||
});
|
||||
describe("NodeTypeConfig", () => {
|
||||
function example() {
|
||||
const onChange = jest.fn();
|
||||
const wnt = {
|
||||
type: inserterNodeType,
|
||||
weight: 0.125,
|
||||
};
|
||||
const element = shallow(
|
||||
<NodeTypeConfig onChange={onChange} weightedType={wnt} />
|
||||
);
|
||||
const slider = element.find(WeightSlider);
|
||||
return {onChange, wnt, slider};
|
||||
}
|
||||
it("sets up the weight slider", () => {
|
||||
const {wnt, slider} = example();
|
||||
expect(slider.props().name).toBe(wnt.type.name);
|
||||
expect(slider.props().weight).toBe(wnt.weight);
|
||||
});
|
||||
it("weight slider onChange works", () => {
|
||||
const {wnt, slider, onChange} = example();
|
||||
slider.props().onChange(9);
|
||||
const updated = {...wnt, weight: 9};
|
||||
expect(onChange).toHaveBeenCalledTimes(1);
|
||||
expect(onChange.mock.calls[0][0]).toEqual(updated);
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue