prodio
Version:
Simplified project management
1,610 lines (1,468 loc) • 106 kB
JavaScript
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({"./web/src/js/app.js":[function(require,module,exports){
var controllers = require('../lib/controllers.js');
var Partials = require('../lib/partials.js');
var handlebarsHelpers = require('../lib/handlebarsHelpers.js');
var Loader = require('../lib/loader.js');
var Support = require('../lib/support.js');
var el = Support.el;
var els = Support.els;
var Application = function(){
var self = this;
partials = new Partials({
path: "partials/",
ext: ".html"
});
partials.preload(function(){
self.init();
});
};
Application.prototype.displayPage = function(pageName, data){
var path = pageName.split('/');
var nav = path.shift();
partials.get(pageName, function(err, template){
if(err){
console.error(err.stack||err);
return;
}
try{
var pane = el('#outlet');
var controllerName = el('#'+pageName).getAttribute('data-controller');
if(nav==='index'){
nav = el('nav li a[href="#home"]');
}else{
nav = el('nav li a[href="#'+(nav||'home')+'"]');
}
pane.innerHTML = template(data||{}, {helpers: handlebarsHelpers});
if(controllerName){
controllers.create(pane, controllerName, data);
}
var elm, elms = els(pane, '[data-controller]'), i, l=elms.length;
for(i=0; i<l; i++){
elm = elms[i];
controllerName = elm.getAttribute('data-controller');
controllers.create(elm, controllerName, data);
}
}catch(e){
throw e;
}
});
};
Application.prototype.init = function(){
var app = this;
var nav = Satnav({
html5: false,
force: true,
poll: 100
});
nav
.navigate({
path: '/',
directions: (function(){
var e = el('script#home');
var dataApi = e?e.getAttribute('data-api'):false;
if(dataApi){
return Loader.get(dataApi, function(err, data){
return app.displayPage('home', err||data);
});
}
return app.displayPage('home');
})
})
;
var e = els('script[nav]'), i=0, l=e.length;
for(; i<l; i++){
nav = nav.navigate(
(function(id, linkTo, dataApi){
return {
path: linkTo,
directions: dataApi?function(params){
var uri = dataApi.replace(/{([^}]+)}/g, function(full, sym){
return params[sym];
});
Loader.get(uri, function(err, data){
app.displayPage(id, err||data);
});
}:function(params){
app.displayPage(id);
}
}
})(e[i].getAttribute('id'), e[i].getAttribute('nav'), e[i].getAttribute('data-api'))
);
}
nav
.change(function(params, old){
app.displayPage('loading');
nav.resolve();
return this.defer;
})
.otherwise('/');
;
nav.go();
};
module.exports = new Application();
},{"../lib/controllers.js":"/home/jdarling/prodio/web/web/src/lib/controllers.js","../lib/handlebarsHelpers.js":"/home/jdarling/prodio/web/web/src/lib/handlebarsHelpers.js","../lib/loader.js":"/home/jdarling/prodio/web/web/src/lib/loader.js","../lib/partials.js":"/home/jdarling/prodio/web/web/src/lib/partials.js","../lib/support.js":"/home/jdarling/prodio/web/web/src/lib/support.js"}],"./web/src/js/controllers/charts/barchartcontroller.js":[function(require,module,exports){
var Bar = require('../../charts/bar.js');
var applyChartConfiguration = require('../../../lib/charts').applyChartConfiguration;
var Support = require('../../../lib/support.js');
var el = Support.el;
var els = Support.els;
var BarChartController = function(container, data){
var self = this;
self.container = container;
self.chart= Bar();
applyChartConfiguration('chart', container, self.chart, ['width', 'height', 'identity', 'duration', 'style']);
if(!data){
try{
var src = container.innerText;
if(src){
var f = new Function('return '+src+';');
data = f();
}
container.innerHTML = '';
}catch(e){
console.log(e);
}
}
if(data){
self.update(data);
}
};
BarChartController.prototype.update = function(data){
var self = this;
self.data = data = data || self.data;
if(!data){
return;
}
d3.select(self.container)
.datum(data)
.call(self.chart)
;
};
require('../../../lib/controllers.js').register('BarChart', BarChartController);
},{"../../../lib/charts":"/home/jdarling/prodio/web/web/src/lib/charts.js","../../../lib/controllers.js":"/home/jdarling/prodio/web/web/src/lib/controllers.js","../../../lib/support.js":"/home/jdarling/prodio/web/web/src/lib/support.js","../../charts/bar.js":"/home/jdarling/prodio/web/web/src/js/charts/bar.js"}],"./web/src/js/controllers/charts/linechartcontroller.js":[function(require,module,exports){
var Line = require('../../charts/line.js');
var applyChartConfiguration = require('../../../lib/charts').applyChartConfiguration;
var LineChartController = function(container, data){
var self = this;
self.container = container;
self.chart= Line();
applyChartConfiguration('chart', container, self.chart, ['width', 'height', 'identity', 'duration', 'style']);
if(!data){
try{
var src = container.innerText;
if(src){
var f = new Function('return '+src+';');
data = f();
}
container.innerHTML = '';
}catch(e){
console.log(e);
}
}
if(data){
self.update(data);
}
};
LineChartController.prototype.update = function(data){
var self = this;
self.data = data = data || self.data;
if(!data){
return;
}
d3.select(self.container)
.datum(data)
.call(self.chart)
;
};
require('../../../lib/controllers').register('LineChart', LineChartController);
},{"../../../lib/charts":"/home/jdarling/prodio/web/web/src/lib/charts.js","../../../lib/controllers":"/home/jdarling/prodio/web/web/src/lib/controllers.js","../../charts/line.js":"/home/jdarling/prodio/web/web/src/js/charts/line.js"}],"./web/src/js/controllers/charts/mindmapcontroller.js":[function(require,module,exports){
var MindMap = require('../../charts/mindmap.js');
var applyChartConfiguration = require('../../../lib/charts').applyChartConfiguration;
var Loader = require('../../../lib/loader');
var support = require('../../../lib/support');
var el = support.el;
var MindMapController = function(container, data){
var self = this;
self.project_id = data.root._id;
self.container = container;
self.chart = MindMap();
applyChartConfiguration('mm', container, self.chart, ['width', 'height', 'identity', 'duration', 'style']);
if(!data){
try{
var src = container.innerText;
if(src){
var f = new Function('return '+src+';');
data = f();
}
container.innerHTML = '';
}catch(e){
console.log(e);
}
}
self.bindEvents(container);
if(data){
self.update(data, support.paramByName('focus'));
}
self.dataAttributePrefix = 'mm';
};
MindMapController.prototype.select = function(node){
// Find previously selected, unselect
d3.select(".selected").classed("selected", false);
// Select current item
d3.select(node).classed("selected", true);
};
MindMapController.prototype.selectNode = function(target){
var self = this;
if(target){
var sel = d3.select(self.container).selectAll('.node');
sel = sel.filter(function(d){return d._id==(target._id||target)});
sel = (sel[0]||[])[0];
if(sel){
self.select(sel);
}
}
};
MindMapController.prototype.bindEvents = function(container){
var self = this;
var getDirection = function(data){
if(!data){
return 'root';
}
if(data.position){
return data.position;
}
return getDirection(data.parent);
};
var update = function(node){
var id = node._id;
self.chart.update(node);
setTimeout(function(){
self.selectNode(id);
}, self.chart.duration()+100);
};
self.chart.click(function(d){
self.select(this);
});
Mousetrap.bind('left', function(){
// left key pressed
var selection = d3.select(".node.selected")[0][0];
if(selection){
var data = selection.__data__;
var dir = getDirection(data);
switch(dir){
case('right'):
case('root'):
self.selectNode(data.parent || data.left[0]);
break;
case('left'):
self.selectNode((data.children||[])[0]);
break;
default:
break;
}
}
return false;
});
Mousetrap.bind('right', function(){
// right key pressed
var selection = d3.select(".node.selected")[0][0];
if(selection){
var data = selection.__data__;
var dir = getDirection(data);
switch(dir){
case('left'):
case('root'):
self.selectNode(data.parent || data.right[0]);
break;
case('right'):
self.selectNode((data.children||[])[0]);
break;
default:
break;
}
}
return false;
});
Mousetrap.bind('up', function(){
// up key pressed
var selection = d3.select(".node.selected")[0][0];
if(selection){
var data = selection.__data__;
var dir = getDirection(data);
switch(dir){
case('root'):
break;
case('left'):
case('right'):
var p = data.parent, nl = p.children || [], i=1;
if(p[dir]){
nl = p[dir];
}
l = nl.length;
for(; i<l; i++){
if(nl[i]._id === data._id){
self.selectNode(nl[i-1]);
break;
}
}
break;
}
}
return false;
});
Mousetrap.bind('down', function(){
// down key pressed
// up key pressed
var selection = d3.select(".node.selected")[0][0];
if(selection){
var data = selection.__data__;
var dir = getDirection(data);
switch(dir){
case('root'):
break;
case('left'):
case('right'):
var p = data.parent, nl = p.children || [], i=0;
if(p[dir]){
nl = p[dir];
}
l = nl.length;
for(; i<l-1; i++){
if(nl[i]._id === data._id){
self.selectNode(nl[i+1]);
break;
}
}
break;
}
}
return false;
});
Mousetrap.bind('ins', function(){
var selection = d3.select(".node.selected")[0][0];
if(selection){
self.unbindEvents();
var data = selection.__data__;
var dir = getDirection(data);
var name = alertify.prompt('New name', function(insert, name){
if(insert && name){
if(dir==='root'){
dir = data.right.length>data.left.length?'left':'right';
}
var cl = data[dir] || data.children || data._children;
if(!cl){
cl = data.children = [];
}
return Loader.post('/api/v1/project/'+self.project_id+'/item',
{
data: {
parent_id: data._id,
name: name,
type: 'unknown'
}
},
function(err, rec){
self.bindEvents();
if(err){
return alertify.error(err.error||err);
}
cl.push({
name: rec.name,
position: rec.dir,
_id: rec._id,
description: rec.description,
rec: rec
});
return update(data);
});
}
if(insert && !name){
alertify.error('Must supply a valid name!');
}
self.bindEvents();
});
}
});
Mousetrap.bind('del', function(){
var selection = d3.select(".node.selected")[0][0];
if(selection){
var data = selection.__data__;
var dir = getDirection(data);
var root = data.parent;
if(dir==='root'){
alert('Can\'t delete root');
return;
}
var cl = data.parent[dir] || data.parent.children;
if(!cl){
alert('Could not locate children');
return;
}
var i = 0, l = cl.length;
for(; i<l; i++){
if(cl[i]._id === data._id){
self.unbindEvents();
alertify.confirm('Sure you want to delete '+data.name+'?', function(remove){
if(remove){
return Loader.delete('/api/v1/project/'+self.project_id+'/item/'+data._id, function(err, deleted){
self.bindEvents();
if(err){
return alertify.error(err.error||err);
}
cl.splice(i, 1);
update(root);
});
}
self.bindEvents();
});
break;
}
}
}
});
var editNodeName = function(){
var selection = d3.select(".node.selected")[0][0];
if(selection){
self.unbindEvents();
var data = selection.__data__;
var name = alertify.prompt('New text:', function(accepted, name){
self.bindEvents();
if(!accepted){
return;
}
if(name !== data.name){
var rec = data.rec;
var uri = data.parent?
'/api/v1/project/'+self.project_id+'/item/'+data._id:
'/api/v1/project/'+self.project_id;
rec.name = name;
return Loader.post(uri,
{
data: rec
},
function(err, rec){
self.bindEvents();
if(err){
return alertify.error(err.error||err);
}
data.name = rec.name;
data.rec = rec;
update(selection);
});
}
self.bindEvents();
}, data.name);
}
};
var editNode = function(){
var selection = d3.select(".node.selected")[0][0];
if(selection){
var data = selection.__data__;
if(data.parent){
return window.location.href = '#project/'+self.project_id+'/item/'+data._id;
}
return window.location.href = '#project/edit/'+self.project_id;
}
};
Mousetrap.bind('ctrl+enter', function(){
setTimeout(function(){
editNodeName();
}, 100);
});
Mousetrap.bind('enter', editNode);
self.chart.doubleClick(editNode);
Mousetrap.bind('esc', function(){
if(draggingNode){
selectedNode=null;
endDrag();
draggingNode=null;
}
});
var scanChildren = function(node, nodes, exclude){
if((exclude||[]).indexOf(node)===-1){
nodes.push(node);
}
(node.children||[]).forEach(function(node){
scanChildren(node, nodes);
});
return nodes;
};
var distance = function(firstObject, secondObject){
var xs = 0;
var xy = 0;
xs = secondObject.x0 - firstObject.x0;
xs = xs * xs;
ys = secondObject.y0 - firstObject.y0;
ys = ys * ys;
return Math.sqrt( xs + ys );
};
var findNearest = function(n, nodes){
var d = Number.MAX_VALUE, t, result;
nodes.forEach(function(node){
if(n._id !== node._id){
t = distance(n, node);
if(t<d){
result = node;
d = t;
}
}
});
return result;
};
var nodes, allNodes, dragStarted, draggingNode=null, selectedNode=null, movement;
// Define the drag listeners for drag/drop behaviour of nodes.
self.dragListener = d3.behavior.drag()
.on("dragstart", function(d) {
if (!d.parent) {
return;
}
nodes = scanChildren(d, []);
allNodes = scanChildren(self.data, [], nodes);
movement = {
x: 0,
y: 0
}
dragStarted = true;
d3.event.sourceEvent.stopPropagation();
// it's important that we suppress the mouseover event on the node being dragged. Otherwise it will absorb the mouseover event and the underlying node will not detect it d3.select(this).attr('pointer-events', 'none');
})
.on("drag", function(d) {
if (!d.parent) {
return;
}
if (dragStarted) {
movement.x+=d3.event.dx;
movement.y+=d3.event.dy;
if(Math.abs(movement.x)<20&&Math.abs(movement.y)<20){
return;
}
domNode = this;
initiateDrag(d, domNode);
}
selectedNode = findNearest(draggingNode, allNodes);
d.x0 += d3.event.dy;
d.y0 += d3.event.dx;
var node = d3.select(this);
node.attr("transform", "translate(" + d.y0 + "," + d.x0 + ")");
updateTempConnector();
}).on("dragend", function(d) {
if(!draggingNode){
return;
}
if (!d.parent) {
return;
}
domNode = this;
endDrag();
});
var updateTempConnector = function() {
var data = [];
if (draggingNode !== null && selectedNode !== null) {
// have to flip the source coordinates since we did this for the existing connectors on the original tree
data = [{
source: {
x: draggingNode.y0,
y: draggingNode.x0
},
target: {
x: selectedNode.y0,
y: selectedNode.x0
}
}];
}
var link = d3.select(el(self.container, 'svg g')).selectAll(".templink").data(data);
link.enter().append("path")
.attr("class", "templink")
.attr("d", d3.svg.diagonal())
.attr('pointer-events', 'none');
link.attr("d", d3.svg.diagonal());
link.exit().remove();
};
function endDrag() {
d3.select(domNode).attr('class', 'node');
updateTempConnector();
d3.select('.templink').remove();
if(draggingNode !== null){
var uri = draggingNode.parent?
'/api/v1/project/'+self.project_id+'/item/'+draggingNode._id:
'/api/v1/project/'+self.project_id;
if(selectedNode){
draggingNode.rec.parent_id = selectedNode.rec._id;
draggingNode.parent = selectedNode;
return Loader.post(uri,
{
data: draggingNode.rec
},
function(err, rec){
if(!selectedNode.children){
selectedNode.children=selectedNode._children||[];
selectedNode._children=null;
}
selectedNode.children.push(draggingNode);
self.updateNode(selectedNode);
draggingNode = null;
selectedNode = null;
});
}
}
selectedNode = null;
draggingNode.parent.children=draggingNode.parent._children||[];
draggingNode.parent._children=null;
draggingNode.parent.children.push(draggingNode);
self.updateNode(draggingNode.parent);
}
function initiateDrag(d, domNode) {
draggingNode = d;
d3.select(container).selectAll("g.node").sort(function(a, b) { // select the parent and sort the path's
if (a._id != draggingNode._id) return 1; // a is not the hovered element, send "a" to the back
else return -1; // a is the hovered element, bring "a" to the front
});
// if nodes has children, remove the links and nodes
if (nodes.length > 1) {
// remove link paths
links = self.chart.tree.links(nodes);
nodePaths = d3.select(container).selectAll("path.link")
.data(links, function(d) {
return d.target._id;
}).remove();
// remove child nodes
nodesExit = d3.select(container).selectAll("g.node")
.data(nodes, function(d) {
return d._id;
}).filter(function(d, i) {
if (d._id == draggingNode._id) {
return false;
}
return true;
}).remove();
}
// remove parent link
parentLink = self.chart.tree.links(self.chart.tree.nodes(draggingNode.parent));
d3.select(container).selectAll('path.link').filter(function(d, i) {
if (d.target._id == draggingNode._id) {
return true;
}
return false;
}).remove();
dragStarted = null;
}
};
MindMapController.prototype.unbindEvents = function(container){
Mousetrap.unbind('left');
Mousetrap.unbind('right');
Mousetrap.unbind('up');
Mousetrap.unbind('down');
Mousetrap.unbind('ins');
Mousetrap.unbind('del');
Mousetrap.unbind('enter');
};
MindMapController.prototype.updateNode = function(data){
var self = this;
d3.select(self.container)
//.datum(data)
.call(self.chart)
;
};
MindMapController.prototype.update = function(data, focus){
var self = this;
self.data = data = data || self.data;
if(!data){
return;
}
if(data.root && data.nodes && data.edges){
var tree = {}, nodes = {};
tree.name = data.root.name;
tree.children = [];
tree._id = data.root._id;
tree.rec = data.root;
tree.description = data.root.description;
nodes[data.root._id] = tree;
data.nodes.forEach(function(node){
nodes[node._id] = {
name: node.name,
_id: node._id,
rec: node,
description: node.description,
children: []
};
});
data.edges.forEach(function(edge){
if(nodes[edge.from] && nodes[edge.to]){
return nodes[edge.from].children.push(nodes[edge.to]);
}
if(!nodes[edge.from]){
var msg = 'Invalid: '+edge.to+' refrences '+edge.from+' that doesn\'t exist!';
console.log(msg);
return alertify.error(msg);
}
var msg = 'Invalid: '+edge.from+' refrences '+edge.to+' that doesn\'t exist!';
console.log(msg);
return alertify.error(msg);
});
self.data = data = tree;
}
self.chart.nodeClass(function(d){
return ('node '+(d.rec.status||'').replace(/\s+/g, '-').toLowerCase()).trim();
});
self.chart.nodeEnter(function(node){
node
.call(self.dragListener)
;
node.append('svg:circle')
.attr('r', 1e-6);
node.append('svg:text')
.attr('text-anchor', 'middle')
.attr('dy', 14)
.text(function(d){
return d.name;
})
.style('fill-opacity', 1);
});
d3.select(self.container)
.datum(data)
.call(self.chart)
;
setTimeout(function(){
self.selectNode(focus||data._id);
}, self.chart.duration()+100);
};
MindMapController.prototype.teardown = function(container){
var self = this;
self.unbindEvents(container);
self.container = null;
};
require('../../../lib/controllers').register('MindMap', MindMapController);
},{"../../../lib/charts":"/home/jdarling/prodio/web/web/src/lib/charts.js","../../../lib/controllers":"/home/jdarling/prodio/web/web/src/lib/controllers.js","../../../lib/loader":"/home/jdarling/prodio/web/web/src/lib/loader.js","../../../lib/support":"/home/jdarling/prodio/web/web/src/lib/support.js","../../charts/mindmap.js":"/home/jdarling/prodio/web/web/src/js/charts/mindmap.js"}],"./web/src/js/controllers/charts/piechartcontroller.js":[function(require,module,exports){
var Pie = require('../../charts/pie.js');
var applyChartConfiguration = require('../../../lib/charts').applyChartConfiguration;
var PieChartController = function(container, data){
var self = this;
self.container = container;
self.chart= Pie();
applyChartConfiguration('chart', container, self.chart, ['width', 'height', 'identity', 'duration', 'style']);
if(!data){
try{
var src = container.innerText;
if(src){
var f = new Function('return '+src+';');
data = f();
}
container.innerHTML = '';
}catch(e){
console.log(e);
}
}
if(data){
self.update(data);
}
};
PieChartController.prototype.update = function(data){
var self = this;
self.data = data = data || self.data;
if(!data){
return;
}
d3.select(self.container)
.datum(data)
.call(self.chart)
;
};
require('../../../lib/controllers').register('PieChart', PieChartController);
},{"../../../lib/charts":"/home/jdarling/prodio/web/web/src/lib/charts.js","../../../lib/controllers":"/home/jdarling/prodio/web/web/src/lib/controllers.js","../../charts/pie.js":"/home/jdarling/prodio/web/web/src/js/charts/pie.js"}],"./web/src/js/controllers/charts/scatterchartcontroller.js":[function(require,module,exports){
var Scatter = require('../../charts/scatter.js');
var applyChartConfiguration = require('../../../lib/charts').applyChartConfiguration;
var ScatterChartController = function(container, data){
var self = this;
self.container = container;
self.chart= Scatter();
applyChartConfiguration('chart', container, self.chart, ['width', 'height', 'identity', 'duration', 'style']);
if(!data){
try{
var src = container.innerText;
if(src){
var f = new Function('return '+src+';');
data = f();
}
container.innerHTML = '';
}catch(e){
console.log(e);
}
}
if(data){
self.update(data);
}
};
ScatterChartController.prototype.update = function(data){
var self = this;
self.data = data = data || self.data;
if(!data){
return;
}
if(data[0] instanceof Array){
var tmp = [];
var i, l = data.length, j, k, v;
for(i=0; i<l; i++){
k = data[i].length;
for(j=0; j<k; j++){
v = data[i][j];
v.x = i;
v.y = v.value;
tmp.push(v);
}
}
data = tmp;
}
d3.select(self.container)
.datum(data)
.call(self.chart)
;
};
require('../../../lib/controllers').register('ScatterChart', ScatterChartController);
},{"../../../lib/charts":"/home/jdarling/prodio/web/web/src/lib/charts.js","../../../lib/controllers":"/home/jdarling/prodio/web/web/src/lib/controllers.js","../../charts/scatter.js":"/home/jdarling/prodio/web/web/src/js/charts/scatter.js"}],"./web/src/js/controllers/charts/tableviewcontroller.js":[function(require,module,exports){
var Table = require('../../charts/table.js');
var applyChartConfiguration = require('../../../lib/charts').applyChartConfiguration;
var TableViewController = function(container, data){
var self = this;
self.container = container;
self.chart= Table();
applyChartConfiguration('table', container, self.chart, ['cols', 'width', 'height', 'identity', 'duration', 'style']);
self.chart
.updated(function(vis){
vis.attr('class', 'ink-table');
})
;
if(!data){
try{
var src = container.innerText;
if(src){
var f = new Function('return '+src+';');
data = f();
}
container.innerHTML = '';
}catch(e){
console.log(e);
}
}
if(data){
self.update(data.items?data.items:data);
}
self.dataAttributePrefix = 'table';
};
TableViewController.prototype.update = function(data){
var self = this;
var isAllArray = function(isArray, toCheck){
return isArray && (toCheck instanceof Array);
};
self.data = data = data || self.data;
if(!data){
return;
}
if(data[0] instanceof Array && data.reduce(isAllArray, true)){
tmp = [];
while(data.length){
tmp = tmp.concat(data.shift());
}
data = tmp;
}
d3.select(self.container)
.datum(data)
.call(self.chart)
;
};
require('../../../lib/controllers').register('TableView', TableViewController);
},{"../../../lib/charts":"/home/jdarling/prodio/web/web/src/lib/charts.js","../../../lib/controllers":"/home/jdarling/prodio/web/web/src/lib/controllers.js","../../charts/table.js":"/home/jdarling/prodio/web/web/src/js/charts/table.js"}],"./web/src/js/controllers/formsubmitter.js":[function(require,module,exports){
var controllers = require('../../lib/controllers.js');
var support = require('../../lib/support');
var Loader = require('../../lib/loader');
var el = support.el;
var els = support.els;
var socket = require('../../lib/socket');
helpers = require('../../lib/handlebarsHelpers')
var FormSubmitterController = function(container, data){
var self = this;
var target = container.dataset.target;
var message = container.dataset.message;
var doConfirm = function(message, callback){
alertify.confirm(message, callback);
};
var processAction = function(form, buttons, method, action, target){
buttons.forEach(function(button){
button.disabled = true;
});
if(method==='post'){
return Loader.postForm(form, function(err, response){
buttons.forEach(function(button){
button.disabled = false;
});
if(err){
return alertify.error(err.error||err.stack||err);
}
if(message && alertify){
alertify.success(message, 1000);
}
window.location.href=target.replace(/{(.+)}/, function(match, token){
return response[token];
});
});
}
Loader[method](action, function(err, response){
buttons.forEach(function(button){
button.disabled = false;
});
if(err){
return alertify.error(err.error||err.stack||err);
}
window.location.href=target.replace(/{(.+)}/, function(match, token){
return response[token];
});
});
};
var handleSubmit = self.handleSubmit = function(e){
if(e.target && (e.target.nodeName === 'FORM') || (e.target.nodeName === 'BUTTON')){
var form = el(container, 'form')||container;
var buttons = els(container, 'button');
var method = (e.target.nodeName === 'BUTTON'?e.target.dataset.method||'POST':'POST').toLowerCase();
var action = e.target.nodeName === 'BUTTON'?e.target.dataset.action||form.action:form.action;
var tgt = e.target.nodeName === 'BUTTON'?e.target.dataset.target||target:target;
var confirm = e.target.nodeName === 'BUTTON'?e.target.dataset.confirm:false;
e.preventDefault();
if(confirm){
return alertify.confirm(confirm, function(ok){
if(ok){
processAction(form, buttons, method, action, tgt);
}
});
}
processAction(form, buttons, method, action, tgt);
}
};
container.addEventListener('submit', handleSubmit);
container.addEventListener('click', handleSubmit);
};
FormSubmitterController.prototype.teardown = function(container){
var self = this;
container.removeEventListener('submit', self.handleSubmit);
container.removeEventListener('click', self.handleSubmit);
};
controllers.register('FormSubmitter', FormSubmitterController);
},{"../../lib/controllers.js":"/home/jdarling/prodio/web/web/src/lib/controllers.js","../../lib/handlebarsHelpers":"/home/jdarling/prodio/web/web/src/lib/handlebarsHelpers.js","../../lib/loader":"/home/jdarling/prodio/web/web/src/lib/loader.js","../../lib/socket":"/home/jdarling/prodio/web/web/src/lib/socket.js","../../lib/support":"/home/jdarling/prodio/web/web/src/lib/support.js"}],"./web/src/js/controllers/reportselector.js":[function(require,module,exports){
var controllers = require('../../lib/controllers.js');
var support = require('../../lib/support');
var Loader = require('../../lib/loader');
var el = support.el;
var els = support.els;
var val = support.val;
var socket = require('../../lib/socket');
helpers = require('../../lib/handlebarsHelpers')
var ReportSelectorController = function(container, data){
var self = this;
var target = container.dataset.target;
var message = container.dataset.message;
var handleSubmit = self.handleSubmit = function(e){
if(e.target && (e.target.nodeName === 'FORM') || (e.target.nodeName === 'BUTTON')){
var form = el(container, 'form')||container;
var elems = form.elements, i=0, l=elems.length, elem;
var data = {};
e.preventDefault();
for(; i<l; i++){
elem = elems[i];
if(elem.name){
data[elem.name] = val(elem);
}
}
var uri = data.report.replace(/{(.+)}/g, function(match, token){
return data[token];
});
window.location.href=uri;
}
};
container.addEventListener('submit', handleSubmit);
container.addEventListener('click', handleSubmit);
};
ReportSelectorController.prototype.teardown = function(container){
var self = this;
container.removeEventListener('submit', self.handleSubmit);
container.removeEventListener('click', self.handleSubmit);
};
controllers.register('ReportSelector', ReportSelectorController);
},{"../../lib/controllers.js":"/home/jdarling/prodio/web/web/src/lib/controllers.js","../../lib/handlebarsHelpers":"/home/jdarling/prodio/web/web/src/lib/handlebarsHelpers.js","../../lib/loader":"/home/jdarling/prodio/web/web/src/lib/loader.js","../../lib/socket":"/home/jdarling/prodio/web/web/src/lib/socket.js","../../lib/support":"/home/jdarling/prodio/web/web/src/lib/support.js"}],"./web/src/js/controllers/socketlistener.js":[function(require,module,exports){
var controllers = require('../../lib/controllers.js');
var support = require('../../lib/support');
var el = support.el;
var socket = require('../../lib/socket');
helpers = require('../../lib/handlebarsHelpers')
var SocketListenerController = function(container, data){
var self = this;
var src = container.innerHTML;
var message = container.dataset.message;
var template = Handlebars.compile(src);
var handleMessage = self.handleMessage = function(status){
container.innerHTML = template(status, {helpers: helpers});
};
socket.on(message, handleMessage);
if(data){
return handleMessage(data);
}
self.message = message;
container.innerHTML = '';
};
SocketListenerController.prototype.teardown = function(){
var self = this;
socket.removeListener(self.message, self.handleMessage);
};
controllers.register('SocketListener', SocketListenerController);
},{"../../lib/controllers.js":"/home/jdarling/prodio/web/web/src/lib/controllers.js","../../lib/handlebarsHelpers":"/home/jdarling/prodio/web/web/src/lib/handlebarsHelpers.js","../../lib/socket":"/home/jdarling/prodio/web/web/src/lib/socket.js","../../lib/support":"/home/jdarling/prodio/web/web/src/lib/support.js"}],"/home/jdarling/prodio/web/web/src/js/charts/bar.js":[function(require,module,exports){
module.exports = function Bar() {
var
margin = {top: 30, right: 10, bottom: 50, left: 50},
width = -1,
height = 420,
xRoundBands = 0.2,
xValue = function(d) { return d[0]; },
yValue = function(d) { return d[1]; },
xScale = d3.scale.ordinal(),
yScale = d3.scale.linear(),
yAxis = d3.svg.axis().scale(yScale).orient("left"),
xAxis = d3.svg.axis().scale(xScale),
xAxisBottom = d3.svg.axis().scale(xScale),
style = false,
onUpdate = false,
duration = 500,
getColor = false,
container,
enterBar = function(bar){
bar = bar.append("rect")
.attr("class", function(d, i) { return yValue(d) < 0 ? "negative" : "positive"; })
;
if(getColor){
bar.style('fill', getColor);
}
},
updateBar = function(bar){
bar.select('rect')
.attr("class", function(d) { return yValue(d) < 0 ? "negative" : "positive"; })
.attr("x", function(d) { return X(d); })
.attr("y", function(d) { return yValue(d) < 0 ? Y0() : Y(d); })
.attr("width", xScale.rangeBand())
.attr("height", function(d, i) { return Math.abs( Y(d) - Y0() ); })
;
},
exitBar = function(bar){
}
;
function chart(selection) {
selection.each(function(data) {
var w = width===-1?this.offsetWidth:width;
// Update the x-scale.
xScale
.domain(data.map(xValue))
.rangeRoundBands([0, w - margin.left - margin.right], xRoundBands);
var ys = d3.extent(data.map(yValue));
if(ys[0]>0){
ys[0] = 0;
}
// Update the y-scale.
yScale
.domain(ys)
.range([height - margin.top - margin.bottom, 0])
.nice();
// Select the svg element, if it exists.
var svg = d3.select(this).selectAll("svg").data([data]);
// Otherwise, create the skeletal chart.
var gEnter = svg.enter().append("svg").append("g");
gEnter.append("g").attr("class", "bars");
gEnter.append("g").attr("class", "y axis");
gEnter.append("g").attr("class", "x axis bottom");
gEnter.append("g").attr("class", "x axis zero");
// Update the outer dimensions.
svg .attr("width", w)
.attr("height", height);
// Update the inner dimensions.
var g = svg.select("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Update the bars.
var bars = svg.select(".bars");//.selectAll(".bar");//.data(data);
var bar = bars.selectAll('g.bar').data(data);
var barEnter = bar.enter()
.append("g")
.attr('class', 'bar')
;
enterBar(barEnter);
updateBar(bar.transition().duration(duration));
var barExit = bar.exit()
.remove()
;
exitBar(barExit);
// x axis at the bottom of the chart
g.select(".x.axis.bottom")
.attr("transform", "translate(0," + (height - margin.top - margin.bottom) + ")")
.call(xAxisBottom.orient("bottom"));
// zero line
g.select(".x.axis.zero")
.attr("transform", "translate(0," + Y0() + ")")
.call(xAxis.tickFormat("").tickSize(0));
// Update the y-axis.
g.select(".y.axis")
.call(yAxis);
g.selectAll(".axis line")
.attr('style', 'shape-rendering: crispEdges; stroke: black; fill: none;')
;
g.selectAll('.axis path')
.attr('style', 'shape-rendering: crispEdges; stroke: black; fill: none;')
;
if(style){
var key;
for(key in style){
svg.selectAll(key).attr('style', style[key]);
}
}
if(onUpdate){
onUpdate(svg);
}
});
}
// The x-accessor for the path generator; xScale ∘ xValue.
function X(d) {
return xScale(xValue(d));
}
function Y0() {
return yScale(0);
}
// The x-accessor for the path generator; yScale ∘ yValue.
function Y(d) {
return yScale(yValue(d));
}
chart.margin = function(_) {
if (!arguments.length) return margin;
margin.top = typeof _.top != 'undefined' ? _.top : margin.top;
margin.right = typeof _.right != 'undefined' ? _.right : margin.right;
margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;
margin.left = typeof _.left != 'undefined' ? _.left : margin.left;
return chart;
};
chart.duration = function(_) {
if (!arguments.length) return duration;
duration = _;
return chart;
};
chart.xRoundBands = function(_) {
if (!arguments.length) return xRoundBands;
xRoundBands = _;
return chart;
};
chart.width = function(_) {
if (!arguments.length) return width;
width = _;
return chart;
};
chart.height = function(_) {
if (!arguments.length) return height;
height = _;
return chart;
};
chart.x = function(_) {
if (!arguments.length) return xValue;
xValue = _;
return chart;
};
chart.y = function(_) {
if (!arguments.length) return yValue;
yValue = _;
return chart;
};
chart.barEnter = function(_){
if (!arguments.length) return enterBar;
enterBar = _;
return chart;
};
chart.barUpdate = function(_){
if (!arguments.length) return updateBar;
updateBar = _;
return chart;
};
chart.barExit = function(_){
if (!arguments.length) return exitBar;
exitBar = _;
return chart;
};
chart.colorize = function(_){
if (!arguments.length) return getColor;
getColor = _;
return chart;
};
chart.style = function(_) {
if (!arguments.length) return style;
style = _;
return chart;
};
chart.updated = function(_){
if (!arguments.length) return onUpdate;
onUpdate = _;
return chart;
};
chart.update = function() {
container.transition().duration(duration).call(chart);
};
return chart;
};
},{}],"/home/jdarling/prodio/web/web/src/js/charts/line.js":[function(require,module,exports){
module.exports = function Line() {
var
margin = {top: 30, right: 10, bottom: 50, left: 50},
width = -1,
height = 420,
duration = 500,
xValue = function(d) { return d[0]; },
yValue = function(d) { return d[1]; },
xScale = d3.scale.linear(),
yScale = d3.scale.linear(),
yAxis = d3.svg.axis().scale(yScale).orient("left"),
xAxis = d3.svg.axis().scale(xScale).orient("bottom"),
getText = function(d){ return d.text||''; },
getValue = function(d){
return yValue(d);
},
line = d3.svg.line()
.x(function(d,i) {
return xScale(i);
})
.y(function(d){
return yScale(yValue(d));
}),
enterSample = function(node){
var sample = node
.append('path').classed('line', true)
.style({
fill: 'none',
stroke: getColor||'black'
})
.attr('d', d3.svg.line().x(function(d, i){return xScale(i)}).y(height))
;
},
updateSample = function(node){
node.select('.line').attr('d', line);
var samples = node
.selectAll('.point')
.data(function(d){
return d;
});
var samplesEnter = samples.enter()
.append('circle').classed('point', true)
.style({
fill: getColor||'black',
stroke: getColor||'black'
})
.attr('transform', function(d, i) { return 'translate(' + xScale(i) + ', ' + (height+margin.top) + ')'; })
.attr('r', 4)
;
var points = node.selectAll('.point')
.attr('transform', function(d, i) { return 'translate(' + xScale(i) + ', ' + yScale(yValue(d)) + ')'; })
;
},
exitSample = function(node){
},
xRoundBands = 0.2,
style = false,
onUpdate = false,
getColor = false
;
function chart(selection) {
selection.each(function(data) {
var wid = width===-1?this.offsetWidth:width;
if(!(data[0] instanceof Array)){
data = [data];
}
// Update the x-scale.
xScale
.domain([0, d3.max(data, function(series) { return series.length-1; })])
.range([0, wid - margin.left - margin.right])
;
//var ys = d3.extent(data.map(yValue));
var ys = [
d3.min(data, function(s) { return d3.min(s, yValue) }),
d3.max(data, function(s) { return d3.max(s, yValue) })
];
// Update the y-scale.
yScale
.domain(ys)
.range([height - margin.top - margin.bottom, 0])
.nice();
// Select the svg element, if it exists.
var svg = d3.select(this).selectAll("svg").data([data]);
// Otherwise, create the skeletal chart.
var gEnter = svg.enter().append("svg").append("g");
gEnter.append("g").attr("class", "series");
gEnter.append("g").attr("class", "y axis");
gEnter.append("g").attr("class", "x axis bottom");
gEnter.append("g").attr("class", "x axis zero");
// Update the outer dimensions.
svg .attr("width", wid)
.attr("height", height);
// Update the inner dimensions.
var g = svg.select("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var lineGroup = svg.select(".series").selectAll("g.line")
.data(data);
var sampleEnter = lineGroup.enter().append('g').classed('line', true);
enterSample(sampleEnter);
updateSample(lineGroup);
/*
updateSample(lineGroup.transition()
.duration(duration));
*/
exitSample(lineGroup.exit().remove());
// x axis at the bottom of the chart
g.select(".x.axis.bottom")
.attr("transform", "translate(0," + (height - margin.top - margin.bottom) + ")")
.call(xAxis);
// Update the y-axis.
g.select(".y.axis")
.call(yAxis);
g.selectAll(".axis line")
.attr('style', 'shape-rendering: crispEdges; stroke: black; fill: none;')
;
g.selectAll('.axis path')
.attr('style', 'shape-rendering: crispEdges; stroke: black; fill: none;')
;
if(style){
var key;
for(key in style){
svg.selectAll(key).attr('style', style[key]);
}
}
if(onUpdate){
onUpdate(svg);
}
});
};
function X(d) {
return xScale(xValue(d));
}
function Y(d) {
return yScale(yValue(d));
}
chart.width = function(_) {
if (!arguments.length) return width;
width = _;
return chart;
};
chart.height = function(_) {
if (!arguments.length) return height;
height = _;
return chart;
};
chart.x = function(_) {
if (!arguments.length) return xValue;
xValue = _;
return chart;
};
chart.y = function(_) {
if (!arguments.length) return yValue;
yValue = _;
return chart;
};
chart.xScale = function(_) {
if (!arguments.length) return xScale;
xScale = _;
return chart;
};
chart.yScale = function(_) {
if (!arguments.length) return yScale;
yScale = _;
return chart;
};
chart.colorize = function(_){
if (!arguments.length) return getColor;
getColor = _;
return chart;
};
chart.text = function(_) {
if (!arguments.length) return getText;
getText = _;
return chart;
};
chart.value= function(_) {
if (!arguments.length) return getValue;
getValue = _;
return chart;
};
chart.duration = function(_) {
if (!arguments.length) return duration;
duration = _;
return chart;
};
chart.margin = function(_) {
if (!arguments.length) return margin;
margin.top = typeof _.top != 'undefined' ? _.top : margin.top;
margin.right = typeof _.right != 'undefined' ? _.right : margin.right;
margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;
margin.left = typeof _.left != 'undefined' ? _.left : margin.left;
return chart;
};
chart.updated = function(_){
if (!arguments.length) return onUpdate;
onUpdate = _;
return chart;
};
return chart;
};
},{}],"/home/jdarling/prodio/web/web/src/js/charts/mindmap.js":[function(require,module,exports){
/*
Sample Usage:
var myData = {
'name': 'Root',
'children': [
{
'name': 'Branch 1',
'children': [
{'name': 'Leaf 3'},
{'name': 'Leaf 4'}
]
},
{'name': 'Branch 2'}
]
};
var chart = MindMap()
.width(900)
.height(500)
;
d3.select('#chart svg')
.datum(myData)
.call(chart)
;
*/
var MindMap = module.exports = function(){
'use strict';
var
margin = {top: 20, left: 120, bottom: 20, right: 120},
width = -1,
height = 500,
duration = 500,
identity = '_id',
handleClick = function(){},
handleDoubleClick = function(){},
text = function(d){ return d.name; },
idx = 1,
style = false,
onUpdate = false,
nodeClass = null,
enterNode = function(node){
node.append('svg:circle')
.attr('r', 1e-6);
node.append('svg:text')
.attr('text-anchor', 'middle')
.attr('dy', 14)
.text(text)
.style('fill-opacity', 1);
},
updateNode = function(node){
node.select('text')
.text(text);
node.select('circle')
.attr('r', 4.5);
},
exitNode = function(node){
node.select('circle')
.attr('r', 1e-6);
node.select('text')
.style('fill-opacity', 1e-6);