Skip to content

Commit

Permalink
added help and cypher export
Browse files Browse the repository at this point in the history
  • Loading branch information
jexp committed Feb 23, 2013
1 parent 5b57140 commit 657820d
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 2 deletions.
48 changes: 48 additions & 0 deletions cypher.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
function cypher(model) {
function props(element) {
var props = {};
if (element.label()) props.label = element.label();
element.properties().list().forEach(function (property) {
props[property.key] = property.value;
});
return props;
}

function isIdentifier(name) {
return /^[\w\d_]+$/.test(name);
}

function formatIdentifier(name) {
return isIdentifier(name) ? name : "`" + name + "`";
}

function render(props) {
var res = "";
for (var key in props) {
if (res.length > 0) res += ",";
if (props.hasOwnProperty(key)) {
res += formatIdentifier(key) + ":";
var value = props[key];
res += typeof value == "string" ? "'" + value + "'" : value;
}
}
return res.length == 0 ? "" : "{" + res + "}";
}

var statements = [];
model.nodeList().forEach(function (node) {
statements.push("(" + formatIdentifier("_"+node.id) +" "+ render(props(node)) + ")");
});
model.relationshipList().forEach(function (rel) {
statements.push(formatIdentifier("_"+rel.start.id) +
"-[:" + formatIdentifier(rel.label()||"RELATED_TO") +
// " " + TODO render(props(rel)) +
"]->"+
formatIdentifier("_"+rel.end.id)
)
});
if (statements.length==0) return "";
return "CREATE \n " + statements.join(",\n ");
};
if (typeof exports != "undefined") exports.cypher=cypher
gd.cypher=function(model) {return cypher(model || this.model());}
10 changes: 10 additions & 0 deletions graph-editor.css
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@ svg.graphdiagram {
margin-left: -400px;
}

.modal.export-cypher {
position: absolute;
width: 800px;
margin-left: -400px;
}

.modal.help {
width: 400px;
}

.modal.export-markup .modal-body {
overflow: hidden;
max-height: 70%;
Expand Down
43 changes: 41 additions & 2 deletions graph-editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,11 +225,23 @@
d3.select( ".modal.export-markup" ).classed( "hide", false );

var markup = formatMarkup();
d3.select( "textarea.code" )
d3.select( ".export-markup .modal-body textarea.code" )
.attr( "rows", markup.split( "\n" ).length * 2 )
.node().value = markup;
};

var showHelp = function ()
{
// appendModalBackdrop();
d3.select( ".modal.help" ).classed( "hide", false );
};

var hideHelp = function ()
{
// cancelModal();
d3.select( ".modal.help" ).classed( "hide", true );
};

function parseMarkup( markup )
{
var container = d3.select( "body" ).append( "div" );
Expand All @@ -241,7 +253,7 @@

var useMarkupFromMarkupEditor = function ()
{
var markup = d3.select( "textarea.code" ).node().value;
var markup = d3.select( ".export-markup .modal-body textarea.code" ).node().value;
graphModel = parseMarkup( markup );
save( markup );
draw();
Expand All @@ -263,6 +275,31 @@
} );
};

var openConsoleWithCypher = function (evt)
{
var cypher = d3.select(".export-cypher .modal-body textarea.code").node().value;
cypher = cypher.replace(/\n /g," ");
var url="http://console.neo4j.org"+
"?init=" + encodeURIComponent(cypher)+
"&query=" + encodeURIComponent("start n=node(*) return n");
d3.select( "#open_console" )
.attr( "href", url );
return true;
};

d3.select( "#open_console" ).on( "click", openConsoleWithCypher );

var exportCypher = function ()
{
appendModalBackdrop();
d3.select( ".modal.export-cypher" ).classed( "hide", false );

var statement = gd.cypher(graphModel);
d3.select( ".export-cypher .modal-body textarea.code" )
.attr( "rows", statement.split( "\n" ).length )
.node().value = statement;
};

function changeInternalScale() {
graphModel.internalScale(d3.select("#internalScale").node().value);
draw();
Expand All @@ -271,8 +308,10 @@

d3.select(window).on("resize", draw);
d3.select("#internalScale" ).on("change", changeInternalScale);
d3.select( "#helpButton" ).on( "mouseover", showHelp).on( "mouseout", hideHelp );
d3.select( "#exportMarkupButton" ).on( "click", exportMarkup );
d3.select( "#exportSvgButton" ).on( "click", exportSvg );
d3.select( "#exportCypherButton" ).on( "click", exportCypher );
d3.selectAll( ".modal-dialog" ).on( "click", function ()
{
d3.event.stopPropagation();
Expand Down
24 changes: 24 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,22 @@
<button class="btn" id="add_node_button"><i class="icon-plus"></i> Node</button>
<button class="btn" id="exportMarkupButton">Export Markup</button>
<button class="btn" id="exportSvgButton">Export SVG</button>
<button class="btn" id="exportCypherButton">Export Cypher</button>
<label for="internalScale">Internal Scale</label>
<input id="internalScale" type="range" min="0.1" max="5" value="1" step="0.01">
<button class="btn" id="helpButton"><i class="icon-question-sign"></i></button>
</div>

<!--<input id="node_name_editor" class="editor-field">-->
<div class="modal hide help">
<div class="modal-header">
<h3>Quick Help</h3>
</div>
<div class="modal-body">
<p><em>Double-click</em>: edit nodes and relationships</p>
<p><em>Shift-drag:</em> create relationships, drag onto existing nodes to connect</p>
</div>
</div>

<div class="modal hide export-markup">
<div class="modal-header">
Expand All @@ -32,6 +43,18 @@ <h3>Edit/Export markup</h3>
<a href="#" class="btn btn-primary" id="save_markup">Save</a>
</div>
</div>
<div class="modal hide export-cypher">
<div class="modal-header">
<h3>Export as Cypher</h3>
</div>
<div class="modal-body">
<textarea class="code">Some text</textarea>
</div>
<div class="modal-footer">
<a href="#" class="btn cancel btn-primary">Close</a>
<a href="#" target="_blank" class="btn" id="open_console">Open in Console</a>
</div>
</div>
<div class="modal hide pop-up-editor node">
<div class="modal-header">
<h3>Edit Node</h3>
Expand Down Expand Up @@ -62,6 +85,7 @@ <h3>Edit Node</h3>
<div id="canvas"></div>

<script type="text/javascript" src="graph-editor.js"></script>
<script type="text/javascript" src="cypher.js"></script>

</body>
</html>
71 changes: 71 additions & 0 deletions test/cypher/cypher-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
var vows = require("vows"),
assert = require("assert" ),
d3 = require("d3");

var suite = vows.describe("graph model");

require("../../graph-diagram.js");
var cypher=require("../../cypher.js").cypher;

suite.addBatch({
"format cypher": {
"empty model": {
topic: function() {
var model = gd.model();
return cypher(model);
},
"empty": function(statement) {
assert.equal(statement, "");
}
},
"one node": {
topic: function() {
var model = gd.model();
model.createNode("node_A").x(12).y(34).label("A" ).class("diagram-specific-class")
.properties().set("first name", "Alistair").set("location", "London").set("number",1).set("male",true);

return cypher(model);
},
"one node": function(statement) {
assert.match(statement,/CREATE/);
},
"with node id": function(statement) {
assert.match(statement,/\(_node_A /);
},
"with label": function(statement) {
assert.match(statement,/label:'A'/);
},
"with properties": function(statement) {
assert.match(statement,/`first name`:'Alistair'/);
assert.match(statement,/location:'London'/);
assert.match(statement,/number:1/);
assert.match(statement,/male:true/);
}
},
"two nodes and one relationship": {
topic: function() {
var model = gd.model();
var nodeA = model.createNode("node_A");
var nodeB = model.createNode("node B");
model.createRelationship(nodeA, nodeB).label("RELATED TO" ).class("diagram-specific-class");
return cypher(model);
},
"create statement": function(statement) {
assert.match(statement,/CREATE/);
},
"from A": function(statement) {
assert.match(statement,/\(_node_A \)/);
assert.match(statement,/_node_A-\[/);
},
"to B": function(statement) {
assert.match(statement,/\(`_node B` \)/);
assert.match(statement,/\]->`_node B`/);
},
"with label": function(statement) {
assert.match(statement,/\[:`RELATED TO`/);
}
}
}
});

suite.export(module);

0 comments on commit 657820d

Please sign in to comment.