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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4cdb1f1e5abc2ac4d6e02a1726c8f681b09e6f29
4
- data.tar.gz: 8e9b44772f5f47c74f746ca5a82288c45205f9fe
3
+ metadata.gz: 7d498bb03f6c2cdf408e73065449df3d27f7d2e4
4
+ data.tar.gz: b23b774a851a748277ffd1a1b33a420ca75f35ed
5
5
  SHA512:
6
- metadata.gz: 630ba5e2d23c39f6a7e782d67e077e38b2c3450c64b7cff0576a6d9237d701ab6d1a7c87b90ae52590fcc9ffd8921e3a53159b87f49c2570fc45df52bcb5d283
7
- data.tar.gz: 10841c3aa381ebe11c471abcf3bff15e5d2023f4ec28aecbf0eebc1703317f039f532095723fa10ff1b729a936a56388c92dc2af991f3b1096df315193f613f1
6
+ metadata.gz: 6f551893a6c87914244c745aa481e01339465b7c59b97caac8a3c323dc378be92bf8ec39ed8d2ad64012880be5cbb909bdf6c8f5278bd3b85930aa1ab17f5b5a
7
+ data.tar.gz: 3fe76a4cb97e6b8f55a338b5c0bbde9564a972bee3fba93bc6b04b9f7bc7331b975abf87fd514b18c5ab6c72039ef2398449539747e9271d1a235fb97a1c236e
@@ -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
+ }
@@ -5,9 +5,8 @@ github.com style (c) Vasily Polovnyov <vast@whiteants.net>
5
5
  */
6
6
 
7
7
  .hljs {
8
- display: block; padding: 0.5em;
8
+ display: block;
9
9
  color: #333;
10
- background: #f8f8f8
11
10
  }
12
11
 
13
12
  .hljs-comment,
@@ -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
 
@@ -41,7 +41,7 @@ module Blazer
41
41
  private
42
42
 
43
43
  def check_params
44
- params.require(:check).permit(:query_id, :emails)
44
+ params.require(:check).permit(:query_id, :emails, :invert)
45
45
  end
46
46
 
47
47
  def set_check
@@ -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 && !@error.to_s.include?("canceling statement due to statement timeout")
82
+ if @query && @error != Blazer::TIMEOUT_MESSAGE
80
83
  @query.checks.each do |check|
81
84
  check.update_state(@rows, @error)
82
85
  end
@@ -25,6 +25,8 @@ module Blazer
25
25
  "numeric"
26
26
  elsif v.is_a?(Time) || v.is_a?(Date)
27
27
  "time"
28
+ elsif v.nil?
29
+ nil
28
30
  else
29
31
  "string"
30
32
  end
@@ -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
- <p class="text-muted">Checks are designed to identify bad data. A check fails if there are any results.</p>
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>
@@ -146,4 +146,6 @@
146
146
  $("#query_statement").val(editor.getValue());
147
147
  return true;
148
148
  });
149
+
150
+ preventBackspaceNav();
149
151
  </script>
@@ -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"] + (values.size - 1).times.map { "numeric" } %>
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]] }} }, id: chart_id, min: nil %>
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]]] } } }, id: chart_id, min: nil %>
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(statement: @query.statement, data_source: @query.data_source, name: "Fork of #{@query.name}")), class: "btn btn-info" %>
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(statement: @statement, query_id: @query.id, format: "csv"), class: "btn btn-primary" %>
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>
@@ -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
@@ -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
 
@@ -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"]
@@ -1,3 +1,3 @@
1
1
  module Blazer
2
- VERSION = "1.1.0"
2
+ VERSION = "1.1.1"
3
3
  end
@@ -40,5 +40,8 @@ audit: true
40
40
  # method name for the user model
41
41
  # user_name: name
42
42
 
43
+ # optional auth method to use as a before_action (default: nil)
44
+ # before_action: :authenticate!
45
+
43
46
  # email to send checks from
44
47
  # from_email: blazer@example.org
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.0
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: 2015-12-28 00:00:00.000000000 Z
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.4.5.1
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: