Skip to content

Commit

Permalink
Rest client binding, diagram refresh, settings, loader add, etc
Browse files Browse the repository at this point in the history
  • Loading branch information
nikitaeverywhere committed Nov 24, 2016
1 parent e32a35d commit 2c2a873
Show file tree
Hide file tree
Showing 13 changed files with 3,951 additions and 132 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Preview
-------

![Screenshot](https://cloud.githubusercontent.com/assets/4989256/20325678/5efeecde-ab8e-11e6-8d8d-f4955a1afa4d.png)
![Screenshot](https://cloud.githubusercontent.com/assets/4989256/20610106/becaeac6-b29d-11e6-987b-670998ac048e.png)

Usage
-----
Expand Down Expand Up @@ -39,3 +40,13 @@ gulp
```

Then, open `build/static/index.html` file.

To install test REST client, run the following:

```bash
import
```

This will put `src/cls/EntityBrowser/Router.cls` class into your Caché (change the `import.*`
script), and after you set up a web application, go to configure app settings by clicking setting
button in the top right corner.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "iknow-entity-browser",
"version": "0.0.8",
"version": "0.1.0",
"description": "Visualizer for iKnow entities",
"main": "gulpfile.babel.js",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion src/cls/EntityBrowser/Router.cls
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ ClassMethod AppendChildObjects(ByRef pObjects, ByRef pGraph, ByRef pEntityTokens
}
set tNodeObj = {"id": (tNodeID), "label": (pEntityTokens(tEntIDx)), "type": "entity", "entities": [ (tEntObj) ]}
do pObjects.nodes.%Push(tNodeObj)
set tEdgeObj = {"origin": (pParentNodeID), "destination": (tNodeID), "type": (tEdgeType)}
set tEdgeObj = {"source": (pParentNodeID), "target": (tNodeID), "type": (tEdgeType)}
do pObjects.edges.%Push(tEdgeObj)

set tSC = ..AppendChildObjects(.pObjects, .pGraph, .pEntityTokens, tNodeID, pLevel+1)
Expand Down
16 changes: 16 additions & 0 deletions src/static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,22 @@ <h1>Selected Nodes</h1>
</div>
<div id="settings">
<i id="closeSettingsToggle" class="ui icon-close"></i>
<h1>General Settings</h1>
<div>
<div>
<b>Data source:</b>
<input type="text" value="http://localhost" id="settings.host" autosize placeholder="http://host.name"/>
: <input id="settings.port" autosize type="number" placeholder="port" value="57772"/>
/ <input id="settings.webAppName" type="text" placeholder="domain" value="EntityBrowser"/>
/domain/ <input id="settings.domain" type="text" placeholder="domain" value="1"/>
/
<select id="settings.queryType">
<option value="related">related</option>
<option value="similar">similar</option>
</select>
/ <input autosize placeholder="seed string" id="settings.seed" value="crew"/>
</div>
</div>
</div>
</div>
</body>
Expand Down
259 changes: 134 additions & 125 deletions src/static/js/graph/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,27 @@ import { updateSelectedNodes } from "../tabular";
import { getGraphData } from "../model";
import { updateSelection, setLastSelectedNode } from "../selection";

export function update () {

var graph = getGraphData();

var shiftKey, ctrlKey,
width = window.innerWidth,
height = window.innerHeight;

var zoomer = d3.zoom()
.scaleExtent([1/4, 40])
let shiftKey, ctrlKey,
width = window.innerWidth,
height = window.innerHeight,
foreverUniq = 0;

let svg = null,
brush = null,
node,
link,
links,
nodes,
zoomer = d3.zoom()
.scaleExtent([1/4, 100])
.on("zoom", () => {
view.attr("transform", d3.event.transform);
});

var dragger = d3.drag()
}),
dragger = d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended);

d3.select(window)
.on("keydown", keyDown)
.on("keyup", keyUp);

var svg = d3.select("#graph")
.call(zoomer);

var view = svg
.append("g")
.attr("class", "view");

var brush = view.append("g")
.datum(() => { return { selected: false, previouslySelected: false }; })
.attr("class", "brush");

// var color = d3.scaleOrdinal(d3.schemeCategory20);

var simulation = d3.forceSimulation()
.on("end", dragended),
simulation = d3.forceSimulation()
.force("link",
d3.forceLink()
.distance(d => 50 + (d.source.radius + d.target.radius) * 2)
Expand All @@ -48,25 +32,125 @@ export function update () {
d3.forceManyBody()
.strength(d => { return -10 * d.radius; })
)
.force("center", d3.forceCenter(width / 2, height / 2));
.force("center", d3.forceCenter(width / 2, height / 2)),
brusher = d3.brush()
.extent([[-9999999, -9999999], [9999999, 9999999]])
.on("start.brush", () => {
if (!d3.event.sourceEvent) return;
node.each((d) => {
d.previouslySelected = ctrlKey && d.selected;
});
})
.on("brush.brush", () => {
if (!d3.event.sourceEvent) return;
let extent = d3.event.selection;
if (!extent)
return;
node.classed("selected", (d) => {
let selected = (extent[0][0] <= d.x && d.x < extent[1][0]
&& extent[0][1] <= d.y && d.y < extent[1][1]);
if (selected) setLastSelectedNode(d);
return d.selected = d.previouslySelected ^ selected;
});
})
.on("end.brush", () => {
if (!d3.event.sourceEvent) return;
setTimeout(() => {
brush.call(brusher.move, null);
updateSelection();
}, 25);
}),
view = null;

function ticked () {
link
.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y);
node
.attr("transform", (d) => `translate(${ d.x },${ d.y })`)
}

function dragstarted (d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}

function dragged (d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}

function dragended (d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}

function keyDown () {
shiftKey = d3.event.shiftKey || d3.event.metaKey;
ctrlKey = d3.event.ctrlKey;

if (d3.event.keyCode == 67) { // the 'c' key
// do stuff
}

if (ctrlKey) {
brush.select('.overlay').style('cursor', 'crosshair');
brush.call(brusher);
d3.event.preventDefault();
}
}

function keyUp () {
shiftKey = d3.event.shiftKey || d3.event.metaKey;
ctrlKey = d3.event.ctrlKey;

var link = view.append("g")
.attr("class", "links")
.selectAll("line")
.data(graph.edges)
.enter().append("line")
brush.call(brusher)
.on(".brush", null);

brush.select('.overlay').style('cursor', 'auto');
}

export function init () {
svg = d3.select("#graph")
.call(zoomer);
view = svg
.append("g")
.attr("class", "view");
brush = view.append("g")
.datum(() => { return { selected: false, previouslySelected: false }; })
.attr("class", "brush");
links = view.append("g").attr("class", "links");
nodes = view.append("g").attr("class", "nodes");
link = links.selectAll("line");
node = nodes.selectAll(".node");
d3.select(window)
.on("keydown", keyDown)
.on("keyup", keyUp);
}

export function update () {

let graph = getGraphData();

link = link
.data(graph.edges, (d) => foreverUniq++);
link.exit().remove();
link = link.enter().append("line")
.attr("class", d => d.type === "similar"
? "similar"
: d.type === "related"
? "related"
: "other"
);

var node = view.append("g")
.attr("class", "nodes")
.selectAll(".node")
.data(graph.nodes)
.enter().append("g")
node = node
.data(graph.nodes, (d) => foreverUniq++);
node.exit().remove();
node = node.enter().append("g")
.attr("class", "node")
.call(dragger)
.on("dblclick", () => d3.event.stopPropagation())
Expand All @@ -80,106 +164,31 @@ export function update () {
updateSelection();
});

var circle = node.append("circle")
node.append("circle")
.attr("r", d => d.radius);

node.append("text")
.attr("dy", ".3em")
.attr("style", d => `font-size:${ Math.round(d.radius / 2) }px`)
.text(d => d.label);

node.exit().remove();
link.exit().remove();

simulation
.nodes(graph.nodes)
.on("tick", ticked);

simulation.force("link")
.links(graph.edges);

var brusher = d3.brush()
.extent([[-9999999, -9999999], [9999999, 9999999]])
.on("start.brush", () => {
if (!d3.event.sourceEvent) return;
node.each((d) => {
d.previouslySelected = ctrlKey && d.selected;
});
})
.on("brush.brush", () => {
if (!d3.event.sourceEvent) return;
var extent = d3.event.selection;
if (!extent)
return;
node.classed("selected", (d) => {
let selected = (extent[0][0] <= d.x && d.x < extent[1][0]
&& extent[0][1] <= d.y && d.y < extent[1][1]);
if (selected) setLastSelectedNode(d);
return d.selected = d.previouslySelected ^ selected;
});
})
.on("end.brush", () => {
if (!d3.event.sourceEvent) return;
setTimeout(() => {
brush.call(brusher.move, null);
updateSelection();
}, 25);
});
simulation.restart();

brush.call(brusher)
.on(".brush", null);

brush.select('.overlay').style('cursor', 'auto');

for (var i = 100; i > 0; --i) simulation.tick();

function ticked () {
link
.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y);
node
.attr("transform", (d) => `translate(${ d.x },${ d.y })`)
}

function dragstarted (d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}

function dragged (d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}

function dragended (d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}

function keyDown () {
shiftKey = d3.event.shiftKey || d3.event.metaKey;
ctrlKey = d3.event.ctrlKey;

if (d3.event.keyCode == 67) { // the 'c' key
// do stuff
}

if (ctrlKey) {
brush.select('.overlay').style('cursor', 'crosshair');
brush.call(brusher);
d3.event.preventDefault();
}
}

function keyUp () {
shiftKey = d3.event.shiftKey || d3.event.metaKey;
ctrlKey = d3.event.ctrlKey;

brush.call(brusher)
.on(".brush", null);

brush.select('.overlay').style('cursor', 'auto');
}
for (let i = 100; i > 0; --i) simulation.tick();

}
8 changes: 6 additions & 2 deletions src/static/js/index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { update } from "./graph";
import * as graph from "./graph";
import * as tabular from "./tabular";
import * as details from "./details";
import * as settings from "./settings";
import * as source from "./source";
import * as model from "./model";

window.init = () => {

update();
tabular.init();
details.init();
settings.init();
source.init();
graph.init();
model.update(() => graph.update());

};
Loading

0 comments on commit 2c2a873

Please sign in to comment.