rails_notebook 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
}();
|