Commit 26d50853 authored by Matija Obreza's avatar Matija Obreza

Node properties include weight (number)

- If child sum !== 100, paint it red
parent 6c4033a9
......@@ -47,38 +47,24 @@
</div>
</div>
<div id="RenameNodeModal" class="reveal" data-reveal aria-labelledby="modalTitle" aria-hidden="true" role="dialog">
<h2 id="modalTitle">Rename Node</h2>
<form id="RenameNodeForm">
<div id="NodePropertiesModal" class="reveal" data-reveal aria-labelledby="modalTitle" aria-hidden="true" role="dialog">
<h2 id="modalTitle">Node properties</h2>
<form id="NodePropertiesForm">
<input type="hidden" id="NodeAction" value="create" />
<div class="row">
<div class="large-12 columns">
<label>
Node name
<input type="text" class="inputName" id='RenameNodeName' placeholder="node name"/>
<input type="text" class="inputName" id='NodeName' placeholder="Node name" />
</label>
</div>
</div>
<div class="row">
<div class="large-8 columns">
&nbsp;
</div>
<div class="large-4 columns">
<a href="#" data-close class="button info closeModal">Cancel</a>
<button type="submit" class="button success">Rename</button>
</div>
</div>
</form>
<a class="close-button" data-close aria-label="Close">&#215;</a>
</div>
<div id="CreateNodeModal" class="reveal" data-reveal aria-labelledby="modalTitle" aria-hidden="true" role="dialog">
<h2 id="modalTitle">Create Node</h2>
<form id="CreateNodeForm">
<div class="row">
<div class="large-12 columns">
<label>Node name
<input type="text" class="inputName" id='CreateNodeName' placeholder="node name"/>
</label>
<label>
Relative weight <em>[0 &mdash; 100]</em>
<input type="text" class="inputName" id='NodeWeight' placeholder="100" />
</label>
</div>
</div>
<div class="row">
......@@ -87,14 +73,13 @@
</div>
<div class="large-4 columns">
<a href="#" data-close class="button info closeModal">Cancel</a>
<button type="submit" class="button success">Create</button>
<button type="submit" class="button success">Confirm</button>
</div>
</div>
</form>
<a class="close-button" data-close aria-label="Close">&#215;</a>
</div>
<div id="ImportTreeModal" class="reveal" data-reveal aria-labelledby="modalTitle" aria-hidden="true" role="dialog">
<h2 id="modalTitle">Upload tree data</h2>
<form>
......
......@@ -23,42 +23,66 @@ function generateUUID(){
return uuid;
};
function hasChildren(d) {
return d !== null && (d.children ? d.children.length > 0 : (d._children ? d._children.length > 0 : false));
};
function sumChildrenWeights(d) {
if (hasChildren(d)) {
let sum = 0;
if (d.children) {
for (let ch of d.children) {
sum += ch.weight || 0;
}
} else if (d._children) {
for (let ch of d._children) {
sum += ch.weight || 0;
}
}
return sum;
} else {
return 100; // fake it
}
};
export function create_node() {
console.log('Creating node');
console.log('Creating new node');
if (create_node_parent && create_node_modal_active) {
if (create_node_parent._children != null) {
create_node_parent.children = create_node_parent._children;
create_node_parent._children = null;
}
if (create_node_parent.children == null) {
if (create_node_parent.children == null || create_node_parent.children == undefined) {
create_node_parent.children = [];
}
let id = generateUUID();
let name = $('#CreateNodeName').val();
let name = $('#NodeName').val();
let nodeWeight = parseFloat($('#NodeWeight').val());
let new_node = { 'name': name,
'weight': nodeWeight,
'id' : id,
'depth': create_node_parent.depth + 1,
'children': [],
'_children':null
};
console.log('Create Node name: ' + name);
console.log('Create Node name: ' + name, new_node);
create_node_parent.children.push(new_node);
create_node_modal_active = false;
$('#CreateNodeName').val('');
$('#NodeName').val('');
}
close_modal($('#CreateNodeModal'));
close_modal($('#NodePropertiesModal'));
outer_update(create_node_parent);
}
export function rename_node() {
console.log('Modifying node', node_to_rename);
if (node_to_rename && rename_node_modal_active) {
name = $('#RenameNodeName').val();
console.log('New Node name: ' + name);
let name = $('#NodeName').val();
let nodeWeight = parseFloat($('#NodeWeight').val());
console.log('Modified node name: ' + name);
node_to_rename.name = name;
node_to_rename.weight = nodeWeight;
rename_node_modal_active = false;
}
close_modal($('#RenameNodeModal'));
close_modal($('#NodePropertiesModal'));
outer_update(node_to_rename);
}
......@@ -106,21 +130,16 @@ export function draw_tree(container, treeData) {
var menu = [
{
title: 'Rename node',
title: 'Node properties',
action: function(elm, d, i) {
console.log('Rename node');
$("#RenameNodeName").val(d.name);
rename_node_modal_active = true;
node_to_rename = d;
$("#RenameNodeName").focus();
$('#RenameNodeModal').foundation('open');
}
},
{
title: 'Delete node',
action: function(elm, d, i) {
console.log('Delete node');
delete_node(d);
$('#NodeAction').val('modify');
$("#NodeName").val(d.name);
$("#NodeWeight").val(d.weight);
$('#NodePropertiesModal').foundation('open');
$("#NodeName").focus();
}
},
{
......@@ -129,15 +148,23 @@ export function draw_tree(container, treeData) {
console.log('Create child node');
create_node_parent = d;
create_node_modal_active = true;
$('#CreateNodeModal').foundation('open');
$('#CreateNodeName').focus();
$('#NodeAction').val('create');
$("#NodeName").val('');
$("#NodeWeight").val(100 - sumChildrenWeights(d));
$('#NodePropertiesModal').foundation('open');
$('#NodeName').focus();
}
}
]
},
{
title: 'Delete node',
action: function(elm, d, i) {
console.log('Delete node');
delete_node(d);
}
},
];
// A recursive helper function for performing some setup by walking through all nodes
function visit(parent, visitFn, childrenFn) {
if (!parent) return;
......@@ -401,23 +428,16 @@ export function draw_tree(container, treeData) {
// color a node properly
function colorNode(d) {
let result = "#fff";
if (d.synthetic == true) {
result = (d._children || d.children) ? "darkgray" : "lightgray";
}
else {
if (d.type == "USDA") {
result = (d._children || d.children) ? "orangered" : "orange";
} else if (d.type == "Produce") {
result = (d._children || d.children) ? "yellowgreen" : "yellow";
} else if (d.type == "RecipeIngredient") {
result = (d._children || d.children) ? "skyblue" : "royalblue";
} else {
result = "lightsteelblue"
}
}
return result;
if (hasChildren(d)) {
if (sumChildrenWeights(d) === 100) {
return 'lightgreen';
} else {
return 'red';
}
} else {
return 'lightsteelblue';
}
}
// Function to update the temporary connector indicating dragging affiliation
......@@ -556,7 +576,7 @@ export function draw_tree(container, treeData) {
return d.children || d._children ? "end" : "start";
})
.text(function(d) {
return d.name;
return `${d.name} [${d.weight}%]`;
})
.style("fill-opacity", 0);
......@@ -565,7 +585,7 @@ export function draw_tree(container, treeData) {
.attr('class', 'ghostCircle')
.attr("r", 30)
.attr("opacity", 0.2) // change this to zero to hide the target area
.style("fill", "red")
.style("fill", "red")
.attr('pointer-events', 'mouseover')
.on("mouseover", function(node) {
overCircle(node);
......@@ -583,7 +603,7 @@ export function draw_tree(container, treeData) {
return d.children || d._children ? "end" : "start";
})
.text(function(d) {
return d.name;
return `${d.name} [${d.weight}%]`;
});
// Change the circle fill depending on whether it has children and is collapsed
......
......@@ -31,7 +31,8 @@ const TREE_STORAGE_NAME = 'lastTree';
// We need to remove parent property from all nodes to avoid an error with converting circular structure to JSON
const cleanTreeJson = (node) => {
const keepProperties = ['name'];
const keepProperties = ['name', 'weight'];
console.log('Cleaning', node);
const copy = {};
if (node === null || node === undefined) {
......@@ -42,14 +43,19 @@ const cleanTreeJson = (node) => {
copy[n] = node[n];
}
let ch = [];
if (node['children']) {
const ch = [];
for (let child of node['children']) {
node['children'].forEach((child) => {
ch.push(cleanTreeJson(child));
}
copy['children'] = ch;
});
} else if (node['_children']) {
node['_children'].forEach((child) => {
ch.push(cleanTreeJson(child));
});
}
copy['children'] = ch;
console.log('Cleaned', copy);
return copy;
};
......@@ -74,8 +80,10 @@ const restoreLastTree = () => {
console.log('localStorage not available');
return null;
}
let lastTree = JSON.parse(window.localStorage.getItem(TREE_STORAGE_NAME) || '{}');
console.log('Read tree from localStorage', lastTree)
let lastTree = JSON.parse(window.localStorage.getItem(TREE_STORAGE_NAME) || null);
if (lastTree !== null) {
console.log('Read tree from localStorage', lastTree);
}
return lastTree;
}
......@@ -103,18 +111,15 @@ $('document').ready(function() {
}, 5000);
}
$('form#RenameNodeForm').submit((e) => {
$('form#NodePropertiesForm').submit((e) => {
// console.log('Submit renamenode form');
e.preventDefault();
rename_node();
rememberCurrentTree(getTree());
return false;
});
$('form#CreateNodeForm').submit((e) => {
// console.log('Submit createnode form');
e.preventDefault();
create_node();
const action = $('#NodeAction').val();
if (action === 'create') {
create_node();
} else if (action === 'modify') {
rename_node();
}
rememberCurrentTree(getTree());
return false;
});
......@@ -165,7 +170,7 @@ $('document').ready(function() {
});
// $('.closeModal').on('click', () => {
// $('#RenameNodeModal').foundation('open', 'close');
// $('#NodePropertiesModal').foundation('open', 'close');
// });
$('#instructionsBtn').on('click', () => {
......@@ -180,7 +185,8 @@ $('document').ready(function() {
const resetTree = () => {
let newTree = {
"name": "Entire genepool"
name: 'Entire genepool',
weight: 100,
};
draw_tree($('#tree-container'), newTree);
rememberCurrentTree(newTree);
......@@ -221,7 +227,7 @@ $('document').ready(function() {
{
if (window.localStorage) {
let lastTree = restoreLastTree();
if (lastTree) {
if (lastTree !== null) {
draw_tree($('#tree-container'), lastTree);
} else {
resetTree();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment