railsblazer 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +1 -0
  3. data/.github/ISSUE_TEMPLATE.md +0 -0
  4. data/.gitignore +14 -0
  5. data/CHANGELOG.md +247 -0
  6. data/CONTRIBUTING.md +42 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +855 -0
  10. data/Rakefile +1 -0
  11. data/app/assets/fonts/blazer/glyphicons-halflings-regular.eot +0 -0
  12. data/app/assets/fonts/blazer/glyphicons-halflings-regular.svg +288 -0
  13. data/app/assets/fonts/blazer/glyphicons-halflings-regular.ttf +0 -0
  14. data/app/assets/fonts/blazer/glyphicons-halflings-regular.woff +0 -0
  15. data/app/assets/fonts/blazer/glyphicons-halflings-regular.woff2 +0 -0
  16. data/app/assets/javascripts/blazer/Chart.js +14145 -0
  17. data/app/assets/javascripts/blazer/Sortable.js +1144 -0
  18. data/app/assets/javascripts/blazer/ace.js +6 -0
  19. data/app/assets/javascripts/blazer/ace/ace.js +11 -0
  20. data/app/assets/javascripts/blazer/ace/ext-language_tools.js +5 -0
  21. data/app/assets/javascripts/blazer/ace/mode-sql.js +1 -0
  22. data/app/assets/javascripts/blazer/ace/snippets/sql.js +1 -0
  23. data/app/assets/javascripts/blazer/ace/snippets/text.js +1 -0
  24. data/app/assets/javascripts/blazer/ace/theme-twilight.js +1 -0
  25. data/app/assets/javascripts/blazer/application.js +79 -0
  26. data/app/assets/javascripts/blazer/bootstrap.js +2366 -0
  27. data/app/assets/javascripts/blazer/chartkick.js +1693 -0
  28. data/app/assets/javascripts/blazer/daterangepicker.js +1505 -0
  29. data/app/assets/javascripts/blazer/fuzzysearch.js +24 -0
  30. data/app/assets/javascripts/blazer/highlight.pack.js +1 -0
  31. data/app/assets/javascripts/blazer/jquery.js +10308 -0
  32. data/app/assets/javascripts/blazer/jquery.stickytableheaders.js +263 -0
  33. data/app/assets/javascripts/blazer/jquery_ujs.js +469 -0
  34. data/app/assets/javascripts/blazer/moment-timezone.js +1007 -0
  35. data/app/assets/javascripts/blazer/moment.js +3043 -0
  36. data/app/assets/javascripts/blazer/queries.js +110 -0
  37. data/app/assets/javascripts/blazer/routes.js +23 -0
  38. data/app/assets/javascripts/blazer/selectize.js +3667 -0
  39. data/app/assets/javascripts/blazer/stupidtable.js +114 -0
  40. data/app/assets/javascripts/blazer/vue.js +7515 -0
  41. data/app/assets/stylesheets/blazer/application.css +198 -0
  42. data/app/assets/stylesheets/blazer/bootstrap.css.erb +6202 -0
  43. data/app/assets/stylesheets/blazer/daterangepicker-bs3.css +375 -0
  44. data/app/assets/stylesheets/blazer/github.css +125 -0
  45. data/app/assets/stylesheets/blazer/selectize.default.css +387 -0
  46. data/app/controllers/blazer/base_controller.rb +113 -0
  47. data/app/controllers/blazer/checks_controller.rb +56 -0
  48. data/app/controllers/blazer/dashboards_controller.rb +105 -0
  49. data/app/controllers/blazer/queries_controller.rb +337 -0
  50. data/app/helpers/blazer/base_helper.rb +57 -0
  51. data/app/mailers/blazer/check_mailer.rb +27 -0
  52. data/app/mailers/blazer/slack_notifier.rb +76 -0
  53. data/app/models/blazer/audit.rb +6 -0
  54. data/app/models/blazer/check.rb +104 -0
  55. data/app/models/blazer/connection.rb +5 -0
  56. data/app/models/blazer/dashboard.rb +13 -0
  57. data/app/models/blazer/dashboard_query.rb +9 -0
  58. data/app/models/blazer/query.rb +40 -0
  59. data/app/models/blazer/record.rb +5 -0
  60. data/app/views/blazer/_nav.html.erb +16 -0
  61. data/app/views/blazer/_variables.html.erb +102 -0
  62. data/app/views/blazer/check_mailer/failing_checks.html.erb +6 -0
  63. data/app/views/blazer/check_mailer/state_change.html.erb +47 -0
  64. data/app/views/blazer/checks/_form.html.erb +79 -0
  65. data/app/views/blazer/checks/edit.html.erb +1 -0
  66. data/app/views/blazer/checks/index.html.erb +43 -0
  67. data/app/views/blazer/checks/new.html.erb +1 -0
  68. data/app/views/blazer/dashboards/_form.html.erb +76 -0
  69. data/app/views/blazer/dashboards/edit.html.erb +1 -0
  70. data/app/views/blazer/dashboards/new.html.erb +1 -0
  71. data/app/views/blazer/dashboards/show.html.erb +47 -0
  72. data/app/views/blazer/queries/_form.html.erb +240 -0
  73. data/app/views/blazer/queries/edit.html.erb +2 -0
  74. data/app/views/blazer/queries/home.html.erb +152 -0
  75. data/app/views/blazer/queries/new.html.erb +2 -0
  76. data/app/views/blazer/queries/run.html.erb +165 -0
  77. data/app/views/blazer/queries/schema.html.erb +20 -0
  78. data/app/views/blazer/queries/show.html.erb +73 -0
  79. data/app/views/layouts/blazer/application.html.erb +24 -0
  80. data/blazer-0.0.1.gem +0 -0
  81. data/blazer.gemspec +27 -0
  82. data/config/routes.rb +16 -0
  83. data/lib/blazer.rb +223 -0
  84. data/lib/blazer/adapters/athena_adapter.rb +128 -0
  85. data/lib/blazer/adapters/base_adapter.rb +53 -0
  86. data/lib/blazer/adapters/bigquery_adapter.rb +68 -0
  87. data/lib/blazer/adapters/cassandra_adapter.rb +59 -0
  88. data/lib/blazer/adapters/drill_adapter.rb +28 -0
  89. data/lib/blazer/adapters/druid_adapter.rb +67 -0
  90. data/lib/blazer/adapters/elasticsearch_adapter.rb +46 -0
  91. data/lib/blazer/adapters/mongodb_adapter.rb +39 -0
  92. data/lib/blazer/adapters/presto_adapter.rb +45 -0
  93. data/lib/blazer/adapters/snowflake_adapter.rb +73 -0
  94. data/lib/blazer/adapters/sql_adapter.rb +182 -0
  95. data/lib/blazer/data_source.rb +195 -0
  96. data/lib/blazer/detect_anomalies.R +19 -0
  97. data/lib/blazer/engine.rb +30 -0
  98. data/lib/blazer/result.rb +170 -0
  99. data/lib/blazer/run_statement.rb +40 -0
  100. data/lib/blazer/run_statement_job.rb +21 -0
  101. data/lib/blazer/version.rb +3 -0
  102. data/lib/generators/blazer/install_generator.rb +39 -0
  103. data/lib/generators/blazer/templates/config.yml.tt +62 -0
  104. data/lib/generators/blazer/templates/install.rb.tt +46 -0
  105. data/lib/tasks/blazer.rake +11 -0
  106. data/railsblazer-0.0.1.gem +0 -0
  107. metadata +234 -0
@@ -0,0 +1,2 @@
1
+ <% blazer_title "Edit - #{@query.name}" %>
2
+ <%= render partial: "form" %>
@@ -0,0 +1,152 @@
1
+ <div id="queries">
2
+ <div id="header" style="margin-bottom: 20px;">
3
+ <div class="pull-right">
4
+ <% if blazer_user %>
5
+ <%= link_to "All", root_path, class: !params[:filter] ? "active" : nil, style: "margin-right: 40px;" %>
6
+
7
+ <% if Blazer.audit %>
8
+ <%= link_to "Viewed", root_path(filter: "viewed"), class: params[:filter] == "viewed" ? "active" : nil, style: "margin-right: 40px;" %>
9
+ <% end %>
10
+
11
+ <%= link_to "Mine", root_path(filter: "mine"), class: params[:filter] == "mine" ? "active" : nil, style: "margin-right: 40px;" %>
12
+ <% end %>
13
+ <div class="btn-group">
14
+ <%= link_to "New Query", new_query_path, class: "btn btn-info" %>
15
+ <button type="button" class="btn btn-info dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
16
+ <span class="caret"></span>
17
+ <span class="sr-only">Toggle Dropdown</span>
18
+ </button>
19
+ <ul class="dropdown-menu">
20
+ <li><%= link_to "Dashboards", dashboards_path %></li>
21
+ <li><%= link_to "Checks", checks_path %></li>
22
+ <li role="separator" class="divider"></li>
23
+ <li><%= link_to "New Dashboard", new_dashboard_path %></li>
24
+ <li><%= link_to "New Check", new_check_path %></li>
25
+ </ul>
26
+ </div>
27
+ </div>
28
+ <input type="text" v-model="searchTerm" placeholder="Start typing a query or person" style="width: 300px; display: inline-block;" autofocus=true class="search form-control" />
29
+ </div>
30
+
31
+ <table class="table">
32
+ <thead>
33
+ <tr>
34
+ <th>Name</th>
35
+ <th style="width: 20%; text-align: right;">Mastermind</th>
36
+ </tr>
37
+ </thead>
38
+ <tbody class="list" v-cloak>
39
+ <tr v-for="query in visibleItems">
40
+ <td>
41
+ <a :href="itemPath(query)" :class="{ dashboard: query.dashboard }">{{ query.name }}</a>
42
+ <span class="vars">{{ query.vars }}</span>
43
+ </td>
44
+ <td class="creator">{{ query.creator }}</td>
45
+ </tr>
46
+ </tbody>
47
+ </table>
48
+
49
+ <p v-if="more" class="text-muted">Loading...</p>
50
+ </div>
51
+
52
+ <script>
53
+ <%= blazer_js_var "dashboards", @dashboards %>
54
+ <%= blazer_js_var "queries", @queries %>
55
+ <%= blazer_js_var "more", @more %>
56
+
57
+ var prepareSearch = function (list) {
58
+ var i, q, searchStr
59
+ for (i = 0; i < list.length; i++) {
60
+ q = list[i]
61
+ searchStr = q.name + q.creator
62
+ if (q.creator === "You") {
63
+ searchStr += "mine me"
64
+ }
65
+ q.searchStr = prepareQuery(searchStr)
66
+ }
67
+ }
68
+
69
+ var prepareQuery = function (str) {
70
+ return str.toLowerCase().replace(/\W+/g, "")
71
+ }
72
+
73
+ var app = new Vue({
74
+ el: "#queries",
75
+ data: {
76
+ searchTerm: "",
77
+ more: more,
78
+ updateCounter: 0
79
+ },
80
+ created: function() {
81
+ this.listItems = dashboards.concat(queries)
82
+
83
+ prepareSearch(this.listItems)
84
+
85
+ this.queryIds = {}
86
+ for (i = 0; i < queries.length; i++) {
87
+ this.queryIds[queries[i].id] = true
88
+ }
89
+
90
+ if (this.more) {
91
+ var _this = this
92
+
93
+ $.getJSON(Routes.queries_path(), function (data) {
94
+ var i, j, newValues, val, size = 500;
95
+
96
+ var newValues = []
97
+ for (j = 0; j < data.length; j++) {
98
+ val = data[j]
99
+ if (val && !_this.queryIds[val.id]) {
100
+ newValues.push(val)
101
+ }
102
+ }
103
+
104
+ prepareSearch(newValues)
105
+
106
+ _this.listItems = _this.listItems.concat(newValues)
107
+ _this.more = false
108
+ // hack to get to update
109
+ _this.updateCounter++
110
+ })
111
+ }
112
+ },
113
+ computed: {
114
+ visibleItems: function () {
115
+ // hack to get to update
116
+ this.updateCounter
117
+
118
+ var pageSize = 200
119
+ var q, i
120
+
121
+ if (this.searchTerm.length > 0) {
122
+ var term = prepareQuery(this.searchTerm)
123
+ var items = []
124
+ var fuzzyItems = []
125
+ for (i = 0; i < this.listItems.length; i++) {
126
+ q = this.listItems[i]
127
+ if (q.searchStr.indexOf(term) !== -1) {
128
+ items.push(q)
129
+ if (items.length == pageSize) {
130
+ break
131
+ }
132
+ } else if (fuzzysearch(term, q.searchStr)) {
133
+ fuzzyItems.push(q)
134
+ }
135
+ }
136
+ return items.concat(fuzzyItems).slice(0, pageSize)
137
+ } else {
138
+ return this.listItems.slice(0, pageSize)
139
+ }
140
+ }
141
+ },
142
+ methods: {
143
+ itemPath: function (item) {
144
+ if (item.dashboard) {
145
+ return Routes.dashboard_path(item.to_param)
146
+ } else {
147
+ return Routes.query_path(item.to_param)
148
+ }
149
+ }
150
+ }
151
+ })
152
+ </script>
@@ -0,0 +1,2 @@
1
+ <% blazer_title "New Query" %>
2
+ <%= render partial: "form" %>
@@ -0,0 +1,165 @@
1
+ <% if @error %>
2
+ <div class="alert alert-danger"><%= @error.first(200) %></div>
3
+ <% elsif !@success %>
4
+ <% if @only_chart %>
5
+ <p class="text-muted">Select variables</p>
6
+ <% else %>
7
+ <div class="alert alert-info">Can’t preview queries with variables...yet!</div>
8
+ <% end %>
9
+ <% else %>
10
+ <% unless @only_chart %>
11
+ <% if @cached_at || @just_cached %>
12
+ <p class="text-muted" style="float: right;">
13
+ <% if @cached_at %>
14
+ Cached <%= time_ago_in_words(@cached_at, include_seconds: true) %> ago
15
+ <% elsif !params[:data_source] %>
16
+ Cached just now
17
+ <% if @data_source.cache_mode == "slow" %>
18
+ (over <%= "%g" % @data_source.cache_slow_threshold %>s)
19
+ <% end %>
20
+ <% end %>
21
+
22
+ <% if @query && !params[:data_source] %>
23
+ <%= link_to "Refresh", refresh_query_path(@query, variable_params), method: :post %>
24
+ <% end %>
25
+ </p>
26
+ <% end %>
27
+ <p class="text-muted">
28
+ <%= pluralize(@rows.size, "row") %>
29
+
30
+ <% @checks.select(&:state).each do |check| %>
31
+ &middot; <small class="check-state <%= check.state.parameterize.gsub("-", "_") %>"><%= link_to check.state.upcase, edit_check_path(check) %></small>
32
+ <% if check.try(:message) %>
33
+ &middot; <%= check.message %>
34
+ <% end %>
35
+ <% end %>
36
+ </p>
37
+ <% end %>
38
+ <% if @rows.any? %>
39
+ <% values = @rows.first %>
40
+ <% chart_id = SecureRandom.hex %>
41
+ <% column_types = @result.column_types %>
42
+ <% chart_type = @result.chart_type %>
43
+ <% chart_options = {id: chart_id, min: nil} %>
44
+ <% series_library = {} %>
45
+ <% target_index = @columns.index { |k| k.downcase == "target" } %>
46
+ <% if target_index %>
47
+ <% series_library[target_index - 1] = {pointStyle: "line", hitRadius: 5, borderColor: "#109618", pointBackgroundColor: "#109618", backgroundColor: "#109618"} %>
48
+ <% end %>
49
+ <% if blazer_maps? && @markers.any? %>
50
+ <div id="map" style="height: <%= @only_chart ? 300 : 500 %>px;"></div>
51
+ <script>
52
+ L.mapbox.accessToken = '<%= ENV["MAPBOX_ACCESS_TOKEN"] %>';
53
+ var map = L.mapbox.map('map', 'ankane.ioo8nki0');
54
+ <%= blazer_js_var "markers", @markers %>
55
+ var featureLayer = L.mapbox.featureLayer().addTo(map);
56
+ var geojson = [];
57
+ for (var i = 0; i < markers.length; i++) {
58
+ var marker = markers[i];
59
+ geojson.push({
60
+ type: 'Feature',
61
+ geometry: {
62
+ type: 'Point',
63
+ coordinates: [
64
+ marker.longitude,
65
+ marker.latitude
66
+ ]
67
+ },
68
+ properties: {
69
+ description: marker.title,
70
+ 'marker-color': '#f86767',
71
+ 'marker-size': 'medium'
72
+ }
73
+ });
74
+ }
75
+ featureLayer.setGeoJSON(geojson);
76
+ map.fitBounds(featureLayer.getBounds());
77
+ </script>
78
+ <% elsif chart_type == "line" %>
79
+ <%= line_chart @columns[1..-1].each_with_index.map{ |k, i| {name: blazer_series_name(k), data: @rows.map{ |r| [r[0], r[i + 1]] }, library: series_library[i]} }, chart_options %>
80
+ <% elsif chart_type == "line2" %>
81
+ <%= line_chart @rows.group_by { |r| v = r[1]; (@boom[@columns[1]] || {})[v.to_s] || v }.each_with_index.map { |(name, v), i| {name: blazer_series_name(name), data: v.map { |v2| [v2[0], v2[2]] }, library: series_library[i]} }, chart_options %>
82
+ <% elsif chart_type == "bar" %>
83
+ <%= column_chart (values.size - 1).times.map { |i| name = @columns[i + 1]; {name: blazer_series_name(name), data: @rows.first(20).map { |r| [(@boom[@columns[0]] || {})[r[0].to_s] || r[0], r[i + 1]] } } }, id: chart_id %>
84
+ <% elsif chart_type == "bar2" %>
85
+ <% first_20 = @rows.group_by { |r| r[0] }.values.first(20).flatten(1) %>
86
+ <% labels = first_20.map { |r| r[0] }.uniq %>
87
+ <% series = first_20.map { |r| r[1] }.uniq %>
88
+ <% labels.each do |l| %>
89
+ <% series.each do |s| %>
90
+ <% first_20 << [l, s, 0] unless first_20.find { |r| r[0] == l && r[1] == s } %>
91
+ <% end %>
92
+ <% end %>
93
+ <%= column_chart first_20.group_by { |r| v = r[1]; (@boom[@columns[1]] || {})[v.to_s] || v }.each_with_index.map { |(name, v), i| {name: blazer_series_name(name), data: v.sort_by { |r2| labels.index(r2[0]) }.map { |v2| v3 = v2[0]; [(@boom[@columns[0]] || {})[v3.to_s] || v3, v2[2]] }} }, id: chart_id %>
94
+ <% elsif chart_type == "scatter" %>
95
+ <%= scatter_chart @rows, xtitle: @columns[0], ytitle: @columns[1], id: chart_id %>
96
+ <% elsif @only_chart %>
97
+ <% if @rows.size == 1 && @rows.first.size == 1 %>
98
+ <% v = @rows.first.first %>
99
+ <% if v.is_a?(String) && v == "" %>
100
+ <div class="text-muted">empty string</div>
101
+ <% else %>
102
+ <p style="font-size: 160px;"><%= blazer_format_value(@columns.first, v) %></p>
103
+ <% end %>
104
+ <% else %>
105
+ <% @no_chart = true %>
106
+ <% end %>
107
+ <% end %>
108
+
109
+ <% unless @only_chart && !@no_chart %>
110
+ <% header_width = 100 / @columns.size.to_f %>
111
+ <div class="results-container">
112
+ <% if @columns == ["QUERY PLAN"] %>
113
+ <pre><code><%= @rows.map { |r| r[0] }.join("\n") %></code></pre>
114
+ <% elsif @columns == ["PLAN"] && @data_source.adapter == "druid" %>
115
+ <pre><code><%= @rows[0][0] %></code></pre>
116
+ <% else %>
117
+ <table class="table results-table" style="margin-bottom: 0;">
118
+ <thead>
119
+ <tr>
120
+ <% @columns.each_with_index do |key, i| %>
121
+ <% type = @column_types[i] %>
122
+ <th style="width: <%= header_width %>%;" data-sort="<%= type %>">
123
+ <div style="min-width: <%= @min_width_types.include?(i) ? 180 : 60 %>px;">
124
+ <%= key %>
125
+ </div>
126
+ </th>
127
+ <% end %>
128
+ </tr>
129
+ </thead>
130
+ <tbody>
131
+ <% @rows.each do |row| %>
132
+ <tr>
133
+ <% row.each_with_index do |v, i| %>
134
+ <% k = @columns[i] %>
135
+ <td>
136
+ <% if v.is_a?(Time) %>
137
+ <% v = blazer_time_value(@data_source, k, v) %>
138
+ <% end %>
139
+
140
+ <% unless v.nil? %>
141
+ <% if v.is_a?(String) && v == "" %>
142
+ <div class="text-muted">empty string</div>
143
+ <% elsif @linked_columns[k] %>
144
+ <%= link_to blazer_format_value(k, v), @linked_columns[k].gsub("{value}", u(v.to_s)), target: "_blank" %>
145
+ <% else %>
146
+ <%= blazer_format_value(k, v) %>
147
+ <% end %>
148
+ <% end %>
149
+
150
+ <% if v2 = (@boom[k] || {})[v.nil? ? v : v.to_s] %>
151
+ <div class="text-muted"><%= v2 %></div>
152
+ <% end %>
153
+ </td>
154
+ <% end %>
155
+ </tr>
156
+ <% end %>
157
+ </tbody>
158
+ </table>
159
+ <% end %>
160
+ </div>
161
+ <% end %>
162
+ <% elsif @only_chart %>
163
+ <p class="text-muted">No rows</p>
164
+ <% end %>
165
+ <% end %>
@@ -0,0 +1,20 @@
1
+ <% blazer_title "Database Schema" %>
2
+
3
+ <% @schema.each do |table| %>
4
+ <h4>
5
+ <%= table[:table] %>
6
+ <% if table[:schema] != "public" %>
7
+ <small><%= table[:schema] %></small>
8
+ <% end %>
9
+ </h4>
10
+ <table class="table" style="max-width: 500px;">
11
+ <tbody>
12
+ <% table[:columns].each do |column| %>
13
+ <tr>
14
+ <td style="width: 60%;"><%= column[:name] %></td>
15
+ <td class="text-muted"><%= column[:data_type] %></td>
16
+ </tr>
17
+ <% end %>
18
+ </tbody>
19
+ </table>
20
+ <% end %>
@@ -0,0 +1,73 @@
1
+ <% blazer_title @query.name %>
2
+
3
+ <div class="topbar">
4
+ <div class="container">
5
+ <div class="row" style="padding-top: 13px;">
6
+ <div class="col-sm-9">
7
+ <%= render partial: "blazer/nav" %>
8
+ <h3 style="margin: 0; line-height: 34px; display: inline;">
9
+ <%= @query.name %>
10
+ </h3>
11
+ </div>
12
+ <div class="col-sm-3 text-right">
13
+ <%= link_to "Edit", edit_query_path(@query, variable_params), class: "btn btn-default", disabled: !@query.editable?(blazer_user) %>
14
+ <%= 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" %>
15
+
16
+ <% if !@error && @success %>
17
+ <%= button_to "Download", run_queries_path(query_id: @query.id, format: "csv"), params: {statement: @statement}, class: "btn btn-primary" %>
18
+ <% end %>
19
+ </div>
20
+ </div>
21
+ </div>
22
+ </div>
23
+
24
+ <div style="margin-bottom: 60px;"></div>
25
+
26
+ <% if @sql_errors.any? %>
27
+ <div class="alert alert-danger">
28
+ <ul>
29
+ <% @sql_errors.each do |message| %>
30
+ <li><%= message %></li>
31
+ <% end %>
32
+ </ul>
33
+ </div>
34
+ <% end %>
35
+
36
+ <% if @query.description.present? %>
37
+ <p><%= @query.description %></p>
38
+ <% end %>
39
+
40
+ <%= render partial: "blazer/variables", locals: {action: query_path(@query)} %>
41
+
42
+ <pre id="code"><code><%= @statement %></code></pre>
43
+
44
+ <% if @success %>
45
+ <div id="results">
46
+ <p class="text-muted">Loading...</p>
47
+ </div>
48
+
49
+ <script>
50
+ function showRun(data) {
51
+ $("#results").html(data)
52
+ $("#results table").stupidtable().stickyTableHeaders({fixedOffset: 60})
53
+ }
54
+
55
+ function showError(message) {
56
+ $("#results").addClass("query-error").html(message)
57
+ }
58
+
59
+ <%= blazer_js_var "data", variable_params.merge(statement: @statement, query_id: @query.id) %>
60
+
61
+ runQuery(data, showRun, showError)
62
+ </script>
63
+ <% end %>
64
+
65
+ <% unless %w(mongodb).include?(Blazer.data_sources[@query.data_source].adapter) %>
66
+ <script>
67
+ // do not highlight really long queries
68
+ // this can lead to performance issues
69
+ if ($("code").text().length < 10000) {
70
+ hljs.highlightBlock(document.getElementById("code"));
71
+ }
72
+ </script>
73
+ <% end %>
@@ -0,0 +1,24 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title><%= blazer_title ? blazer_title : "Blazer" %></title>
5
+
6
+ <meta charset="utf-8" />
7
+
8
+ <%= stylesheet_link_tag "blazer/application" %>
9
+ <%= javascript_include_tag "blazer/application" %>
10
+ <script>
11
+ <%= blazer_js_var "rootPath", root_path %>
12
+ </script>
13
+ <% if blazer_maps? %>
14
+ <%= stylesheet_link_tag "https://api.mapbox.com/mapbox.js/v3.1.1/mapbox.css", integrity: "sha384-o8tecBIfqi9yU5yYK2Ne/9A9hlOGFV9MBvCpmemvJH1XxqOe6h8Bl4mLxMi6PgjG", crossorigin: "anonymous" %>
15
+ <%= javascript_include_tag "https://api.mapbox.com/mapbox.js/v3.1.1/mapbox.js", integrity: "sha384-j81LqvtvYigFzGSUgAoFijpvoq4yGoCJSOXI9DFaUEpenR029MBE3E/X5Gr+WdO0", crossorigin: "anonymous" %>
16
+ <% end %>
17
+ <%= csrf_meta_tags %>
18
+ </head>
19
+ <body>
20
+ <div class="container">
21
+ <%= yield %>
22
+ </div>
23
+ </body>
24
+ </html>
Binary file