diff --git a/css/tabs.css b/css/tabs.css index 6430c25..25aeeb0 100644 --- a/css/tabs.css +++ b/css/tabs.css @@ -20,7 +20,7 @@ body{ .tab-navigator{ display: block; width: 100%; - margin-left: 3px; + margin-left: 8px; } .tab-title{ @@ -93,6 +93,7 @@ body{ padding: 3px 12px; font-size: inherit; height: inherit; + padding-right: 50px; } .tab-split { @@ -530,4 +531,24 @@ body{ position: absolute; } +/* data charts */ + +div[data-chart-id]{ + margin-left: 10px; +} + + +/* bubble chart */ + +.bubbles-tooltip{ +position: absolute; +z-index: 10; +visibility: hidden; +color: white; +padding: 8px; +background-color: rgba(0, 0, 0, 0.75); +border-radius: 6px; +font: 12px sans-serif; +} /* */ + diff --git a/package.json b/package.json index 5de5a07..02213f2 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "toolbar": false }, "dependencies": { - "alasql": "^0.3.7", + "alasql": "^0.3.9", "async": "^1.4.2", "bootstrap": "3.3.2", "brace": "^0.9.0", diff --git a/src/Executor.js b/src/Executor.js index b0a991d..eb13e40 100644 --- a/src/Executor.js +++ b/src/Executor.js @@ -30,10 +30,10 @@ var TunnelPorts = {}; var PortSequence = 15000; function resolveHome(filepath) { - if (filepath[0] === '~') { + if (filepath.charAt(0) === '~') { return path.join(process.env.HOME, filepath.slice(1)); } - return path; + return filepath; } var Executor = { @@ -77,6 +77,7 @@ var Executor = { function(){callback();} ); client.on('error', function(e){ + console.log("test ssh error: "+e); client.end(); }); }, @@ -100,7 +101,12 @@ var Executor = { if (db_url.path == null){ var url_path= ''; } else { - var url_path = db_url.path; + if (db_url.path.indexOf('---') > 0){ // trim connection alias + var url_path = db_url.path.split('---')[0]; + url_path = decodeURI(url_path); // convert possible %20 etc + } else { + var url_path = decodeURI(db_url.path); + } } try{ @@ -111,6 +117,7 @@ var Executor = { } } catch(e){ + console.log(e); identity_file = null; } @@ -136,24 +143,36 @@ var Executor = { readyTimeout: 30000, }; + if (ssh_config.username == null){ + delete ssh_config.username; + } + if (ssh_config.port == null){ + delete ssh_config.port; + } + console.log(ssh_config); + var ssh_server = tunnel(ssh_config, function (error, server) { if (error){ + console.log(error); err_callback(id, "create ssh tunnel error: "+error); return; } + Tunnels[id] = server; TunnelPorts[id] = PortSequence; self.testSSH(id, ssh_config, function(){ return callback(self._getConnector(mapped_db_url)); - }, function(){ - err_callback(id, "ssh tunnel error"); + }, function(err){ + console.log(err); + err_callback(id, "ssh tunnel error: "+err); }); }); ssh_server.on('error', function(err, srv){ - self.releaseTunnel(id); + console.log(ssh_server.config); + err_callback(id, err); }); diff --git a/src/index.js b/src/index.js index 63c770c..7ef5eac 100644 --- a/src/index.js +++ b/src/index.js @@ -215,6 +215,9 @@ function mount_charts(){ if (chart_type == "bubble"){ // bubble chart is implemented not with c3 return mount_bubble_chart(chart_id, dataset); } + if (chart_type == "tree"){ // tree chart is implemented not with c3 + return mount_tree_chart(chart_id, dataset); + } var columns = dataset.data; data = { @@ -245,6 +248,21 @@ function mount_charts(){ function mount_bubble_chart(chart_id, dataset){ + if (d3.select("[data-chart-id='"+chart_id+"']").attr("mounted")){ // don't mount if already mounted + return; + } + console.log(d3.select("[data-chart-id='"+chart_id+"']").attr("mounted", "true")); // mark as mounted + + var display_selected_name = d3.select("[data-chart-id='"+chart_id+"']") + .append("div") + .attr("class", "bubble-chart-selected-name") + .html(" "); + + var display_selected_value = d3.select("[data-chart-id='"+chart_id+"']") + .append("div") + .attr("class", "bubble-chart-selected-value") + .html(" "); + var diameter = 500, //max size of the bubbles color = d3.scale.category20b(); //color category @@ -261,7 +279,9 @@ function mount_bubble_chart(chart_id, dataset){ var data = dataset.data; // convert list of lists to list of dicts - data = data.map(function(d){ return {name: d[0], value: d[1]}; }); + data = data.map(function(d){ + return {name: d[0], value: d[1]}; + }); // keep only leaf nodes var nodes = bubble.nodes({children:data}).filter(function(d) { return !d.children; }); @@ -275,14 +295,7 @@ function mount_bubble_chart(chart_id, dataset){ var tooltip = d3.select("[data-chart-id='"+chart_id+"']") .append("div") - .style("position", "absolute") - .style("z-index", "10") - .style("visibility", "hidden") - .style("color", "white") - .style("padding", "8px") - .style("background-color", "rgba(0, 0, 0, 0.75)") - .style("border-radius", "6px") - .style("font", "12px sans-serif") + .attr("class", "bubbles-tooltip") .text("tooltip"); //create the bubbles @@ -298,7 +311,13 @@ function mount_bubble_chart(chart_id, dataset){ .on("mousemove", function() { return tooltip.style("top", (d3.event.pageY-10)+"px").style("left",(d3.event.pageX+10)+"px"); }) - .on("mouseout", function(){return tooltip.style("visibility", "hidden");}); + .on("mouseout", function(){ + return tooltip.style("visibility", "hidden"); + }) + .on("click", function(d){ + display_selected_name.text(dataset.fields[0].name + ": " + d.name); + display_selected_value.text(dataset.fields[1].name + ": " + d.value); + }); //format the text for each bubble bubbles.append("text") @@ -317,3 +336,65 @@ function mount_bubble_chart(chart_id, dataset){ "font-size": "12px" }); } + + +//function mount_tree_chart(chart_id, dataset){ +// +// // drawing +// var margin = {top: 40, right: 40, bottom: 40, left: 40}, +// width = 960 - margin.left - margin.right, +// height = 500 - margin.top - margin.bottom; +// +// var tree = d3.layout.tree() +// .size([height, width]); +// +// var diagonal = d3.svg.diagonal() +// .projection(function(d) { return [d.y, d.x]; }); +// +// var svg = d3.select("[data-chart-id='"+chart_id+"']").append("svg") +// .attr("width", width + margin.left + margin.right) +// .attr("height", height + margin.top + margin.bottom) +// .append("g") +// .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); +// +// // data transformation +// +// var data = dataset.data; +// // convert list of lists to list of dicts +// data = data.map(function(d){ +// return {source: d[0], target: d[1], label: d[2]}; +// }); +// +// var nodesByName = {}; +// +// data.forEach(function(link) { +// var parent = link.source = nodeByName(link.source), +// child = link.target = nodeByName(link.target); +// if (parent.children) parent.children.push(child); +// else parent.children = [child]; +// }); +// +// var nodes = tree.nodes(data[0].source); +// +// +// // drawing again +// // Create the link lines. +// svg.selectAll(".link") +// .data(data) +// .enter().append("path") +// .attr("class", "link") +// .attr("d", diagonal); +// +// // Create the node circles. +// svg.selectAll(".node") +// .data(nodes) +// .enter().append("circle") +// .attr("class", "node") +// .attr("r", 4.5) +// .attr("cx", function(d) { return d.y; }) +// .attr("cy", function(d) { return d.x; }); +// +// function nodeByName(name) { +// return nodesByName[name] || (nodesByName[name] = {name: name}); +// } +//}