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.

@@ -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 title(title = nil)
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 format_value(key, value)
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
@@ -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
- <% title "Checks" %>
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
- <p>
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 %>", <%= json_escape({statement: @query.statement, query_id: @query.id, check: true}.to_json).html_safe %>, function (data) {
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
- <% title "Dashboards" %>
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
- <p>
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
- <% title @dashboard.name %>
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
- <%= link_to "Back", dashboards_path, class: "btn btn-primary", style: "vertical-align: top; margin-right: 5px;" %>
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: <%= json_escape({statement: query.statement, query_id: query.id, only_chart: true}.to_json).html_safe %>,
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);
@@ -97,7 +97,7 @@
97
97
 
98
98
  var error_line = null;
99
99
  var xhr;
100
- var params = <%= raw json_escape(variable_params.to_json) %>;
100
+ var params = <%= raw blazer_json_escape(variable_params.to_json) %>;
101
101
 
102
102
  $("#run").click(function (e) {
103
103
  e.preventDefault();
@@ -1 +1,2 @@
1
+ <% blazer_title "Edit - #{@query.name}" %>
1
2
  <%= render partial: "form" %>
@@ -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
- <%= link_to "Dashboards", dashboards_path, class: "btn btn-primary" %>
6
- <%= link_to "Checks", checks_path, class: "btn btn-primary" %>
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 %>", updateList);
48
+ $(".list").load("<%= queries_path %>", function () {
49
+ updateList();
50
+ $("#loading").remove();
51
+ });
39
52
  </script>
40
53
  <% end %>
@@ -1 +1,2 @@
1
+ <% blazer_title "New Query" %>
1
2
  <%= render partial: "form" %>
@@ -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;"><%= format_value(@rows.first.keys.first, @rows.first.values.first) %></p>
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 format_value(k, v), @linked_columns[k].gsub("{value}", u(v.to_s)), target: "_blank" %>
102
+ <%= link_to blazer_format_value(k, v), @linked_columns[k].gsub("{value}", u(v.to_s)), target: "_blank" %>
74
103
  <% else %>
75
- <%= format_value(k, v) %>
104
+ <%= blazer_format_value(k, v) %>
76
105
  <% end %>
77
106
 
78
107
  <% if v2 = (@boom[k] || {})[v] %>
@@ -1,4 +1,4 @@
1
- <% title @query.name %>
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
- <%= link_to "Home", root_path, class: "btn btn-primary", style: "vertical-align: top; margin-right: 5px;" %>
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: <%= json_escape(variable_params.merge(statement: @statement, query_id: @query.id).to_json).html_safe %>,
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><%= title ? title : "Blazer" %></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>
@@ -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
- ["PostgreSQL", "Redshift"].include?(connection_model.connection.adapter_name)
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
@@ -1,3 +1,3 @@
1
1
  module Blazer
2
- VERSION = "1.0.2"
2
+ VERSION = "1.0.3"
3
3
  end
data/lib/blazer.rb CHANGED
@@ -14,6 +14,7 @@ module Blazer
14
14
  attr_accessor :user_method
15
15
  attr_accessor :from_email
16
16
  attr_accessor :cache
17
+ attr_accessor :transform_statement
17
18
  end
18
19
  self.audit = true
19
20
  self.user_name = :name
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.2
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-12 00:00:00.000000000 Z
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