rails_notebook 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/Rakefile +22 -0
- data/app/assets/javascripts/rails_notebook/application.js +13 -0
- data/app/assets/stylesheets/rails_notebook/application.css +15 -0
- data/app/controllers/rails_notebook/application_controller.rb +4 -0
- data/app/helpers/rails_notebook/application_helper.rb +4 -0
- data/app/views/layouts/rails_notebook/application.html.erb +14 -0
- data/config/routes.rb +2 -0
- data/lib/rails_notebook.rb +14 -0
- data/lib/rails_notebook/assets/d3.js +9553 -0
- data/lib/rails_notebook/assets/dagre-d3.js +17572 -0
- data/lib/rails_notebook/assets/jquery.jsonview.css +52 -0
- data/lib/rails_notebook/assets/jquery.jsonview.js +284 -0
- data/lib/rails_notebook/assets/jquery.qtip.min.css +2 -0
- data/lib/rails_notebook/assets/jquery.qtip.min.js +3 -0
- data/lib/rails_notebook/assets/jquery.tipsy.js +288 -0
- data/lib/rails_notebook/assets/kernel.css +7 -0
- data/lib/rails_notebook/assets/kernel.js +18 -0
- data/lib/rails_notebook/assets/kernel.json +1 -0
- data/lib/rails_notebook/assets/logo-32x32.png +0 -0
- data/lib/rails_notebook/assets/logo-64x64.png +0 -0
- data/lib/rails_notebook/assets/nv.d3.css +641 -0
- data/lib/rails_notebook/assets/nv.d3.js +13298 -0
- data/lib/rails_notebook/assets/rails_notebook.css +136 -0
- data/lib/rails_notebook/assets/rails_notebook.js +548 -0
- data/lib/rails_notebook/assets/tipsy.css +25 -0
- data/lib/rails_notebook/command.rb +104 -0
- data/lib/rails_notebook/engine.rb +9 -0
- data/lib/rails_notebook/profiler.rb +111 -0
- data/lib/rails_notebook/renderers.rb +121 -0
- data/lib/rails_notebook/route.rb +121 -0
- data/lib/rails_notebook/schemaTable.rb +27 -0
- data/lib/rails_notebook/serializers.rb +92 -0
- data/lib/rails_notebook/table.rb +28 -0
- data/lib/rails_notebook/version.rb +3 -0
- data/lib/tasks/rails_notebook_tasks.rake +8 -0
- metadata +196 -0
@@ -0,0 +1,136 @@
|
|
1
|
+
/*General css*/
|
2
|
+
|
3
|
+
body {
|
4
|
+
font-family: Avenir,Helvetica Neue,Helvetica,Arial,sans-serif;
|
5
|
+
line-height: 1.4;
|
6
|
+
}
|
7
|
+
|
8
|
+
div.text_cell_render {
|
9
|
+
font-size: 16px;
|
10
|
+
font-weight: lighter;
|
11
|
+
}
|
12
|
+
|
13
|
+
text {
|
14
|
+
font-weight: 300;
|
15
|
+
font-family: "Helvetica Neue", Helvetica, Arial, sans-serf;
|
16
|
+
font-size: 14px;
|
17
|
+
color: black;
|
18
|
+
}
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
/* Rails.applicaiton.routes*/
|
23
|
+
g.type-hasDisplay > rect {
|
24
|
+
fill: #b3ffb3;
|
25
|
+
}
|
26
|
+
g.type-noDisplay > rect {
|
27
|
+
fill: #eee;
|
28
|
+
}
|
29
|
+
|
30
|
+
table, th, td {
|
31
|
+
font-size: 14px;
|
32
|
+
border: 2px solid white;
|
33
|
+
border-collapse: collapse;
|
34
|
+
padding: 8px;
|
35
|
+
}
|
36
|
+
|
37
|
+
.toolTipTable h4 {
|
38
|
+
font-size: 16px;
|
39
|
+
font-weight:normal;
|
40
|
+
text-align: center;
|
41
|
+
}
|
42
|
+
|
43
|
+
.activeRecordSchema h3 {
|
44
|
+
font-size: 16px;
|
45
|
+
font-weight:normal;
|
46
|
+
text-align: center;
|
47
|
+
}
|
48
|
+
|
49
|
+
|
50
|
+
/*Render Schema Table*/
|
51
|
+
.activeRecordSchema {
|
52
|
+
color:black;
|
53
|
+
}
|
54
|
+
table.activeRecordSchemaTable{
|
55
|
+
background: #f2f2f2;
|
56
|
+
border-collapse:collapse;
|
57
|
+
}
|
58
|
+
table.activeRecordSchemaTable tr, table.activeRecordSchemaTable td{
|
59
|
+
border:0;
|
60
|
+
}
|
61
|
+
table.activeRecordSchemaTable th{
|
62
|
+
border:0;
|
63
|
+
font-weight: bold;
|
64
|
+
}
|
65
|
+
|
66
|
+
|
67
|
+
|
68
|
+
/*Flamechart*/
|
69
|
+
.job_chart .chart:hover {
|
70
|
+
cursor: pointer;
|
71
|
+
}
|
72
|
+
|
73
|
+
.job_chart .axis text {
|
74
|
+
font-size: 0.85em;
|
75
|
+
}
|
76
|
+
|
77
|
+
.job_chart .axis path,
|
78
|
+
.job_chart .axis line {
|
79
|
+
fill: none;
|
80
|
+
stroke: #000;
|
81
|
+
shape-rendering: crispEdges;
|
82
|
+
}
|
83
|
+
|
84
|
+
.table.table-striped{
|
85
|
+
border-collapse: collapse;
|
86
|
+
margin:2px;
|
87
|
+
}
|
88
|
+
|
89
|
+
.table.table-striped tr, .table.table-striped td , .table.table-striped th{
|
90
|
+
font-size: 12px;
|
91
|
+
padding: 2px 4px 2px 4px;
|
92
|
+
}
|
93
|
+
|
94
|
+
.domain{
|
95
|
+
fill: none;
|
96
|
+
stroke: #000;
|
97
|
+
stroke-width: 2px
|
98
|
+
}
|
99
|
+
|
100
|
+
/*.table.table-striped tr:nth-child(even) {background: #e6e6e6}
|
101
|
+
.table.table-striped tr:nth-child(odd) {background: #f2f2f2}
|
102
|
+
*/
|
103
|
+
.rendered_html h1,.rendered_html h2,.rendered_html h3,.rendered_html h4,.rendered_html h5{
|
104
|
+
font-weight:normal;
|
105
|
+
text-align: center;
|
106
|
+
}
|
107
|
+
|
108
|
+
|
109
|
+
div.cell.selected {
|
110
|
+
background: #FDFCF8;
|
111
|
+
}
|
112
|
+
|
113
|
+
.rendered_html code {
|
114
|
+
border: 1px solid #ddd;
|
115
|
+
background: #F5F5F5;
|
116
|
+
padding: 1px;
|
117
|
+
font-size: 85%;
|
118
|
+
}
|
119
|
+
|
120
|
+
|
121
|
+
|
122
|
+
/*For Dagre-d3 graph rendering*/
|
123
|
+
.node rect {
|
124
|
+
stroke: #999;
|
125
|
+
fill: #fff;
|
126
|
+
stroke-width: 1.5px;
|
127
|
+
}
|
128
|
+
|
129
|
+
.edgePath path {
|
130
|
+
stroke: #333;
|
131
|
+
stroke-width: 1.5px;
|
132
|
+
}
|
133
|
+
|
134
|
+
.edgeLabel rect {
|
135
|
+
fill: #fff;
|
136
|
+
}
|
@@ -0,0 +1,548 @@
|
|
1
|
+
!function() {
|
2
|
+
|
3
|
+
var railsNB = {
|
4
|
+
version: "0.0.1"
|
5
|
+
};
|
6
|
+
|
7
|
+
// Margin values are standard for all elements
|
8
|
+
var margin = { left: 45, top: 10, right: 5, bottom: 60 };
|
9
|
+
|
10
|
+
railsNB.renderFlamechart = function ( _data , _element ){
|
11
|
+
require( [ "/kernelspecs/rails_notebook/dagre-d3.js", "/kernelspecs/rails_notebook/d3.js", "jquery", "/kernelspecs/rails_notebook/jquery.tipsy.js" ] , function ( dagreD3, d3, $, tipsy ) {
|
12
|
+
|
13
|
+
// Initialize
|
14
|
+
var SAMPLE_TIME = _data.sampleTime;
|
15
|
+
var element = $(_element);
|
16
|
+
var data = _data.data;
|
17
|
+
var self = this;
|
18
|
+
|
19
|
+
var getGemName = function(frame) {
|
20
|
+
var split = frame.split('/gems/');
|
21
|
+
if(split.length == 1) {
|
22
|
+
split = frame.split('/app/');
|
23
|
+
if(split.length == 1) { split = frame.split('/lib/'); }
|
24
|
+
split = split[ Math.max( split.length-2,0 ) ].split('/');
|
25
|
+
return split[split.length-1].split(':')[0];
|
26
|
+
}
|
27
|
+
else {
|
28
|
+
return split[split.length -1].split('/')[0];
|
29
|
+
}
|
30
|
+
};
|
31
|
+
|
32
|
+
var getMethodName = function(frame) {
|
33
|
+
var split = frame.split('`');
|
34
|
+
if(split.length == 2) {
|
35
|
+
var fullMethod = split[1].split("'")[0];
|
36
|
+
split = fullMethod.split("#");
|
37
|
+
if(split.length == 2) { return split[1]; }
|
38
|
+
return split[0];
|
39
|
+
}
|
40
|
+
return '';
|
41
|
+
};
|
42
|
+
|
43
|
+
var generate_flamechart = function myself() {
|
44
|
+
var bar_height = 20;
|
45
|
+
// Generate color from data. The color palette is based on warm colors i.e.
|
46
|
+
// from red to orange which have a hue of 0 to around 40. The step taken to
|
47
|
+
// increment the hue from 0 to 40 is a function of the step or depth level.
|
48
|
+
var color = function(d) {
|
49
|
+
var hue_min = 0,
|
50
|
+
hue_max = 40,
|
51
|
+
hue = null,
|
52
|
+
saturation = 80,
|
53
|
+
luminosity = 60,
|
54
|
+
hues = [],
|
55
|
+
step = (hue_max - hue_min)/Math.max.apply(Math,y_values);
|
56
|
+
for (var h = 0; h < hue_max; h+=step) { hues.push(h) };
|
57
|
+
hue = hues[d.y - 1];
|
58
|
+
return d3.hsl("hsl(" + hue + "," + saturation + "%," + luminosity + "%)");
|
59
|
+
};
|
60
|
+
|
61
|
+
var guessGem = function(frame)
|
62
|
+
{
|
63
|
+
var split = frame.split('/gems/');
|
64
|
+
if(split.length == 1) {
|
65
|
+
split = frame.split('/app/');
|
66
|
+
if(split.length == 1) {
|
67
|
+
split = frame.split('/lib/');
|
68
|
+
}
|
69
|
+
split = split[Math.max(split.length-2,0)].split('/');
|
70
|
+
return split[split.length-1].split(':')[0];
|
71
|
+
}
|
72
|
+
else
|
73
|
+
{
|
74
|
+
return split[split.length -1].split('/')[0];
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
var guessMethod = function(frame) {
|
79
|
+
var split = frame.split('`');
|
80
|
+
if(split.length == 2) {
|
81
|
+
var fullMethod = split[1].split("'")[0];
|
82
|
+
split = fullMethod.split("#");
|
83
|
+
if(split.length == 2) {
|
84
|
+
return split[1];
|
85
|
+
}
|
86
|
+
return split[0];
|
87
|
+
}
|
88
|
+
return '?';
|
89
|
+
}
|
90
|
+
|
91
|
+
// Format the data into formats that make it easier to generate the chart.
|
92
|
+
// For example ... convert the UNIX timestamps into Date objects for a more
|
93
|
+
// meaningful x-axis. To note is that UNIX timestamps are seconds while
|
94
|
+
// JavaScript Date objects expect milliseconds.
|
95
|
+
var chart_data = $.map(data, function(d, i) {
|
96
|
+
var entry = {}
|
97
|
+
entry['x_start'] = d.x * SAMPLE_TIME;
|
98
|
+
entry['x_end'] = ( d.x + d.width ) * SAMPLE_TIME;
|
99
|
+
entry['y'] = d.y;
|
100
|
+
entry['width'] = d.width * SAMPLE_TIME;
|
101
|
+
entry['methodDescription'] = d.frame;
|
102
|
+
entry['step'] = i;
|
103
|
+
d.index = i;
|
104
|
+
return entry;
|
105
|
+
});
|
106
|
+
|
107
|
+
// D3 orders the drawing of elements stacked on each other so we reverse the
|
108
|
+
// order by steps to hack in some form of z-index-ness.
|
109
|
+
//chart_data.sort(function(a, b) { return b.step - a.step });
|
110
|
+
|
111
|
+
// Determine the chart width (minus axis y-axis and its label).
|
112
|
+
var width = function() {
|
113
|
+
return element.width() - margin.left - margin.right;
|
114
|
+
};
|
115
|
+
|
116
|
+
// Determine the position of the bar which represents each entry i.e. each
|
117
|
+
// bar.
|
118
|
+
var bar_y_position = function(d) {
|
119
|
+
return bar_height * (d.y - 1)
|
120
|
+
};
|
121
|
+
|
122
|
+
var x_values = function() {
|
123
|
+
var start_time_values = $.map(chart_data, function(v, i) { return v.x_start }),
|
124
|
+
end_time_values = $.map(chart_data, function(v, i) { return v.x_end });
|
125
|
+
return start_time_values.concat(end_time_values);
|
126
|
+
};
|
127
|
+
// Get the y-domain possible values ... depending on the mode.
|
128
|
+
var y_values = $.map( chart_data, function(d){ return d.y });
|
129
|
+
|
130
|
+
var max_y_value = Math.max.apply( Math,y_values );
|
131
|
+
var max_x_value = Math.max.apply( Math,x_values() );
|
132
|
+
|
133
|
+
// Determine the chart height (minus axis x-axis and its label).
|
134
|
+
var height = bar_height * Math.max.apply(Math,y_values);
|
135
|
+
|
136
|
+
// Define the limits/scale of the x-axis from it's maximum and minimum points.
|
137
|
+
var xScale = d3.scale.linear()
|
138
|
+
.domain(d3.extent(x_values() ) )
|
139
|
+
.range([ 0, width() ]);
|
140
|
+
|
141
|
+
// Define the limits/scale of the y-axis from it's maximum and minimum points.
|
142
|
+
var yScale = d3.scale.ordinal()
|
143
|
+
.domain(y_values)
|
144
|
+
.rangeBands([0, height ]);
|
145
|
+
|
146
|
+
// Create x-axis.
|
147
|
+
var xAxis = d3.svg.axis()
|
148
|
+
.scale(xScale)
|
149
|
+
.orient("bottom");
|
150
|
+
|
151
|
+
// Create y-axis.
|
152
|
+
var yAxis = d3.svg.axis()
|
153
|
+
.scale(yScale)
|
154
|
+
.orient("left");
|
155
|
+
|
156
|
+
// Get the SVG element.
|
157
|
+
element.append('<svg class="chart" id='+element.context.id+'></svg>');
|
158
|
+
|
159
|
+
var svg = d3.select( "#"+element.context.id+".chart" )
|
160
|
+
.attr("width", width() + margin.left + margin.right)
|
161
|
+
.attr("height", height + margin.top + margin.bottom);
|
162
|
+
|
163
|
+
// Add the chart area.
|
164
|
+
var chart = svg
|
165
|
+
.append("g")
|
166
|
+
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
|
167
|
+
|
168
|
+
// Create entries from data
|
169
|
+
var entries = chart.selectAll("g")
|
170
|
+
.data(chart_data)
|
171
|
+
.enter()
|
172
|
+
|
173
|
+
// Create the bars that represent each entry of data.
|
174
|
+
var bar = entries.append("g")
|
175
|
+
.attr("transform", function (d) { return "translate(0," + bar_y_position(d) + ")" })
|
176
|
+
.on("mouseover", function (d) {
|
177
|
+
$("table tr." + d.step, element).addClass("info");
|
178
|
+
})
|
179
|
+
.on("mouseout", function (d) {
|
180
|
+
$("table tr." + d.step, element).removeClass("info");
|
181
|
+
})
|
182
|
+
|
183
|
+
var e_sub_bar = bar.append("rect")
|
184
|
+
.attr("id", function (d) {return d.step})
|
185
|
+
.attr("width", function (d) { return xScale(d.width) })
|
186
|
+
.attr("height", bar_height - 1)
|
187
|
+
.attr("fill", function (d) { return color(d).toString(); })
|
188
|
+
.attr("storedfill", function (d) { return color(d).toString(); }) //for reverting color after cell highlight
|
189
|
+
.attr("class", "flamechart-bar")
|
190
|
+
.attr("transform", function (d) { return "translate(" + xScale(d.x_start) + ",0)"; });
|
191
|
+
|
192
|
+
|
193
|
+
// Add the x-axis.
|
194
|
+
var xAxisScale = chart.append("g")
|
195
|
+
.attr("class", "x axis")
|
196
|
+
.attr("transform", "translate(0," + height + ")")
|
197
|
+
.call(xAxis);
|
198
|
+
|
199
|
+
// Add the y-axis.
|
200
|
+
var yAxisScale = chart.append("g")
|
201
|
+
.attr("class", "y axis")
|
202
|
+
.call(yAxis);
|
203
|
+
|
204
|
+
// Add label to the x-axis
|
205
|
+
var xAxisLabel = xAxisScale.append("text")
|
206
|
+
.attr("class", "label")
|
207
|
+
.attr("x", width()/2)
|
208
|
+
.attr("y", 30)
|
209
|
+
.attr("dy", ".71em")
|
210
|
+
.style("text-anchor", "middle")
|
211
|
+
.text("Duration (s)");
|
212
|
+
|
213
|
+
// Add label to the y-axis
|
214
|
+
var yAxisLabel = yAxisScale.append("text")
|
215
|
+
.attr("class", "label")
|
216
|
+
.attr("x", height/2 * -1)
|
217
|
+
.attr("transform", "rotate(-90)")
|
218
|
+
.attr("y", margin.left * -0.85)
|
219
|
+
.attr("dy", ".71em")
|
220
|
+
.style("text-anchor", "middle")
|
221
|
+
.text("Depth");
|
222
|
+
|
223
|
+
// Add the time taken for the expression to execute.
|
224
|
+
var bar_time = bar.append("text")
|
225
|
+
.attr("x", function (d) { return xScale( d.x_end ) - 3; })
|
226
|
+
.attr("y", bar_height/2)
|
227
|
+
.attr("fill", "black")
|
228
|
+
.attr("dy", ".35em")
|
229
|
+
.attr("text-anchor", "end")
|
230
|
+
.attr("style", "font: 0.8em sans-serif;")
|
231
|
+
.text(function(d) {
|
232
|
+
if ( d.width > ( max_x_value/15) ) {
|
233
|
+
return ( d.width ).toFixed(2) + 'ms'
|
234
|
+
}
|
235
|
+
});
|
236
|
+
|
237
|
+
var bar_text = bar.append("text")
|
238
|
+
.attr("x", function (d) { return xScale( d.x_start ) + 3; })
|
239
|
+
.attr("y", bar_height/2)
|
240
|
+
.attr("fill", "black")
|
241
|
+
.attr("dy", ".35em")
|
242
|
+
.attr("style", "font: 0.8em sans-serif;")
|
243
|
+
.text(function(d) {
|
244
|
+
if ( d.width > ( max_x_value/5) ) {
|
245
|
+
return ( getMethodName( d.methodDescription ) )
|
246
|
+
}
|
247
|
+
});
|
248
|
+
};
|
249
|
+
|
250
|
+
// Load results in a table.
|
251
|
+
var load_analysis_table = function() {
|
252
|
+
// Create table that will hold our data.
|
253
|
+
var empty_table_structure = '<table class="table table-striped">' +
|
254
|
+
'<thead>' +
|
255
|
+
'<tr>' +
|
256
|
+
'<th>Depth</th>' +
|
257
|
+
'<th>Method Name</th>' +
|
258
|
+
'<th>Gem Name</th>' +
|
259
|
+
'<th>Time Taken</th>' +
|
260
|
+
'<th>% Total Time</th>' +
|
261
|
+
'</tr>' +
|
262
|
+
'</thead>' +
|
263
|
+
'<tbody></tbody>' +
|
264
|
+
'</table>';
|
265
|
+
$(element).append(empty_table_structure);
|
266
|
+
|
267
|
+
var widths = $.map( data, function(d){ return d.width });
|
268
|
+
var max_entry_time = Math.max.apply( Math, widths );
|
269
|
+
|
270
|
+
// Populate the empty table we just created.
|
271
|
+
$.each( data, function( index , entry ) {
|
272
|
+
var table_row = '<tr class="' + entry.index + '">'
|
273
|
+
table_row += '<td>' + entry.y + '</td>';
|
274
|
+
table_row += '<td>' + getMethodName(entry.frame).replace("<","<").replace(">",">") + '</td>';
|
275
|
+
table_row += '<td>' + getGemName(entry.frame) + '</td>';
|
276
|
+
table_row += '<td>' + ( (entry.width * SAMPLE_TIME) ).toFixed(3) + ' ms' + '</td>';
|
277
|
+
table_row += '<td>' + (entry.width / max_entry_time * 100).toFixed(3) + '%' + '</td>';
|
278
|
+
table_row += '</tr>';
|
279
|
+
$('table', element).append(table_row);
|
280
|
+
$("table tr." + index, element)
|
281
|
+
.on("mouseover", function (d) {
|
282
|
+
$( "rect#" + index + ".flamechart-bar", element ).attr("fill","#eee")
|
283
|
+
})
|
284
|
+
.on("mouseout", function (d) {
|
285
|
+
$("rect#" + index + ".flamechart-bar", element)
|
286
|
+
.attr("fill",
|
287
|
+
$("rect#" + index + ".flamechart-bar", element).attr("storedfill")
|
288
|
+
)
|
289
|
+
});
|
290
|
+
});
|
291
|
+
};
|
292
|
+
|
293
|
+
// Draw chart.
|
294
|
+
generate_flamechart();
|
295
|
+
load_analysis_table();
|
296
|
+
|
297
|
+
});
|
298
|
+
};
|
299
|
+
|
300
|
+
railsNB.renderRoutes = function( tree , _element ){
|
301
|
+
require( ["/kernelspecs/rails_notebook/dagre-d3.js", "/kernelspecs/rails_notebook/d3.js", "/kernelspecs/rails_notebook/jquery.tipsy.js", "jquery" ] , function ( dagreD3, d3, tipsy ,$ ) {
|
302
|
+
|
303
|
+
var element = $(_element);
|
304
|
+
var routeTree = tree;
|
305
|
+
|
306
|
+
var g = new dagreD3.graphlib.Graph().setGraph({}).setDefaultEdgeLabel(function() { return {}; });
|
307
|
+
|
308
|
+
// Rendering the graph
|
309
|
+
var buildOutput = function myself( g, thisNode, parent ){
|
310
|
+
g.setNode( thisNode.id , {
|
311
|
+
label: ( parent ? thisNode.nodeUri + "/" : "/" + thisNode.nodeUri ),
|
312
|
+
class: ( thisNode.verbs.length > 0 && thisNode.verbs[0] != "" ? "type-hasDisplay" : "type-noDisplay" ),
|
313
|
+
uriPattern: thisNode.uriPattern,
|
314
|
+
controller: thisNode.controller,
|
315
|
+
verbs: thisNode.verbs,
|
316
|
+
actions: thisNode.actions,
|
317
|
+
});
|
318
|
+
if ( parent ){
|
319
|
+
g.setEdge( parent.id , thisNode.id );
|
320
|
+
}
|
321
|
+
for ( c in thisNode.childrenNodes ){
|
322
|
+
child = thisNode.childrenNodes[c];
|
323
|
+
myself( g , child, thisNode );
|
324
|
+
}
|
325
|
+
}
|
326
|
+
buildOutput( g , routeTree.headNode, null)
|
327
|
+
|
328
|
+
// DagreD3 code to display graph
|
329
|
+
var render = new dagreD3.render(); // Create the renderer
|
330
|
+
g.nodes().forEach(function(v) {
|
331
|
+
var node = g.node(v);
|
332
|
+
node.rx = node.ry = 5;
|
333
|
+
});
|
334
|
+
|
335
|
+
// Set up an SVG group so that we can translate the final graph.
|
336
|
+
element.append('<svg class="routes" id='+element.context.id+'><g></g></svg>');
|
337
|
+
var width = function() {
|
338
|
+
return element.width() - margin.left - margin.right;
|
339
|
+
};
|
340
|
+
|
341
|
+
var svg = d3.select( "#"+element.context.id+".routes" )
|
342
|
+
.attr("width", width() + margin.left + margin.right)
|
343
|
+
.attr("height", 400 + margin.top + margin.bottom);
|
344
|
+
var inner = svg.select("g");
|
345
|
+
|
346
|
+
// Set up zoom support
|
347
|
+
var zoom = d3.behavior.zoom().on("zoom", function() {
|
348
|
+
inner.attr("transform", "translate(" + d3.event.translate + ")" + "scale(" + d3.event.scale + ")");
|
349
|
+
});
|
350
|
+
svg.call(zoom);
|
351
|
+
|
352
|
+
// Simple function to style the tooltip for the given node.
|
353
|
+
var styleTooltip = function( node ) {
|
354
|
+
return(
|
355
|
+
node.verbs.length > 0?
|
356
|
+
"<div class='toolTipTable'><h4>"+node.uriPattern.slice(0, -1)+"</h4>" +
|
357
|
+
"<table border=1 align='center'>" +
|
358
|
+
(node.controller? "<tr><th>Controller:</th><td>"+node.controller+"</td></tr>":"")+
|
359
|
+
"<tr><th>Verbs: </th>" +
|
360
|
+
"<td>"+node.verbs.join("</td><td>")+"</td>"+
|
361
|
+
"</tr>" +
|
362
|
+
"<tr><th>Actions: </th>" +
|
363
|
+
"<td>"+node.actions.join("</td><td>")+"</td>"+
|
364
|
+
"</tr>" +
|
365
|
+
"</table></div>"
|
366
|
+
:
|
367
|
+
null
|
368
|
+
)
|
369
|
+
};
|
370
|
+
|
371
|
+
// Run the renderer. This is what draws the final graph.
|
372
|
+
render(inner, g);
|
373
|
+
inner.selectAll("g.node")
|
374
|
+
.attr("title", function(v) {
|
375
|
+
return styleTooltip( g.node(v) )
|
376
|
+
})
|
377
|
+
.each(function(v) {
|
378
|
+
$(this).tipsy({ gravity: "w", opacity: 1, html: true });
|
379
|
+
});
|
380
|
+
// Center the graph
|
381
|
+
var initialScale = 0.70;
|
382
|
+
zoom
|
383
|
+
.translate([(svg.attr("width") - g.graph().width * initialScale) / 2, 20])
|
384
|
+
.scale(initialScale)
|
385
|
+
.event(svg);
|
386
|
+
svg.attr('height', g.graph().height * initialScale + 40);
|
387
|
+
|
388
|
+
});
|
389
|
+
};
|
390
|
+
|
391
|
+
railsNB.renderSchema = function( tables, _element ){
|
392
|
+
require( ["/kernelspecs/rails_notebook/dagre-d3.js", "/kernelspecs/rails_notebook/d3.js", "jquery" ] , function ( dagreD3, d3, $ ) {
|
393
|
+
|
394
|
+
var element = $(_element);
|
395
|
+
var tablesVar = tables;
|
396
|
+
|
397
|
+
function capitalizeFirstLetter(string) {
|
398
|
+
return string.charAt(0).toUpperCase() + string.slice(1);
|
399
|
+
}
|
400
|
+
|
401
|
+
// Lets start by creating something simple and add lables to them
|
402
|
+
var g = new dagreD3.graphlib.Graph().setGraph({});
|
403
|
+
|
404
|
+
//Create rectangles for each of the tables
|
405
|
+
var tablesVarLangth = tablesVar.length;
|
406
|
+
for (var i=tablesVarLangth-1; i >= 0; i--)
|
407
|
+
{
|
408
|
+
var rows = tablesVar[i].columns.map( function( r ){
|
409
|
+
var name = r[0].indexOf("id") > -1? "<th>" + r[0] + "</th>" : "<td>" + r[0] + "</td>";
|
410
|
+
return "<tr>" + name + "<td>" + r[1] + "</td></tr>";
|
411
|
+
});
|
412
|
+
var buildHtmlOutput = "<div class='activeRecordSchema'><h3>" + capitalizeFirstLetter(tablesVar[i].table_name) + "</h3>";
|
413
|
+
buildHtmlOutput += "<table class='activeRecordSchemaTable'>";
|
414
|
+
buildHtmlOutput += rows.join("");
|
415
|
+
buildHtmlOutput += "</table>";
|
416
|
+
buildHtmlOutput += "</div>";
|
417
|
+
g.setNode(tablesVar[i].table_name, { shape: "rect", labelType: "html", label: buildHtmlOutput});
|
418
|
+
} // End of loop i, but not end of scope for i
|
419
|
+
|
420
|
+
// Now we want to populate the rectangles with column information
|
421
|
+
// TODO
|
422
|
+
|
423
|
+
// Now we want to make the arrows from the arrowsTo array
|
424
|
+
for (var i=0; i < tablesVarLangth; i++)
|
425
|
+
{
|
426
|
+
if (tablesVar[i].arrowsTo.length != 0)
|
427
|
+
{
|
428
|
+
tablesVar[i].arrowsTo.forEach(function(arrow) {
|
429
|
+
g.setEdge(tablesVar[i].table_name, arrow, {
|
430
|
+
arrowhead: "normal",
|
431
|
+
label: "belongs to"
|
432
|
+
});
|
433
|
+
});// For each arrow in table
|
434
|
+
} // If there are arrows
|
435
|
+
} // End of loop i, but not end of scope for i
|
436
|
+
|
437
|
+
|
438
|
+
// Set up an SVG group so that we can translate the final graph.
|
439
|
+
element.append('<svg class="schema" id='+element.context.id+'><g></g></svg>');
|
440
|
+
var width = function() {
|
441
|
+
return element.width() - margin.left - margin.right;
|
442
|
+
};
|
443
|
+
|
444
|
+
var svg = d3.select( "#"+element.context.id+".schema" )
|
445
|
+
.attr("width", width() + margin.left + margin.right)
|
446
|
+
.attr("height", 400 + margin.top + margin.bottom);
|
447
|
+
var inner = svg.select("g");
|
448
|
+
|
449
|
+
// Set up zoom support
|
450
|
+
var zoom = d3.behavior.zoom().on("zoom", function() {
|
451
|
+
inner.attr("transform", "translate(" + d3.event.translate + ")" +
|
452
|
+
"scale(" + d3.event.scale + ")");
|
453
|
+
});
|
454
|
+
|
455
|
+
svg.call(zoom);
|
456
|
+
|
457
|
+
// Create the renderer
|
458
|
+
var render = new dagreD3.render();
|
459
|
+
|
460
|
+
// Run the renderer. This is what draws the final graph.
|
461
|
+
render(inner, g);
|
462
|
+
|
463
|
+
// Center the graph
|
464
|
+
var initialScale = 0.60;
|
465
|
+
zoom
|
466
|
+
.translate([(svg.attr("width") - g.graph().width * initialScale) / 2, 20])
|
467
|
+
.scale(initialScale)
|
468
|
+
.event(svg);
|
469
|
+
svg.attr('height', g.graph().height * initialScale + 40);
|
470
|
+
|
471
|
+
});
|
472
|
+
};
|
473
|
+
|
474
|
+
railsNB.renderTableData = function( tableData, element ){
|
475
|
+
require( ["jquery"] , function ( $ ) {
|
476
|
+
|
477
|
+
var rows = tableData[1].map( function( rowElem , i ){
|
478
|
+
var cellTypeOpen = i == 0 ? "<th>" : "<td>";
|
479
|
+
var cellTypeClose = i == 0 ? "</th>" : "</td>";
|
480
|
+
var row = "<tr>";
|
481
|
+
for ( var j = 1 ; j <= tableData.slice(1).length ; j ++ ) {
|
482
|
+
row += cellTypeOpen+ tableData[j][i] + cellTypeClose;
|
483
|
+
}
|
484
|
+
row += "</tr>"
|
485
|
+
return ( row );
|
486
|
+
});
|
487
|
+
|
488
|
+
$(element).append( "<table>" + rows.join("") + "</table>" );
|
489
|
+
|
490
|
+
});
|
491
|
+
};
|
492
|
+
|
493
|
+
railsNB.renderBarChart = function( hash, _element ){
|
494
|
+
require(["jquery", "/kernelspecs/rails_notebook/nv.d3.js", "/kernelspecs/rails_notebook/d3.js"], function ( $, nvd3, d3 ) {
|
495
|
+
console.log( "nvd3" , nvd3 );
|
496
|
+
console.log( "nv", nv );
|
497
|
+
var element = $(_element);
|
498
|
+
|
499
|
+
var width = function() {
|
500
|
+
return element.width() - margin.left - margin.right;
|
501
|
+
};
|
502
|
+
|
503
|
+
element.append('<svg class="barChart" id='+element.context.id+'></svg>');
|
504
|
+
|
505
|
+
var barData = [];
|
506
|
+
var hashVar = hash;
|
507
|
+
|
508
|
+
for (var key in hashVar)
|
509
|
+
{
|
510
|
+
barData.push({
|
511
|
+
"label": key,
|
512
|
+
"value": hashVar[key]
|
513
|
+
})
|
514
|
+
}
|
515
|
+
|
516
|
+
var object = [{
|
517
|
+
key: "This Chart",
|
518
|
+
values: barData
|
519
|
+
}];
|
520
|
+
|
521
|
+
nv.addGraph(function() {
|
522
|
+
var chart = nv.models.discreteBarChart()
|
523
|
+
.x(function(d) { return d.label }) //Specify the data accessors.
|
524
|
+
.y(function(d) { return d.value })
|
525
|
+
.staggerLabels(true) //Too many bars and not enough room? Try staggering labels.
|
526
|
+
.showValues(true); //...instead, show the bar value right on top of each bar.
|
527
|
+
|
528
|
+
|
529
|
+
d3.select("#"+element.context.id+".barChart")
|
530
|
+
.attr("width", width() + margin.left + margin.right)
|
531
|
+
.attr("height", 300 + margin.top + margin.bottom)
|
532
|
+
.datum(object)
|
533
|
+
.call(chart);
|
534
|
+
// .selectAll("text")
|
535
|
+
// .style("text-anchor", "end")
|
536
|
+
// .attr("dx", "-.8em")
|
537
|
+
// .attr("dy", ".15em")
|
538
|
+
// .attr("transform", function(d) {
|
539
|
+
// return "rotate(-65)"
|
540
|
+
// });
|
541
|
+
|
542
|
+
nv.utils.windowResize(chart.update);
|
543
|
+
}); // nv add graph end
|
544
|
+
}); // Require end
|
545
|
+
}; // RenderBarChart end
|
546
|
+
|
547
|
+
if (typeof define === "function" && define.amd) this.railsNB = railsNB, define(railsNB); else if (typeof module === "object" && module.exports) module.exports = railsNB; else this.railsNB = railsNB;
|
548
|
+
}();
|