blazer 1.0.2 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of blazer might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +14 -2
- data/app/assets/javascripts/blazer/application.js +7 -0
- data/app/assets/javascripts/blazer/bootstrap.js +2366 -0
- data/app/controllers/blazer/queries_controller.rb +20 -1
- data/app/helpers/blazer/base_helper.rb +20 -2
- data/app/models/blazer/query.rb +1 -0
- data/app/views/blazer/_nav.html.erb +15 -0
- data/app/views/blazer/checks/index.html.erb +2 -4
- data/app/views/blazer/checks/run.html.erb +1 -1
- data/app/views/blazer/dashboards/index.html.erb +2 -4
- data/app/views/blazer/dashboards/show.html.erb +3 -3
- data/app/views/blazer/queries/_form.html.erb +1 -1
- data/app/views/blazer/queries/edit.html.erb +1 -0
- data/app/views/blazer/queries/home.html.erb +17 -4
- data/app/views/blazer/queries/new.html.erb +1 -0
- data/app/views/blazer/queries/run.html.erb +32 -3
- data/app/views/blazer/queries/show.html.erb +3 -3
- data/app/views/layouts/blazer/application.html.erb +5 -1
- data/lib/blazer/data_source.rb +7 -3
- data/lib/blazer/version.rb +1 -1
- data/lib/blazer.rb +1 -0
- metadata +4 -2
@@ -41,6 +41,8 @@ module Blazer
|
|
41
41
|
@sql_errors << error if error
|
42
42
|
end
|
43
43
|
end
|
44
|
+
|
45
|
+
Blazer.transform_statement.call(data_source, @statement) if Blazer.transform_statement
|
44
46
|
end
|
45
47
|
|
46
48
|
def edit
|
@@ -56,6 +58,8 @@ module Blazer
|
|
56
58
|
|
57
59
|
data_source = params[:data_source]
|
58
60
|
data_source = @query.data_source if @query && @query.data_source
|
61
|
+
@data_source = Blazer.data_sources[data_source]
|
62
|
+
Blazer.transform_statement.call(@data_source, @statement) if Blazer.transform_statement
|
59
63
|
|
60
64
|
# audit
|
61
65
|
if Blazer.audit
|
@@ -66,7 +70,6 @@ module Blazer
|
|
66
70
|
audit.save!
|
67
71
|
end
|
68
72
|
|
69
|
-
@data_source = Blazer.data_sources[data_source]
|
70
73
|
@rows, @error, @cached_at = @data_source.run_statement(@statement, user: blazer_user, query: @query, refresh_cache: params[:check])
|
71
74
|
|
72
75
|
if @query && !@error.to_s.include?("canceling statement due to statement timeout")
|
@@ -105,6 +108,22 @@ module Blazer
|
|
105
108
|
end
|
106
109
|
|
107
110
|
@linked_columns = @data_source.linked_columns
|
111
|
+
|
112
|
+
@markers = []
|
113
|
+
[["latitude", "longitude"], ["lat", "lon"]].each do |keys|
|
114
|
+
if (keys - (@rows.first || {}).keys).empty?
|
115
|
+
@markers =
|
116
|
+
@rows.select do |r|
|
117
|
+
r[keys.first] && r[keys.last]
|
118
|
+
end.map do |r|
|
119
|
+
{
|
120
|
+
title: r.except(*keys).map{ |k, v| "<strong>#{k}:</strong> #{v}" }.join("<br />").truncate(140),
|
121
|
+
latitude: r[keys.first],
|
122
|
+
longitude: r[keys.last]
|
123
|
+
}
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
108
127
|
end
|
109
128
|
|
110
129
|
respond_to do |format|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Blazer
|
2
2
|
module BaseHelper
|
3
|
-
def
|
3
|
+
def blazer_title(title = nil)
|
4
4
|
if title
|
5
5
|
content_for(:title) { title }
|
6
6
|
else
|
@@ -8,12 +8,30 @@ module Blazer
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
-
def
|
11
|
+
def blazer_format_value(key, value)
|
12
12
|
if value.is_a?(Integer) && !key.to_s.end_with?("id")
|
13
13
|
number_with_delimiter(value)
|
14
14
|
else
|
15
15
|
value
|
16
16
|
end
|
17
17
|
end
|
18
|
+
|
19
|
+
def blazer_maps?
|
20
|
+
ENV["MAPBOX_ACCESS_TOKEN"].present?
|
21
|
+
end
|
22
|
+
|
23
|
+
JSON_ESCAPE = { '&' => '\u0026', '>' => '\u003e', '<' => '\u003c', "\u2028" => '\u2028', "\u2029" => '\u2029' }
|
24
|
+
JSON_ESCAPE_REGEXP = /[\u2028\u2029&><]/u
|
25
|
+
|
26
|
+
# Prior to version 4.1 of rails double quotes were inadventently removed in json_escape.
|
27
|
+
# This adds the correct json_escape functionality to rails versions < 4.1
|
28
|
+
def blazer_json_escape(s)
|
29
|
+
if Rails::VERSION::STRING < "4.1"
|
30
|
+
result = s.to_s.gsub(JSON_ESCAPE_REGEXP, JSON_ESCAPE)
|
31
|
+
s.html_safe? ? result.html_safe : result
|
32
|
+
else
|
33
|
+
json_escape(s)
|
34
|
+
end
|
35
|
+
end
|
18
36
|
end
|
19
37
|
end
|
data/app/models/blazer/query.rb
CHANGED
@@ -2,6 +2,7 @@ module Blazer
|
|
2
2
|
class Query < ActiveRecord::Base
|
3
3
|
belongs_to :creator, class_name: Blazer.user_class.to_s if Blazer.user_class
|
4
4
|
has_many :checks, dependent: :destroy
|
5
|
+
has_many :dashboard_queries, dependent: :destroy
|
5
6
|
|
6
7
|
validates :name, presence: true
|
7
8
|
validates :statement, presence: true
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<div class="btn-group" style="vertical-align: top; margin-right: 5px;">
|
2
|
+
<%= link_to "Home", root_path, class: "btn btn-primary" %>
|
3
|
+
<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
4
|
+
<span class="caret"></span>
|
5
|
+
<span class="sr-only">Toggle Dropdown</span>
|
6
|
+
</button>
|
7
|
+
<ul class="dropdown-menu">
|
8
|
+
<li><%= link_to "Dashboards", dashboards_path %></li>
|
9
|
+
<li><%= link_to "Checks", checks_path %></li>
|
10
|
+
<li role="separator" class="divider"></li>
|
11
|
+
<li><%= link_to "New Query", new_query_path %></li>
|
12
|
+
<li><%= link_to "New Dashboard", new_dashboard_path %></li>
|
13
|
+
<li><%= link_to "New Check", new_check_path %></li>
|
14
|
+
</ul>
|
15
|
+
</div>
|
@@ -1,9 +1,7 @@
|
|
1
|
-
<%
|
1
|
+
<% blazer_title "Checks" %>
|
2
2
|
|
3
3
|
<p style="float: right;"><%= link_to "New Check", new_check_path, class: "btn btn-info" %></p>
|
4
|
-
|
5
|
-
<%= link_to "Home", root_path, class: "btn btn-primary", style: "margin-right: 10px;" %>
|
6
|
-
</p>
|
4
|
+
<%= render partial: "blazer/nav" %>
|
7
5
|
|
8
6
|
<% colors = {failing: "red", passing: "#5cb85c", error: "#666"} %>
|
9
7
|
<table class="table">
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<p style="text-muted">Running check...</p>
|
2
2
|
|
3
3
|
<script>
|
4
|
-
$.post("<%= run_queries_path %>", <%=
|
4
|
+
$.post("<%= run_queries_path %>", <%= blazer_json_escape({statement: @query.statement, query_id: @query.id, check: true}.to_json).html_safe %>, function (data) {
|
5
5
|
setTimeout( function () {
|
6
6
|
window.location.href = "<%= checks_path %>";
|
7
7
|
}, 200);
|
@@ -1,9 +1,7 @@
|
|
1
|
-
<%
|
1
|
+
<% blazer_title "Dashboards" %>
|
2
2
|
|
3
3
|
<p style="float: right;"><%= link_to "New Dashboard", new_dashboard_path, class: "btn btn-info" %></p>
|
4
|
-
|
5
|
-
<%= link_to "Home", root_path, class: "btn btn-primary", style: "margin-right: 10px;" %>
|
6
|
-
</p>
|
4
|
+
<%= render partial: "blazer/nav" %>
|
7
5
|
|
8
6
|
<table class="table">
|
9
7
|
<thead>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<%
|
1
|
+
<% blazer_title @dashboard.name %>
|
2
2
|
|
3
3
|
<script>
|
4
4
|
function submitIfCompleted($form) {
|
@@ -18,7 +18,7 @@
|
|
18
18
|
<div class="container">
|
19
19
|
<div class="row" style="padding-top: 13px;">
|
20
20
|
<div class="col-sm-9">
|
21
|
-
<%=
|
21
|
+
<%= render partial: "blazer/nav" %>
|
22
22
|
<h3 style="margin: 0; line-height: 34px; display: inline-block;">
|
23
23
|
<%= @dashboard.name %>
|
24
24
|
</h3>
|
@@ -137,7 +137,7 @@
|
|
137
137
|
var request = $.ajax({
|
138
138
|
url: "<%= run_queries_path %>",
|
139
139
|
method: "POST",
|
140
|
-
data: <%=
|
140
|
+
data: <%= blazer_json_escape({statement: query.statement, query_id: query.id, only_chart: true}.to_json).html_safe %>,
|
141
141
|
dataType: "html"
|
142
142
|
}).done(function(data) {
|
143
143
|
$("#chart-<%= i %>").html(data);
|
@@ -1,9 +1,18 @@
|
|
1
1
|
<div id="queries">
|
2
2
|
<div id="header" style="margin-bottom: 20px;">
|
3
|
-
<div class="pull-right">
|
3
|
+
<div class="btn-group pull-right">
|
4
4
|
<%= link_to "New Query", new_query_path, class: "btn btn-info" %>
|
5
|
-
|
6
|
-
|
5
|
+
<button type="button" class="btn btn-info dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
6
|
+
<span class="caret"></span>
|
7
|
+
<span class="sr-only">Toggle Dropdown</span>
|
8
|
+
</button>
|
9
|
+
<ul class="dropdown-menu">
|
10
|
+
<li><%= link_to "Dashboards", dashboards_path %></li>
|
11
|
+
<li><%= link_to "Checks", checks_path %></li>
|
12
|
+
<li role="separator" class="divider"></li>
|
13
|
+
<li><%= link_to "New Dashboard", new_dashboard_path %></li>
|
14
|
+
<li><%= link_to "New Check", new_check_path %></li>
|
15
|
+
</ul>
|
7
16
|
</div>
|
8
17
|
<input type="text" placeholder="Start typing a query or person" style="width: 300px; display: inline-block;" autofocus=true class="search form-control" />
|
9
18
|
</div>
|
@@ -34,7 +43,11 @@
|
|
34
43
|
</script>
|
35
44
|
|
36
45
|
<% if @queries.size == 1000 %>
|
46
|
+
<p id="loading" class="text-muted">Loading...</p>
|
37
47
|
<script>
|
38
|
-
$(".list").load("<%= queries_path %>",
|
48
|
+
$(".list").load("<%= queries_path %>", function () {
|
49
|
+
updateList();
|
50
|
+
$("#loading").remove();
|
51
|
+
});
|
39
52
|
</script>
|
40
53
|
<% end %>
|
@@ -34,9 +34,38 @@
|
|
34
34
|
<%= line_chart @rows.group_by { |v| v[keys[1]] }.map { |name, v| {name: name, data: v.map { |v2| [v2[keys[0]], v2[keys[2]]] } } }, id: chart_id, min: nil %>
|
35
35
|
<% elsif values.size == 2 && values.first.is_a?(String) && values.last.is_a?(Numeric) %>
|
36
36
|
<%= pie_chart @rows.map(&:values), library: {sliceVisibilityThreshold: 1 / 40.0}, id: chart_id %>
|
37
|
+
<% elsif blazer_maps? && @markers.any? %>
|
38
|
+
<div id="map" style="height: <%= @only_chart ? 300 : 500 %>px;"></div>
|
39
|
+
<script>
|
40
|
+
L.mapbox.accessToken = '<%= ENV["MAPBOX_ACCESS_TOKEN"] %>';
|
41
|
+
var map = L.mapbox.map('map', 'ankane.ioo8nki0');
|
42
|
+
var markers = <%= blazer_json_escape(@markers.to_json).html_safe %>;
|
43
|
+
var featureLayer = L.mapbox.featureLayer().addTo(map);
|
44
|
+
var geojson = [];
|
45
|
+
for (var i = 0; i < markers.length; i++) {
|
46
|
+
var marker = markers[i];
|
47
|
+
geojson.push({
|
48
|
+
type: 'Feature',
|
49
|
+
geometry: {
|
50
|
+
type: 'Point',
|
51
|
+
coordinates: [
|
52
|
+
marker.longitude,
|
53
|
+
marker.latitude
|
54
|
+
]
|
55
|
+
},
|
56
|
+
properties: {
|
57
|
+
description: marker.title,
|
58
|
+
'marker-color': '#f86767',
|
59
|
+
'marker-symbol': 'star'
|
60
|
+
}
|
61
|
+
});
|
62
|
+
}
|
63
|
+
featureLayer.setGeoJSON(geojson);
|
64
|
+
map.fitBounds(featureLayer.getBounds());
|
65
|
+
</script>
|
37
66
|
<% elsif @only_chart %>
|
38
67
|
<% if @rows.size == 1 && @rows.first.size == 1 %>
|
39
|
-
<p style="font-size: 160px;"><%=
|
68
|
+
<p style="font-size: 160px;"><%= blazer_format_value(@rows.first.keys.first, @rows.first.values.first) %></p>
|
40
69
|
<% else %>
|
41
70
|
<% @no_chart = true %>
|
42
71
|
<% end %>
|
@@ -70,9 +99,9 @@
|
|
70
99
|
<% if v == "" %>
|
71
100
|
<div class="text-muted">empty string</div>
|
72
101
|
<% elsif @linked_columns[k] %>
|
73
|
-
<%= link_to
|
102
|
+
<%= link_to blazer_format_value(k, v), @linked_columns[k].gsub("{value}", u(v.to_s)), target: "_blank" %>
|
74
103
|
<% else %>
|
75
|
-
<%=
|
104
|
+
<%= blazer_format_value(k, v) %>
|
76
105
|
<% end %>
|
77
106
|
|
78
107
|
<% if v2 = (@boom[k] || {})[v] %>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<%
|
1
|
+
<% blazer_title @query.name %>
|
2
2
|
|
3
3
|
<script>
|
4
4
|
function submitIfCompleted($form) {
|
@@ -18,7 +18,7 @@
|
|
18
18
|
<div class="container">
|
19
19
|
<div class="row" style="padding-top: 13px;">
|
20
20
|
<div class="col-sm-9">
|
21
|
-
<%=
|
21
|
+
<%= render partial: "blazer/nav" %>
|
22
22
|
<h3 style="margin: 0; line-height: 34px; display: inline-block;">
|
23
23
|
<%= @query.name %>
|
24
24
|
</h3>
|
@@ -158,7 +158,7 @@
|
|
158
158
|
var request = $.ajax({
|
159
159
|
url: "<%= run_queries_path %>",
|
160
160
|
method: "POST",
|
161
|
-
data: <%=
|
161
|
+
data: <%= blazer_json_escape(variable_params.merge(statement: @statement, query_id: @query.id).to_json).html_safe %>,
|
162
162
|
dataType: "html"
|
163
163
|
}).done(function(data) {
|
164
164
|
$("#results").html(data);
|
@@ -1,12 +1,16 @@
|
|
1
1
|
<!DOCTYPE html>
|
2
2
|
<html>
|
3
3
|
<head>
|
4
|
-
<title><%=
|
4
|
+
<title><%= blazer_title ? blazer_title : "Blazer" %></title>
|
5
5
|
|
6
6
|
<meta charset="utf-8" />
|
7
7
|
|
8
8
|
<%= stylesheet_link_tag "blazer/application" %>
|
9
9
|
<%= javascript_include_tag "//www.google.com/jsapi", "blazer/application" %>
|
10
|
+
<% if blazer_maps? %>
|
11
|
+
<%= stylesheet_link_tag "https://api.mapbox.com/mapbox.js/v2.2.2/mapbox.css" %>
|
12
|
+
<%= javascript_include_tag "https://api.mapbox.com/mapbox.js/v2.2.2/mapbox.js" %>
|
13
|
+
<% end %>
|
10
14
|
<%= csrf_meta_tags %>
|
11
15
|
</head>
|
12
16
|
<body>
|
data/lib/blazer/data_source.rb
CHANGED
@@ -71,7 +71,7 @@ module Blazer
|
|
71
71
|
|
72
72
|
in_transaction do
|
73
73
|
begin
|
74
|
-
connection_model.connection.execute("SET statement_timeout = #{timeout.to_i * 1000}") if timeout && postgresql?
|
74
|
+
connection_model.connection.execute("SET statement_timeout = #{timeout.to_i * 1000}") if timeout && (postgresql? || redshift?)
|
75
75
|
result = connection_model.connection.select_all("#{statement} /*#{comment}*/")
|
76
76
|
result.each do |untyped_row|
|
77
77
|
row = {}
|
@@ -100,7 +100,7 @@ module Blazer
|
|
100
100
|
end
|
101
101
|
|
102
102
|
def schemas
|
103
|
-
default_schema = postgresql? ? "public" : connection_model.connection_config[:database]
|
103
|
+
default_schema = (postgresql? || redshift?) ? "public" : connection_model.connection_config[:database]
|
104
104
|
settings["schemas"] || [connection_model.connection_config[:schema] || default_schema]
|
105
105
|
end
|
106
106
|
|
@@ -110,7 +110,11 @@ module Blazer
|
|
110
110
|
end
|
111
111
|
|
112
112
|
def postgresql?
|
113
|
-
|
113
|
+
connection_model.connection.adapter_name == "PostgreSQL"
|
114
|
+
end
|
115
|
+
|
116
|
+
def redshift?
|
117
|
+
connection_model.connection.adapter_name == "Redshift"
|
114
118
|
end
|
115
119
|
|
116
120
|
protected
|
data/lib/blazer/version.rb
CHANGED
data/lib/blazer.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: blazer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-10-
|
11
|
+
date: 2015-10-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -87,6 +87,7 @@ files:
|
|
87
87
|
- app/assets/javascripts/blazer/ace/snippets/text.js
|
88
88
|
- app/assets/javascripts/blazer/ace/theme-twilight.js
|
89
89
|
- app/assets/javascripts/blazer/application.js
|
90
|
+
- app/assets/javascripts/blazer/bootstrap.js
|
90
91
|
- app/assets/javascripts/blazer/chartkick.js
|
91
92
|
- app/assets/javascripts/blazer/daterangepicker.js
|
92
93
|
- app/assets/javascripts/blazer/highlight.pack.js
|
@@ -115,6 +116,7 @@ files:
|
|
115
116
|
- app/models/blazer/dashboard.rb
|
116
117
|
- app/models/blazer/dashboard_query.rb
|
117
118
|
- app/models/blazer/query.rb
|
119
|
+
- app/views/blazer/_nav.html.erb
|
118
120
|
- app/views/blazer/check_mailer/failing_checks.html.erb
|
119
121
|
- app/views/blazer/check_mailer/state_change.html.erb
|
120
122
|
- app/views/blazer/checks/_form.html.erb
|