blazer 1.1.0 → 1.1.1
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 +9 -0
- data/README.md +8 -0
- data/app/assets/javascripts/blazer/application.js +32 -0
- data/app/assets/stylesheets/blazer/github.css +1 -2
- data/app/controllers/blazer/base_controller.rb +5 -1
- data/app/controllers/blazer/checks_controller.rb +1 -1
- data/app/controllers/blazer/queries_controller.rb +4 -1
- data/app/helpers/blazer/base_helper.rb +2 -0
- data/app/models/blazer/check.rb +3 -2
- data/app/views/blazer/checks/_form.html.erb +16 -1
- data/app/views/blazer/dashboards/show.html.erb +1 -1
- data/app/views/blazer/queries/_form.html.erb +2 -0
- data/app/views/blazer/queries/run.html.erb +7 -3
- data/app/views/blazer/queries/show.html.erb +2 -2
- data/lib/blazer.rb +3 -0
- data/lib/blazer/data_source.rb +1 -0
- data/lib/blazer/engine.rb +1 -0
- data/lib/blazer/version.rb +1 -1
- data/lib/generators/blazer/templates/config.yml +3 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7d498bb03f6c2cdf408e73065449df3d27f7d2e4
|
4
|
+
data.tar.gz: b23b774a851a748277ffd1a1b33a420ca75f35ed
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f551893a6c87914244c745aa481e01339465b7c59b97caac8a3c323dc378be92bf8ec39ed8d2ad64012880be5cbb909bdf6c8f5278bd3b85930aa1ab17f5b5a
|
7
|
+
data.tar.gz: 3fe76a4cb97e6b8f55a338b5c0bbde9564a972bee3fba93bc6b04b9f7bc7331b975abf87fd514b18c5ab6c72039ef2398449539747e9271d1a235fb97a1c236e
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
## 1.1.1
|
2
|
+
|
3
|
+
- Added `before_action` option
|
4
|
+
- Added invert option for checks
|
5
|
+
- Added targets
|
6
|
+
- Friendlier error message for timeouts
|
7
|
+
- Fixed request URI too large
|
8
|
+
- Prevent accidental backspace nav on query page
|
9
|
+
|
1
10
|
## 1.1.0
|
2
11
|
|
3
12
|
- Replaced pie charts with column charts
|
data/README.md
CHANGED
@@ -127,6 +127,14 @@ authenticate :user, lambda { |user| user.admin? } do
|
|
127
127
|
end
|
128
128
|
```
|
129
129
|
|
130
|
+
### Other
|
131
|
+
|
132
|
+
Specify a `before_action` method to run in `blazer.yml`.
|
133
|
+
|
134
|
+
```yml
|
135
|
+
before_action: require_admin
|
136
|
+
```
|
137
|
+
|
130
138
|
## Queries
|
131
139
|
|
132
140
|
### Variables
|
@@ -23,3 +23,35 @@ $( function () {
|
|
23
23
|
$(this).parent().addClass('open');
|
24
24
|
});
|
25
25
|
});
|
26
|
+
|
27
|
+
// Prevent backspace from navigating backwards.
|
28
|
+
// Adapted from Biff MaGriff: http://stackoverflow.com/a/7895814/1196499
|
29
|
+
function preventBackspaceNav() {
|
30
|
+
$(document).keydown(function (e) {
|
31
|
+
var preventKeyPress;
|
32
|
+
if (e.keyCode == 8) {
|
33
|
+
var d = e.srcElement || e.target;
|
34
|
+
switch (d.tagName.toUpperCase()) {
|
35
|
+
case 'TEXTAREA':
|
36
|
+
preventKeyPress = d.readOnly || d.disabled;
|
37
|
+
break;
|
38
|
+
case 'INPUT':
|
39
|
+
preventKeyPress = d.readOnly || d.disabled || (d.attributes["type"] && $.inArray(d.attributes["type"].value.toLowerCase(), ["radio", "reset", "checkbox", "submit", "button"]) >= 0);
|
40
|
+
break;
|
41
|
+
case 'DIV':
|
42
|
+
preventKeyPress = d.readOnly || d.disabled || !(d.attributes["contentEditable"] && d.attributes["contentEditable"].value == "true");
|
43
|
+
break;
|
44
|
+
default:
|
45
|
+
preventKeyPress = true;
|
46
|
+
break;
|
47
|
+
}
|
48
|
+
}
|
49
|
+
else {
|
50
|
+
preventKeyPress = false;
|
51
|
+
}
|
52
|
+
|
53
|
+
if (preventKeyPress) {
|
54
|
+
e.preventDefault();
|
55
|
+
}
|
56
|
+
});
|
57
|
+
}
|
@@ -9,6 +9,10 @@ module Blazer
|
|
9
9
|
http_basic_authenticate_with name: ENV["BLAZER_USERNAME"], password: ENV["BLAZER_PASSWORD"]
|
10
10
|
end
|
11
11
|
|
12
|
+
if Blazer.before_action
|
13
|
+
before_action Blazer.before_action
|
14
|
+
end
|
15
|
+
|
12
16
|
layout "blazer/application"
|
13
17
|
|
14
18
|
before_action :ensure_database_url
|
@@ -42,7 +46,7 @@ module Blazer
|
|
42
46
|
helper_method :extract_vars
|
43
47
|
|
44
48
|
def variable_params
|
45
|
-
params.except(:controller, :action, :id, :host, :query, :dashboard, :query_id, :query_ids, :table_names, :authenticity_token, :utf8, :_method, :commit, :statement, :data_source, :name)
|
49
|
+
params.except(:controller, :action, :id, :host, :query, :dashboard, :query_id, :query_ids, :table_names, :authenticity_token, :utf8, :_method, :commit, :statement, :data_source, :name, :fork_query_id)
|
46
50
|
end
|
47
51
|
helper_method :variable_params
|
48
52
|
|
@@ -17,6 +17,9 @@ module Blazer
|
|
17
17
|
data_source: params[:data_source],
|
18
18
|
name: params[:name]
|
19
19
|
)
|
20
|
+
if params[:fork_query_id]
|
21
|
+
@query.statement ||= Blazer::Query.find(params[:fork_query_id]).try(:statement)
|
22
|
+
end
|
20
23
|
end
|
21
24
|
|
22
25
|
def create
|
@@ -76,7 +79,7 @@ module Blazer
|
|
76
79
|
|
77
80
|
@rows, @error, @cached_at = @data_source.run_statement(@statement, user: blazer_user, query: @query, refresh_cache: params[:check])
|
78
81
|
|
79
|
-
if @query &&
|
82
|
+
if @query && @error != Blazer::TIMEOUT_MESSAGE
|
80
83
|
@query.checks.each do |check|
|
81
84
|
check.update_state(@rows, @error)
|
82
85
|
end
|
data/app/models/blazer/check.rb
CHANGED
@@ -9,13 +9,14 @@ module Blazer
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def update_state(rows, error)
|
12
|
+
invert = self.respond_to?(:invert) && self.invert
|
12
13
|
self.state =
|
13
14
|
if error
|
14
15
|
"error"
|
15
16
|
elsif rows.any?
|
16
|
-
"failing"
|
17
|
+
invert ? "passing" : "failing"
|
17
18
|
else
|
18
|
-
"passing"
|
19
|
+
invert ? "failing" : "passing"
|
19
20
|
end
|
20
21
|
|
21
22
|
# do not notify on creation, except when not passing
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
<% unless @check.respond_to?(:invert) %>
|
2
|
+
<p class="text-muted">Checks are designed to identify bad data. A check fails if there are any results.</p>
|
3
|
+
<% end %>
|
2
4
|
|
3
5
|
<% if @check.errors.any? %>
|
4
6
|
<div class="alert alert-danger"><%= @check.errors.full_messages.first %></div>
|
@@ -14,6 +16,19 @@
|
|
14
16
|
$("#check_query_id").selectize().parents(".hide").removeClass("hide");
|
15
17
|
</script>
|
16
18
|
</div>
|
19
|
+
|
20
|
+
<% if @check.respond_to?(:invert) %>
|
21
|
+
<div class="form-group">
|
22
|
+
<%= f.label "Fails if" %>
|
23
|
+
<div class="hide">
|
24
|
+
<%= f.select :invert, [["Any results (bad data)", false], ["No results (missing data)", true]], {}, {id: "select-invert"} %>
|
25
|
+
</div>
|
26
|
+
<script>
|
27
|
+
$("#select-invert").selectize({}).parent().removeClass("hide");
|
28
|
+
</script>
|
29
|
+
</div>
|
30
|
+
<% end %>
|
31
|
+
|
17
32
|
<div class="form-group">
|
18
33
|
<%= f.label :emails %>
|
19
34
|
<%= f.text_field :emails, placeholder: "Optional, comma separated", class: "form-control" %>
|
@@ -136,7 +136,7 @@
|
|
136
136
|
<% end %>
|
137
137
|
|
138
138
|
<% @queries.each_with_index do |query, i| %>
|
139
|
-
<div style="padding-top: 10px;">
|
139
|
+
<div style="padding-top: 10px; clear: both;">
|
140
140
|
<h4 style="text-align: center;"><%= link_to query.friendly_name, query_path(query, variable_params), target: "_blank", style: "color: inherit;" %></h4>
|
141
141
|
<div id="chart-<%= i %>" class="chart">
|
142
142
|
<p class="text-muted">Loading...</p>
|
@@ -27,6 +27,10 @@
|
|
27
27
|
<% values = @rows.first.values %>
|
28
28
|
<% chart_id = SecureRandom.hex %>
|
29
29
|
<% column_types = blazer_column_types(@columns, @rows, @boom) %>
|
30
|
+
<% chart_options = {id: chart_id, min: nil} %>
|
31
|
+
<% if (target_index = @columns.keys.map(&:downcase).index("target")) %>
|
32
|
+
<% chart_options[:library] = {series: {(target_index - 1) => {pointSize: 0, lineWidth: 3, color: "#109618"}}} %>
|
33
|
+
<% end %>
|
30
34
|
<% if blazer_maps? && @markers.any? %>
|
31
35
|
<div id="map" style="height: <%= @only_chart ? 300 : 500 %>px;"></div>
|
32
36
|
<script>
|
@@ -56,12 +60,12 @@
|
|
56
60
|
featureLayer.setGeoJSON(geojson);
|
57
61
|
map.fitBounds(featureLayer.getBounds());
|
58
62
|
</script>
|
59
|
-
<% elsif values.size >= 2 && column_types == ["time"] + (
|
63
|
+
<% elsif values.size >= 2 && column_types.compact == ["time"] + (column_types.compact.size - 1).times.map { "numeric" } %>
|
60
64
|
<% time_k = @columns.keys.first %>
|
61
|
-
<%= line_chart @columns.keys[1..-1].map{|k| {name: k, data: @rows.map{|r| [r[time_k], r[k]] }} },
|
65
|
+
<%= line_chart @columns.keys[1..-1].map{|k| {name: k, data: @rows.map{|r| [r[time_k], r[k]] }} }, chart_options %>
|
62
66
|
<% elsif values.size == 3 && column_types == ["time", "string", "numeric"] %>
|
63
67
|
<% keys = @columns.keys %>
|
64
|
-
<%= line_chart @rows.group_by { |r| k = keys[1]; v = r[k]; (@boom[k] || {})[v.to_s] || v }.map { |name, v| {name: name, data: v.map { |v2| [v2[keys[0]], v2[keys[2]]] } } },
|
68
|
+
<%= line_chart @rows.group_by { |r| k = keys[1]; v = r[k]; (@boom[k] || {})[v.to_s] || v }.map { |name, v| {name: name, data: v.map { |v2| [v2[keys[0]], v2[keys[2]]] } } }, chart_options %>
|
65
69
|
<% elsif values.size >= 2 && column_types == ["string"] + (values.size - 1).times.map { "numeric" } %>
|
66
70
|
<% keys = @columns.keys %>
|
67
71
|
<%= column_chart (values.size - 1).times.map { |i| name = @columns.keys[i + 1]; {name: name, data: @rows.first(20).map { |r| [(@boom[keys[0]] || {})[r[keys[0]].to_s] || r[keys[0]], r[keys[i + 1]]] } } }, id: chart_id %>
|
@@ -25,10 +25,10 @@
|
|
25
25
|
</div>
|
26
26
|
<div class="col-sm-3 text-right">
|
27
27
|
<%= link_to "Edit", edit_query_path(@query, variable_params), class: "btn btn-default" %>
|
28
|
-
<%= link_to "Fork", new_query_path(variable_params.merge(
|
28
|
+
<%= link_to "Fork", new_query_path(variable_params.merge(fork_query_id: @query.id, data_source: @query.data_source, name: @query.name)), class: "btn btn-info" %>
|
29
29
|
|
30
30
|
<% if !@error && @success %>
|
31
|
-
<%= button_to "Download", run_queries_path(
|
31
|
+
<%= button_to "Download", run_queries_path(query_id: @query.id, format: "csv"), params: {statement: @statement}, class: "btn btn-primary" %>
|
32
32
|
<% end %>
|
33
33
|
</div>
|
34
34
|
</div>
|
data/lib/blazer.rb
CHANGED
@@ -13,6 +13,7 @@ module Blazer
|
|
13
13
|
attr_accessor :user_name
|
14
14
|
attr_accessor :user_class
|
15
15
|
attr_accessor :user_method
|
16
|
+
attr_accessor :before_action
|
16
17
|
attr_accessor :from_email
|
17
18
|
attr_accessor :cache
|
18
19
|
attr_accessor :transform_statement
|
@@ -20,6 +21,8 @@ module Blazer
|
|
20
21
|
self.audit = true
|
21
22
|
self.user_name = :name
|
22
23
|
|
24
|
+
TIMEOUT_MESSAGE = "Query timed out :("
|
25
|
+
|
23
26
|
def self.time_zone=(time_zone)
|
24
27
|
@time_zone = time_zone.is_a?(ActiveSupport::TimeZone) ? time_zone : ActiveSupport::TimeZone[time_zone.to_s]
|
25
28
|
end
|
data/lib/blazer/data_source.rb
CHANGED
@@ -82,6 +82,7 @@ module Blazer
|
|
82
82
|
end
|
83
83
|
rescue ActiveRecord::StatementInvalid => e
|
84
84
|
error = e.message.sub(/.+ERROR: /, "")
|
85
|
+
error = Blazer::TIMEOUT_MESSAGE if error.include?("canceling statement due to statement timeout") || error.include?("cancelled on user's request")
|
85
86
|
end
|
86
87
|
end
|
87
88
|
|
data/lib/blazer/engine.rb
CHANGED
@@ -11,6 +11,7 @@ module Blazer
|
|
11
11
|
Blazer.audit = Blazer.settings.key?("audit") ? Blazer.settings["audit"] : true
|
12
12
|
Blazer.user_name = Blazer.settings["user_name"] if Blazer.settings["user_name"]
|
13
13
|
Blazer.from_email = Blazer.settings["from_email"] if Blazer.settings["from_email"]
|
14
|
+
Blazer.before_action = Blazer.settings["before_action"] if Blazer.settings["before_action"]
|
14
15
|
|
15
16
|
Blazer.user_class ||= Blazer.settings.key?("user_class") ? Blazer.settings["user_class"] : (User rescue nil)
|
16
17
|
Blazer.user_method = Blazer.settings["user_method"]
|
data/lib/blazer/version.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.1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-03-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -173,8 +173,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
173
173
|
version: '0'
|
174
174
|
requirements: []
|
175
175
|
rubyforge_project:
|
176
|
-
rubygems_version: 2.
|
176
|
+
rubygems_version: 2.6.1
|
177
177
|
signing_key:
|
178
178
|
specification_version: 4
|
179
179
|
summary: Share data effortlessly with your team
|
180
180
|
test_files: []
|
181
|
+
has_rdoc:
|