Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show edge labels when hovering on connected nodes #45

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions app/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const DELETE_SELECTION = 'DELETE_SELECTION';
export const UPDATE_NODE = 'UPDATE_NODE';
export const UPDATE_EDGE = 'UPDATE_EDGE';
export const UPDATE_CAPTION = 'UPDATE_CAPTION';
export const SET_HOVERED_NODE = 'SET_HOVERED_NODE';
export const PRUNE_GRAPH = 'PRUNE_GRAPH';
export const LAYOUT_CIRCLE = 'LAYOUT_CIRCLE';
export const DELETE_ALL = 'DELETE_ALL';
Expand Down Expand Up @@ -176,6 +177,10 @@ export function updateCaption(captionId, data) {
return { type: UPDATE_CAPTION, captionId, data };
}

export function setHoveredNode(node) {
return { type: SET_HOVERED_NODE, node };
}

export function pruneGraph() {
return { type: PRUNE_GRAPH };
}
Expand Down
10 changes: 5 additions & 5 deletions app/components/Edge.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default class Edge extends BaseComponent {
this.bindAll('_handleDragStart', '_handleDrag', '_handleDragStop', '_handleClick', '_handleTextClick');
// need control point immediately for dragging
let { cx, cy } = this._calculateGeometry(props.edge.display);
this.state = merge({}, props.edge.display, { cx, cy });
this.state = merge({}, props.edge.display, { cx, cy }, {"hoveringOnNode": props.hoveringOnConnectedNode});
}

render() {
Expand All @@ -21,7 +21,8 @@ export default class Edge extends BaseComponent {
let width = 1 + (e.display.scale - 1) * 5;
let selected = this.props.selected;
let highlighted = e.display.status == "highlighted";

let hoveredOn = this.props.hoveringOnConnectedNode ? "hoveredOn" : null;

return (
<DraggableCore
ref={(c) => this.draggable = c}
Expand All @@ -30,7 +31,7 @@ export default class Edge extends BaseComponent {
onStart={this._handleDragStart}
onDrag={this._handleDrag}
onStop={this._handleDragStop}>
<g id={sp.groupId} className={classNames({ edge: true, selected, highlighted })}>
<g id={sp.groupId} className={classNames({ edge: true, selected, highlighted, hoveredOn })}>
{ selected ? <path
className="edge-selection"
d={sp.curve}
Expand Down Expand Up @@ -76,7 +77,7 @@ export default class Edge extends BaseComponent {
}

componentWillReceiveProps(props) {
let newState = merge({ label: null, url: null }, props.edge.display);
let newState = merge({ label: null, url: null }, props.edge.display, {"hoveringOnNode": props.hoveringOnConnectedNode});
this.setState(newState);
}

Expand Down Expand Up @@ -180,7 +181,6 @@ export default class Edge extends BaseComponent {
yb = y1;
is_reverse = true;
}

// generate curve offset if it doesn't exist
if (!cx || !cy) {
cx = -(ya - y) * eds.curveStrength;
Expand Down
13 changes: 12 additions & 1 deletion app/components/Graph.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,15 @@ export default class Graph extends BaseComponent {
);
}

hasHovered(){

}

// COMPONENT LIFECYCLE

shouldComponentUpdate() {
return true;
}

componentDidMount() {
this.mounted = true;
Expand All @@ -59,8 +67,10 @@ export default class Graph extends BaseComponent {
// RENDERING

_renderEdges() {
let connected = GraphModel.edgesConnectedToNode(this.props.graph, this.props.hoveredNode);
return values(this.props.graph.edges).map((e, i) =>
<Edge
hoveringOnConnectedNode={includes(connected, e)}
ref={(c) => { this.edges[e.id] = c; if (c) { c.graph = this; } }}
key={e.id}
edge={e}
Expand All @@ -77,7 +87,8 @@ export default class Graph extends BaseComponent {
<Node
ref={(c) => { this.nodes[n.id] = c; if (c) { c.graph = this; } }}
key={n.id}
node={n}
node={n}
setHoveredNode={this.props.setHoveredNode}
graph={this.props.graph}
zoom={this.props.zoom}
selected={this.props.selection && includes(this.props.selection.nodeIds, n.id)}
Expand Down
14 changes: 12 additions & 2 deletions app/components/Node.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import Helpers from '../models/Helpers';
export default class Node extends BaseComponent {
constructor(props) {
super(props);
this.bindAll('_handleDragStart', '_handleDrag', '_handleDragStop', '_handleClick');
this.bindAll('_handleDragStart', '_handleDrag', '_handleDragStop', '_handleClick', '_highlightEdges', '_removeHighlightEdges');
this.state = props.node.display;
}

Expand All @@ -33,7 +33,9 @@ export default class Node extends BaseComponent {
id={groupId}
className="node"
transform={transform}
onClick={this._handleClick}>
onClick={this._handleClick}
onMouseEnter={this._highlightEdges}
onMouseLeave={this._removeHighlightEdges}>
<NodeCircle node={n} selected={this.props.selected} />
{ this.state.name ? <NodeLabel node={n} /> : null }
</g>
Expand All @@ -60,6 +62,14 @@ export default class Node extends BaseComponent {
};
}

_highlightEdges(){
this.props.setHoveredNode(this.props.node.id);
}

_removeHighlightEdges(){
this.props.setHoveredNode(null);
}

// while dragging node and its edges are updated only in state, not store
_handleDrag(e, ui) {
if (this.props.isLocked) return;
Expand Down
9 changes: 6 additions & 3 deletions app/components/Root.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ import { loadGraph, showGraph,
deleteSelection, deselectAll,
pruneGraph, layoutCircle,
addNode, addEdge, addCaption,
updateNode, updateEdge, updateCaption,
updateNode, updateEdge, updateCaption, setHoveredNode,
deleteAll, addSurroundingNodes,
fetchInterlocks,
toggleEditTools, toggleAddForm,
setNodeResults, setTitle,
loadAnnotations, showAnnotation, createAnnotation,
toggleAnnotations, updateAnnotation,
toggleAnnotations, updateAnnotation,
deleteAnnotation, moveAnnotation,
toggleHelpScreen, setSettings, toggleSettings } from '../actions';
import Graph from './Graph';
Expand Down Expand Up @@ -45,7 +45,7 @@ class Root extends Component {
}

render() {
let { dispatch, graph, selection, isEditor, isLocked, title,
let { dispatch, graph, selection, isEditor, hoveredNode, isLocked, title,
showEditTools, showSaveButton, showHelpScreen,
hasSettings, graphSettings, showSettings, onSave,
currentIndex, annotation, annotations, visibleAnnotations } = this.props;
Expand Down Expand Up @@ -157,6 +157,8 @@ class Root extends Component {
<Graph
ref={(c) => { this.graph = c; if (c) { c.root = this; } }}
{...this.props}
setHoveredNode={(nodeId) => dispatch(setHoveredNode(nodeId))}
hoveredNode={this.props.hoveredNode}
graph={annotatedGraph ? annotatedGraph : graph}
isEditor={isEditor}
isLocked={isLocked}
Expand Down Expand Up @@ -360,6 +362,7 @@ function select(state) {
graph: state.graph.present,
canUndo: state.graph.past.length > 0,
canRedo: state.graph.future.length > 0,
hoveredNode: state.editTools.hoveredNode,
selection: state.selection,
zoom: state.zoom,
showEditTools: state.editTools.visible,
Expand Down
6 changes: 5 additions & 1 deletion app/main.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { loadGraph, showGraph, newGraph,
pruneGraph, layoutCircle,
setHighlights, clearHighlights,
loadAnnotations, setTitle,
toggleEditTools } from './actions';
toggleEditTools, setHoveredNode } from './actions';
import Graph from './models/Graph';
import merge from 'lodash/object/merge';
import assign from 'lodash/object/assign';
Expand Down Expand Up @@ -220,6 +220,10 @@ class Oligrapher {
return this.root.getWrappedInstance().props.graph.captions[captionId];
}

setHoveredNode(node) {
this.root.dispatchProps.dispatch(setHoveredNode(node));
}

prune() {
this.root.dispatchProps.dispatch(pruneGraph());
}
Expand Down
1 change: 1 addition & 0 deletions app/models/Graph.js
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,7 @@ class Graph {
let sin = Math.sin(angle);
return { x: x * cos - y * sin, y: x * sin + y * cos };
}

}

module.exports = Graph;
37 changes: 37 additions & 0 deletions app/reducers/__tests__/editTools-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
jest.unmock("../editTools");
jest.unmock('../../actions');
jest.unmock("lodash");

import reducer from "../editTools";
import {setHoveredNode} from '../../actions';


describe("editTools reducer", ()=>{

it("should return initial state", () => {
expect(reducer(undefined, {})).toEqual({visible: false, addForm: null,
nodeResults: [], hoveredNode: null });
});

describe('SET_HOVERED_NODE', ()=>{

it('sets hoveredNode to the nodeId passed in', ()=>{
expect(reducer({hoveredNode: null}, {
type: 'SET_HOVERED_NODE',
node: "nodeA"
})).toEqual({"hoveredNode": "nodeA"})
});

it('sets hoveredNode to null when null is passed in', ()=>{
expect(reducer({hoveredNode: "nodeB"}, {
type: 'SET_HOVERED_NODE',
node: null
})).toEqual({"hoveredNode": null})
});

});




});
8 changes: 6 additions & 2 deletions app/reducers/editTools.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { TOGGLE_EDIT_TOOLS, TOGGLE_ADD_FORM, SET_NODE_RESULTS,
CREATE_ANNOTATION } from '../actions';
CREATE_ANNOTATION, SET_HOVERED_NODE } from '../actions';

const initState = {
visible: false,
addForm: null,
nodeResults: []
nodeResults: [],
hoveredNode: null
};

export default function editTools(state = initState, action) {
Expand All @@ -24,6 +25,9 @@ export default function editTools(state = initState, action) {
case CREATE_ANNOTATION:
return Object.assign({}, state, { visible: false });

case SET_HOVERED_NODE:
return Object.assign({}, state, { hoveredNode: action.node });

default:
return state;
}
Expand Down
3 changes: 3 additions & 0 deletions app/reducers/graph.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { LOAD_GRAPH, SHOW_GRAPH, NEW_GRAPH,
SET_HIGHLIGHTS, TOGGLE_EDIT_TOOLS } from '../actions';
import Graph from '../models/Graph';
import Edge from '../models/Edge';
import merge from 'lodash/object/merge';


export default function graph(state = null, action) {
let newState, graph;
Expand Down Expand Up @@ -98,6 +100,7 @@ export default function graph(state = null, action) {
case SET_HIGHLIGHTS:
return Graph.setHighlights(state, action.highlights, action.otherwiseFaded);


default:
return state;
}
Expand Down
2 changes: 1 addition & 1 deletion app/styles/oligrapher.css
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ a.nodeLabel text tspan {
display: none;
}

#oligrapherContainer:hover .edge:hover text, .edge.selected text, .edge.highlighted text {
#oligrapherContainer:hover .edge:hover text, .edge.selected text, .edge.highlighted text, #oligrapherContainer:hover .edge.hoveredOn text{
display: inline;
}

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,4 @@
"<rootDir>/node_modules/"
]
}
}
}