summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2020-06-13 23:57:19 +0200
committerBent Bisballe Nyeng <deva@aasimon.org>2020-06-13 23:57:19 +0200
commitb2d6e2b4ac56e4ece3ecbe3f98d64ea9bd107151 (patch)
tree3770666c838745ce7a947a837e93f635ebf8555a
parent7c054c7d99285610267aa80a4f9c9cd166edf71a (diff)
Refactor the way node hierarchies are being represented. Add state attribute.
-rw-r--r--src/ws/munia.css61
-rw-r--r--src/ws/node.js146
-rw-r--r--src/ws/view.js143
3 files changed, 239 insertions, 111 deletions
diff --git a/src/ws/munia.css b/src/ws/munia.css
index 8eeebba..38b435f 100644
--- a/src/ws/munia.css
+++ b/src/ws/munia.css
@@ -27,12 +27,20 @@ body
border-width: 1px;
border-color: black;
border-radius: 3px;
- padding: 6px;
- margin: 10px;
-/* max-width: 800px;*/
+ padding: 0px;
+ margin: 0px;
margin-left: auto;
margin-right: auto;
- overflow: hidden;
+}
+
+.node + .node
+{
+ margin-top: 12px;
+}
+
+.node .data
+{
+ background-color: grey;
}
.node .id
@@ -52,9 +60,27 @@ body
pointer-events: none;
}
+.node .state
+{
+ float: right;
+ padding-left: 5px;
+ padding-right: 5px;
+ background: transparent;
+ pointer-events: none;
+}
+
+.node .description
+{
+ clear: both;
+ padding-left: 5px;
+ background: transparent;
+ pointer-events: none;
+}
+
.node .edit
{
border-color: red;
+ pointer-events: all;
/*
border: inherit;
padding: inherit;
@@ -63,30 +89,33 @@ body
*/
}
-.node .add_button
+.node .button
{
float: right;
display: inline-box;
width: 1em;
height: 1em;
- font-size: 0.5em;
+ font-size: 0.7em;
vertical-align: text-center;
text-align: center;
border: solid green 2px;
cursor: pointer;
+ pointer-events: auto;
}
-.node .collapse_button
+.node .children
{
- float: right;
- display: inline-box;
- width: 1em;
- height: 1em;
- font-size: 0.5em;
- vertical-align: text-center;
- text-align: center;
- border: solid green 2px;
- cursor: pointer;
+ padding: 6px;
+ min-height: 5px;
+ border: dotted 1px black;
+ overflow: hidden;
+}
+
+.collapsed
+{
+ background-image: linear-gradient(to bottom, rgba(0,0,0,0), rgba(0,0,0,0.6));
+ max-height: 16px;
+ padding: 16px;
}
.board
diff --git a/src/ws/node.js b/src/ws/node.js
index fa97368..dff7056 100644
--- a/src/ws/node.js
+++ b/src/ws/node.js
@@ -33,6 +33,11 @@ function findNode(id, subscribeid)
return null;
}
+function findNodeFromString(idstr)
+{
+ return findNode(idFromStr(idstr), subscriptionIdFromStr(idstr));
+}
+
function Node(id, subscribeid)
{
this.id = id;
@@ -40,13 +45,6 @@ function Node(id, subscribeid)
this.children = new Array();
this.attributes = {};
this.parent = null;
-
- // Elements:
- this.element = document.createElement("div");
- this.div_id = document.createElement("span");
- this.div_id.setAttribute("class", "id");
- this.div_title = document.createElement("span");
- this.div_title.setAttribute("class", "title");
}
Node.prototype.dump = function()
@@ -94,8 +92,7 @@ Node.prototype.addChild = function(node, insertBeforeId)
if(this.children[i].id == insertBeforeId)
{
this.children.splice(i - 1, 0, node);
- // Insert after id, title, add button and collapse button (ie. + 4)
- this.element.insertBefore(node.element, this.element.childNodes[i + 4]);
+ this.children_element.insertBefore(node.element, this.children_element.childNodes[i]);
inserted = true;
break;
}
@@ -104,17 +101,17 @@ Node.prototype.addChild = function(node, insertBeforeId)
if(inserted == false)
{
this.children.push(node);
- this.element.appendChild(node.element);
+ this.children_element.appendChild(node.element);
}
- if(this.children.length == 0)
- {
- this.element.style.backgroundColor = "#aaa";
- }
- else
- {
- this.element.style.backgroundColor = "#aaaa81";
- }
+// if(this.children.length == 0)
+// {
+// this.element.style.backgroundColor = "#aaa";
+// }
+// else
+// {
+// this.element.style.backgroundColor = "#aaaa81";
+// }
};
Node.prototype.removeChild = function(node)
@@ -124,32 +121,57 @@ Node.prototype.removeChild = function(node)
return e.id != node.id;
});
node.parent = null;
- this.element.removeChild(node.element);
-
- if(this.children.length == 0)
- {
- this.element.style.backgroundColor = "#aaa";
- }
- else
- {
- this.element.style.backgroundColor = "#aaaa81";
- }
+ this.children_element.removeChild(node.element);
+
+// if(this.children.length == 0)
+// {
+// this.element.style.backgroundColor = "#aaa";
+// }
+// else
+// {
+// this.element.style.backgroundColor = "#aaaa81";
+// }
};
Node.prototype.create = function()
{
+ // Node root element
+ this.element = document.createElement("div");
+
+ // Element for title, description, state, etc...
+ this.data_element = document.createElement("div");
+ this.data_element.className = "data";
+ this.data_element.style.pointerEvents = "none";
+ this.element.appendChild(this.data_element);
+
+ // Root element for child nodes.
+ this.children_element = document.createElement("div");
+ this.children_element.className = "children";
+ this.element.appendChild(this.children_element);
+
+
+ this.div_id = document.createElement("span");
+ this.div_id.setAttribute("class", "id");
+ this.data_element.appendChild(this.div_id);
+
+ this.div_title = document.createElement("span");
+ this.div_title.setAttribute("class", "title");
+ var id_txt = document.createTextNode(this.id);
+ this.div_id.appendChild(id_txt);
+ this.data_element.appendChild(this.div_title);
+ this.setAttribute("title", "");
+
var node = this.element;
node.name = "node";
node.setAttribute("class", "node");
node.setAttribute("ondblclick", "editTitle(event)");
- //node.setAttribute("onclick", "showHideChildren(this, event)");
node.setAttribute("ondrop", "drop(event)");
node.setAttribute("ondragenter", "dragenter(event)");
node.setAttribute("ondragover", "dragover(event)");
node.setAttribute("ondragleave", "dragleave(event)");
node.setAttribute("draggable", true);
- node.setAttribute("ondragstart", "drag(this, event)");
+ node.setAttribute("ondragstart", "drag(event)");
node.setAttribute("ondragend", "dragEnd(event)");
node.setAttribute("nodeid", this.id);
@@ -161,19 +183,28 @@ Node.prototype.create = function()
add_child_button.name = "add_button";
add_child_button.setAttribute("onclick", "addChild(event)");
add_child_button.setAttribute("nodeid", this.id);
- add_child_button.setAttribute("class", "add_button");
+ add_child_button.setAttribute("class", "button");
var txt_plus = document.createTextNode("+");
add_child_button.appendChild(txt_plus);
- node.appendChild(add_child_button);
+ this.data_element.appendChild(add_child_button);
var collapse_button = document.createElement("div");
collapse_button.name = "add_button";
collapse_button.setAttribute("onclick", "collapse(event)");
collapse_button.setAttribute("nodeid", this.id);
- collapse_button.setAttribute("class", "collapse_button");
- var txt_plus = document.createTextNode("v");
- collapse_button.appendChild(txt_plus);
- node.appendChild(collapse_button);
+ collapse_button.setAttribute("class", "button");
+ var txt_v = document.createTextNode("v");
+ collapse_button.appendChild(txt_v);
+ this.data_element.appendChild(collapse_button);
+
+ this.state_element = document.createElement("div");
+ this.state_element.name = "state";
+ this.state_element.setAttribute("onclick", "changeState(event)");
+ this.state_element.setAttribute("nodeid", this.id);
+ this.state_element.setAttribute("class", "state");
+ var txt_state = document.createTextNode("");
+ this.state_element.appendChild(txt_state);
+ this.data_element.appendChild(this.state_element);
/*
var subscribe_button = document.createElement("div");
@@ -183,7 +214,7 @@ Node.prototype.create = function()
subscribe_button.setAttribute("style", "float: left; display: inline-box; width:14px; height: 14px; border: solid green 2px; cursor: pointer;");
var txt_plus = document.createTextNode("+");
subscribe_button.appendChild(txt_plus);
- node.appendChild(subscribe_button);
+ this.data_element.appendChild(subscribe_button);
var unsubscribe_button = document.createElement("div");
unsubscribe_button.name = "unsubscribe_button";
@@ -192,24 +223,20 @@ Node.prototype.create = function()
unsubscribe_button.setAttribute("style", "float: left; display: inline-box; width:14px; height: 14px; border: solid red 2px; cursor: pointer;");
var txt_minus = document.createTextNode("-");
unsubscribe_button.appendChild(txt_minus);
- node.appendChild(unsubscribe_button);
+ this.data_element.appendChild(unsubscribe_button);
*/
- this.element.appendChild(this.div_id);
- var id_txt = document.createTextNode(this.id);
- this.div_id.appendChild(id_txt);
- this.element.appendChild(this.div_title);
- this.setAttribute("title", "");
-
{
var collapsed = getCookie(node.id+"_collapsed") == "true";
if(collapsed)
{
- this.element.style.maxHeight = "32px";
+ //this.children_element.style.maxHeight = "16px";
+ this.children_element.classList.add('collapsed');
}
else
{
- this.element.style.maxHeight = "inherit";
+ //this.children_element.style.maxHeight = "inherit";
+ this.children_element.classList.remove('collapsed');
}
}
};
@@ -245,6 +272,33 @@ Node.prototype.setAttribute = function(name, value)
this.element.setAttribute("draggable", true);
}
}
+
+ if(name == "state")
+ {
+ var txt = this.state_element.firstChild;
+ if(txt != null)
+ {
+ this.state_element.removeChild(txt);
+ }
+ txt = document.createTextNode(value);
+ this.state_element.appendChild(txt);
+ if(value == "done")
+ {
+ this.state_element.style.color = "green";
+ }
+ else if(value == "in-progress")
+ {
+ this.state_element.style.color = "yellow";
+ }
+ else if(value == "blocked")
+ {
+ this.state_element.style.color = "red";
+ }
+ else
+ {
+ this.state_element.style.color = "black";
+ }
+ }
};
Node.prototype.getTitle = function()
diff --git a/src/ws/view.js b/src/ws/view.js
index 2c9d507..986e3f9 100644
--- a/src/ws/view.js
+++ b/src/ws/view.js
@@ -82,6 +82,11 @@ function deleteNode(id)
function getElementAfter(e)
{
+ if(e.target.className != "children")
+ {
+ return null;
+ }
+
var element_after = null;
var min_y_diff = 9999999999999;
for(i = 0; i < e.target.children.length; ++i)
@@ -102,15 +107,22 @@ function getElementAfter(e)
return element_after;
}
-function drag(target, e)
+function drag(e)
{
- e.dataTransfer.setData('id', target.id);
+ // e.target is always a node.element here
+ var id = e.target.id;
+ e.dataTransfer.setData('id', id);
e.stopPropagation(); // <--- this fixes the drag target problem
- update(idFromStr(target.id), "dragged", "true");
+ update(idFromStr(id), "dragged", "true");
}
function dragenter(e)
{
+ // Only highlight children areas
+ if(e.target.className != "children")
+ {
+ return;
+ }
e.target.style.backgroundColor = "#646588";
last_over = e.target;
}
@@ -118,6 +130,12 @@ function dragenter(e)
var last_after = null;
function dragover(e)
{
+// // Only highlight children areas
+// if(e.target.className != "children")
+// {
+// return;
+// }
+
e.preventDefault();
var after = getElementAfter(e);
@@ -134,11 +152,29 @@ function dragover(e)
function dragleave(e)
{
+ // Only highlight children areas
+ if(e.target.className != "children")
+ {
+ return;
+ }
+
e.target.style.backgroundColor = "#aaa";
}
function dragEnd(e)
{
+ e.stopPropagation();
+
+ // FIXME: This doesn't seem to work in Chromium 65
+ var id = e.dataTransfer.getData('id');
+ update(idFromStr(id), "dragged", "false");
+
+// // Only highlight children areas
+// if(e.target.className != "children")
+// {
+// return;
+// }
+
e.target.style.backgroundColor = "#aaa";
if(last_after != null)
@@ -154,20 +190,26 @@ function dragEnd(e)
}
e.preventDefault();
- e.stopPropagation();
-
- // FIXME: This doesn't seem to work in Chromium 65
- var id = e.dataTransfer.getData('id');
- update(idFromStr(id), "dragged", "false");
}
function drop(e)
{
+ e.stopPropagation();
+
+ // Only allow drops in children areas
+ if(e.target.className != "children")
+ {
+ return;
+ }
+
var id = e.dataTransfer.getData('id');
- update(idFromStr(id), "dragged", "false");
+ //update(idFromStr(id), "dragged", "false");
+ // Get drop id from targets parent (children tag inside the node)
+ var dropid = e.target.parentElement.id;
+ console.log("dropid: " + dropid);
// Prevent dropping on item itself
- if(id == e.target.id)
+ if(id == dropid)
{
return;
}
@@ -178,7 +220,7 @@ function drop(e)
{
before_id = idFromStr(element_after.id);
}
- move(idFromStr(id), idFromStr(e.target.id), before_id);
+ move(idFromStr(id), idFromStr(dropid), before_id);
}
function subscribeMe(target, e)
@@ -193,28 +235,6 @@ function unsubscribeMe(target, e)
unsubscribe(target.nodeid);
}
-function showHideChildren(target, e)
-{
- e.stopPropagation();
- updateid = idFromStr(target.id);
- if(target.style.backgroundColor != "red")
- {
- target.style.backgroundColor = "red";
- for(i = 1; i < target.childNodes.length; i++)
- {
- target.childNodes[i].style.display = "none";
- }
- }
- else
- {
- target.style.backgroundColor = "#aaa";
- for(i = 1; i < target.childNodes.length; i++)
- {
- target.childNodes[i].style.display = "block";
- }
- }
-}
-
function node_submit()
{
var data = document.getElementById("input_node_data");
@@ -238,52 +258,77 @@ var lineedit;
var lineeditparent;
function onKeyUpHandler(e)
{
+ var node = findNodeFromString(e.target.id);
+ if(node == null)
+ {
+ return; // no node
+ }
+
+ var lineedit = e.target;
+ var updateid = idFromStr(lineedit.id);
+
if(e.which == 13)
{ // enter
- lineeditparent.removeChild(lineedit);
- lineeditparent.nodeValue = 'updating...';
+ node.data_element.removeChild(lineedit);
+ //node.data_element.nodeValue = 'updating...';
update(updateid, "title", lineedit.value);
}
if(e.which == 27)
{ // escape
- lineeditparent.removeChild(lineedit);
+ node.data_element.removeChild(lineedit);
}
}
function onLostFocusHandler(e)
{
- lineeditparent.removeChild(lineedit);
+ var node = findNodeFromString(e.target.id);
+ if(node == null)
+ {
+ return; // no node
+ }
+
+ var lineedit = e.target;
+
+ node.data_element.removeChild(lineedit);
}
function editTitle(e)
{
e.stopPropagation();
- updateid = idFromStr(e.target.id);
- subscriptionId = subscriptionIdFromStr(e.target.id);
-
- var node = findNode(updateid, subscriptionId);
+ var node = findNodeFromString(e.target.id);
+ if(node == null)
+ {
+ return; // no node
+ }
- lineedit = document.createElement("input");
+ var lineedit = document.createElement("input");
lineedit.setAttribute("class", "edit");
lineedit.setAttribute("onkeyup", "onKeyUpHandler(event)");
lineedit.setAttribute("onblur", "onLostFocusHandler(event)");
lineedit.value = node.getTitle();
- e.target.appendChild(lineedit);
- //e.target.insertBefore(e.target.childNodes[2], lineedit);
- lineeditparent = e.target;
+ lineedit.id = e.target.id;
+ node.data_element.appendChild(lineedit);
+ //lineeditparent = e.target;
lineedit.focus();
}
function addChild(e)
{
e.stopPropagation();
- id = idFromStr(e.target.parentElement.id);
+ id = idFromStr(e.target.parentElement.parentElement.id);
create("x", id, -1);
}
function collapse(e)
{
- var id = e.target.parentElement.id;
+ var id = e.target.parentElement.parentElement.id;
+
+ var node = findNodeFromString(id);
+ if(node == null)
+ {
+ return; // no node
+ }
+
var collapsed = getCookie(id+"_collapsed") == "true";
collapsed = !collapsed;
setCookie(id+"_collapsed", collapsed?"true":"false");
@@ -291,10 +336,10 @@ function collapse(e)
e.stopPropagation();
if(collapsed)
{
- e.target.parentElement.style.maxHeight = "32px";
+ node.children_element.classList.add('collapsed');
}
else
{
- e.target.parentElement.style.maxHeight = "inherit";
+ node.children_element.classList.remove('collapsed');
}
}