sql-jarvis 2.1 → 2.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,7 @@
1
1
  module Blazer
2
2
  class Query < Record
3
3
  serialize :assignee_ids, Array
4
+ serialize :team_ids, Array
4
5
 
5
6
  belongs_to :creator, Blazer::BELONGS_TO_OPTIONAL.merge(class_name: Blazer.user_class.to_s) if Blazer.user_class
6
7
  has_many :checks, dependent: :destroy
@@ -8,6 +9,7 @@ module Blazer
8
9
  has_many :dashboards, through: :dashboard_queries
9
10
  has_many :audits
10
11
 
12
+ before_validation :statement_format
11
13
  validates :statement, presence: true
12
14
 
13
15
  scope :named, -> { where("blazer_queries.name <> ''") }
@@ -42,5 +44,12 @@ module Blazer
42
44
  def variables
43
45
  Blazer.extract_vars(statement)
44
46
  end
47
+
48
+ private
49
+
50
+ def statement_format
51
+ self.statement.gsub!(/\n/, '')
52
+ end
53
+
45
54
  end
46
55
  end
@@ -3,10 +3,8 @@
3
3
  #{blazer_js_var "timeZone", Blazer.time_zone.tzinfo.name}
4
4
  var now = moment.tz(timeZone)
5
5
  var format = "YYYY-MM-DD"
6
+ function toDate(time) { return moment.tz(time.format(format), timeZone) }
6
7
 
7
- function toDate(time) {
8
- return moment.tz(time.format(format), timeZone)
9
- }
10
8
  %form#bind.form-inline{:action => action, :method => "get", :style => "margin-bottom: 15px;"}
11
9
  - date_vars = ["start_time", "end_time"]
12
10
  - if (date_vars - @bind_vars).empty?
@@ -16,7 +14,7 @@
16
14
  - @bind_vars.each_with_index do |var, i|
17
15
  = label_tag var, var
18
16
  - if (data = @smart_vars[var])
19
- = select_tag var, options_for_select([[nil, nil]] + data, selected: params[var]), style: "margin-right: 20px; width: 200px; display: none;", multiple: true
17
+ = select_tag var, options_for_select(data, selected: params[var]), style: "margin-right: 20px; width: 200px; display: none;", multiple: true
20
18
  :javascript
21
19
  $("##{var}").selectize({
22
20
  create: true
@@ -100,3 +98,4 @@
100
98
  submitIfCompleted($("#start_time").closest("form"))
101
99
  }
102
100
  %input.btn.btn-success{:style => "vertical-align: top;", :type => "submit", :value => "Run"}/
101
+ %hr
@@ -17,17 +17,18 @@
17
17
  = render partial: "blazer/variables", locals: {action: dashboard_path(@dashboard)}
18
18
  - else
19
19
  %div{:style => "padding-bottom: 15px;"}
20
- - @queries.each_with_index do |query, i|
21
- .chart-container
22
- %h4= link_to query.friendly_name, query_path(query, variable_params), target: "_blank"
23
- .chart{:id => "chart-#{i}"}
24
- %p.text-muted Loading...
25
- :javascript
26
- #{blazer_js_var "data", {statement: query.statement, query_id: query.id, data_source: query.data_source, only_chart: true}}
20
+ .dashboard
21
+ - @queries.each_with_index do |query, i|
22
+ .chart-container
23
+ %h4= link_to query.friendly_name, query_path(query, variable_params), target: "_blank"
24
+ .chart{:id => "chart-#{i}"}
25
+ %p.text-muted Loading...
26
+ :javascript
27
+ #{blazer_js_var "data", {statement: query.statement, query_id: query.id, data_source: query.data_source, only_chart: true}}
27
28
 
28
- runQuery(data, function (data) {
29
- $("#chart-#{i}").html(data)
30
- $("#chart-#{i} table").stupidtable()
31
- }, function (message) {
32
- $("#chart-#{i}").addClass("query-error").html(message)
33
- });
29
+ runQuery(data, function (data) {
30
+ $("#chart-#{i}").html(data)
31
+ $("#chart-#{i} table").stupidtable()
32
+ }, function (message) {
33
+ $("#chart-#{i}").addClass("query-error").html(message)
34
+ });
@@ -0,0 +1,52 @@
1
+ - values = rows.first
2
+ - chart_id = SecureRandom.hex
3
+ - column_types = result.column_types
4
+ - chart_type = result.chart_type
5
+ - chart_options = { id: chart_id, height: '40vh' }
6
+
7
+ - if ["line", "line2"].include?(chart_type)
8
+ - chart_options.merge!(min: nil)
9
+ - if chart_type == "scatter"
10
+ - chart_options.merge!(library: {tooltips: {intersect: false}})
11
+ - elsif ["bar", "bar2"].include?(chart_type)
12
+ - chart_options.merge!(library: {tooltips: {intersect: false, axis: 'x'}})
13
+ - elsif chart_type != "pie"
14
+ - if column_types.size == 2 || forecast
15
+ - chart_options.merge!(library: {tooltips: {intersect: false, axis: 'x'}})
16
+ - else
17
+ - chart_options.merge!(library: {tooltips: {intersect: false}})
18
+ - series_library = {}
19
+ - target_index = columns.index { |k| k.downcase == "target" }
20
+ - if target_index
21
+ - series_library[target_index - 1] = {pointStyle: "line", hitRadius: 5, borderColor: "#109618", pointBackgroundColor: "#109618", backgroundColor: "#109618"}
22
+ - if forecast
23
+ - color = "#54a3ee"
24
+ - series_library[1] = {borderDash: [8], borderColor: color, pointBackgroundColor: color, backgroundColor: color, pointHoverBackgroundColor: color}
25
+ - elsif chart_type == "line"
26
+ - chart_data = 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]} }
27
+ = line_chart chart_data, chart_options
28
+ - elsif chart_type == "line2"
29
+ = 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
30
+ - elsif chart_type == "pie"
31
+ = pie_chart rows.map { |r| [(boom[columns[0]] || {})[r[0].to_s] || r[0], r[1]] }, chart_options
32
+ - elsif chart_type == "bar"
33
+ = 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]] } } }, chart_options
34
+ - elsif chart_type == "bar2"
35
+ - first_20 = rows.group_by { |r| r[0] }.values.first(20).flatten(1)
36
+ - labels = first_20.map { |r| r[0] }.uniq
37
+ - series = first_20.map { |r| r[1] }.uniq
38
+ - labels.each do |l|
39
+ - series.each do |s|
40
+ - first_20 << [l, s, 0] unless first_20.find { |r| r[0] == l && r[1] == s }
41
+ = 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]] }} }, chart_options
42
+ - elsif chart_type == "scatter"
43
+ = scatter_chart rows, xtitle: columns[0], ytitle: columns[1], **chart_options
44
+ - elsif only_chart
45
+ - if rows.size == 1 && rows.first.size == 1
46
+ - v = rows.first.first
47
+ - if v.is_a?(String) && v == ""
48
+ .text-muted empty string
49
+ - else
50
+ %p{style: "font-size: 160px;"}= blazer_format_value(columns.first, v)
51
+ - else
52
+ - @no_chart = true
@@ -1,23 +1,30 @@
1
1
  - if @query.errors.any?
2
2
  .alert.alert-danger= @query.errors.full_messages.first
3
3
  #app{"v-cloak" => ""}
4
- = form_for @query, url: (@query.persisted? ? query_path(@query, variable_params) : queries_path(variable_params)), html: {autocomplete: "off"} do |f|
4
+ = form_for @query, url: (@query.persisted? ? query_path(@query, variable_params) : queries_path(variable_params)), html: {autocomplete: "off", class: 'sql-query'} do |f|
5
5
  .row
6
6
  #statement-box.col-xs-8
7
7
  .form-group
8
8
  = f.hidden_field :statement
9
9
  #editor-container
10
- #editor{":style" => "{ height: editorHeight }"}= @query.statement
11
- .form-group.text-right{:style => "margin-bottom: 8px;"}
12
- .pull-left{:style => "margin-top: 8px;"}
10
+ #editor{style: "{ height: editorHeight }"}= @query.statement.to_s.gsub("\n", '')
11
+ .form-group.text-right{style: "margin-bottom: 8px;"}
12
+ .pull-left{style: "margin-top: 8px;"}
13
13
  = link_to "Back", :back
14
- %a{":href" => "schemaPath", :style => "margin-left: 40px;", :target => "_blank"} Schema
14
+ = link_to 'Schema', 'schemaPath', style: 'margin-left: 40px;', target: :blank
15
+ - if Blazer.integration
16
+ = link_to 'Integration', '#integration-session', style: 'margin-left: 40px;', data: { toggle: :collapse }
15
17
  = f.select :data_source, Blazer.data_sources.values.select { |ds| q = @query.dup; q.data_source = ds.id; q.editable?(blazer_user) }.map { |ds| [ds.name, ds.id] }, {}, class: ("hide" if Blazer.data_sources.size <= 1), style: "width: 140px;"
16
- #tables{:style => "display: inline-block; width: 250px; margin-right: 10px;"}
17
- %select#table_names{:placeholder => "Preview table", :style => "width: 240px;"}
18
- %a.btn.btn-info{:style => "vertical-align: top; width: 70px;", "v-if" => "!running", "v-on:click" => "run"} Run
19
- %a.btn.btn-danger{:style => "vertical-align: top; width: 70px;", "v-if" => "running", "v-on:click" => "cancel"} Cancel
20
- %hr/
18
+ #tables{style: "display: inline-block; width: 250px; margin-right: 10px;"}
19
+ %select#table_names{placeholder: "Preview table", style: "width: 240px;"}
20
+ %a.btn.btn-info{style: "vertical-align: top; width: 70px;", "v-if" => "!running", "v-on:click" => "run"} Run
21
+ %a.btn.btn-danger{style: "vertical-align: top; width: 70px;", "v-if" => "running", "v-on:click" => "cancel"} Cancel
22
+ - if Blazer.integration
23
+ #integration-session.collapse
24
+ %hr
25
+ = f.hidden_field :integration
26
+ #integration-editor{style: 'height: 200px'}
27
+ %hr
21
28
  = render partial: "tips"
22
29
  .col-xs-4
23
30
  .form-group
@@ -30,6 +37,10 @@
30
37
  .form-group
31
38
  = f.label :assignees
32
39
  = f.collection_select :assignee_ids, @assignees, :first, :last, {}, { placeholder: "Assignees", style: "height: 80px;", class: "form-control", multiple: true }
40
+ - if @teams.any?
41
+ .form-group
42
+ = f.label :teams
43
+ = f.collection_select :team_ids, @teams, :first, :last, {}, { placeholder: "Teams", style: "height: 80px;", class: "form-control", multiple: true }
33
44
  .form-group.text-right
34
45
  = f.submit "For Enter Press", class: "hide"
35
46
  - if @query.persisted?
@@ -48,6 +59,7 @@
48
59
  #results
49
60
  %p.text-muted{"v-if" => "running"} Loading...
50
61
  #results-html{":class" => "{ 'query-error': error }", "v-if" => "!running"}
62
+
51
63
  :javascript
52
64
  #{blazer_js_var "params", variable_params}
53
65
  #{blazer_js_var "previewStatement", Hash[Blazer.data_sources.map { |k, v| [k, (v.preview_statement rescue "")] }]}
@@ -77,7 +89,11 @@
77
89
  this.error = false
78
90
  cancelAllQueries()
79
91
 
80
- var data = $.extend({}, params, {statement: this.getSQL(), data_source: $("#query_data_source").val()})
92
+ var data = $.extend({}, params, {
93
+ statement: this.getSQL(),
94
+ integration: $('#integration').val(),
95
+ data_source: $("#query_data_source").val()
96
+ })
81
97
 
82
98
  var _this = this
83
99
 
@@ -121,9 +137,27 @@
121
137
  selectize.refreshOptions(false)
122
138
  })
123
139
  },
140
+ showIntegrationEditor: function() {
141
+ if ($('#integration-editor').length) {
142
+ integrationEditor = ace.edit("integration-editor")
143
+ integrationEditor.setTheme("ace/theme/twilight")
144
+ integrationEditor.getSession().setMode("ace/mode/ruby")
145
+ integrationEditor.setOptions({
146
+ fontSize: 12,
147
+ minLines: 10,
148
+ enableSnippets: false,
149
+ highlightActiveLine: false,
150
+ enableLiveAutocompletion: true,
151
+ enableBasicAutocompletion: true
152
+ })
153
+ integrationEditor.renderer.setShowGutter(true)
154
+ integrationEditor.renderer.setPrintMarginColumn(false)
155
+ integrationEditor.renderer.setPadding(10)
156
+ integrationEditor.getSession().setUseWrapMode(true)
157
+ }
158
+ },
124
159
  showEditor: function() {
125
160
  var _this = this
126
-
127
161
  editor = ace.edit("editor")
128
162
  editor.setTheme("ace/theme/twilight")
129
163
  editor.getSession().setMode("ace/mode/sql")
@@ -223,7 +257,8 @@
223
257
  lines = 9
224
258
  }
225
259
 
226
- this.editorHeight = ((lines + 1) * 16).toString() + "px"
260
+ this.editorHeight = ((lines + 1) * 16).toString();
261
+ $('#editor').height(this.editorHeight);
227
262
 
228
263
  Vue.nextTick(function () {
229
264
  editor.resize()
@@ -277,7 +312,8 @@
277
312
  dsSelectize.blur()
278
313
  })
279
314
 
280
- this.showEditor()
315
+ this.showEditor();
316
+ // this.showIntegrationEditor();
281
317
  }
282
318
  })
283
319
 
@@ -292,7 +328,7 @@
292
328
  }
293
329
 
294
330
  $(document).ready(function() {
295
- $('#query_assignee_ids').select2();
331
+ $('#query_assignee_ids, #query_team_ids').select2();
296
332
  setInterval(function() {
297
333
  var lastVersion = $('#query_statement').val();
298
334
  if (localStorage.getItem('lastVersion') !== lastVersion) {
@@ -308,3 +344,11 @@
308
344
  return false;
309
345
  }
310
346
  });
347
+
348
+ (function () {
349
+ $('.sql-query').one('change', function () {
350
+ window.onbeforeunload = function () {
351
+ return 'Form protection';
352
+ };
353
+ });
354
+ })();
@@ -20,32 +20,12 @@
20
20
  - if @forecast_error
21
21
  .alert.alert-danger= @forecast_error
22
22
  - if @rows.any?
23
- - values = @rows.first
24
- - chart_id = SecureRandom.hex
25
- - column_types = @result.column_types
26
- - chart_type = @result.chart_type
27
- - chart_options = {id: chart_id}
28
- - if ["line", "line2"].include?(chart_type)
29
- - chart_options.merge!(min: nil)
30
- - if chart_type == "scatter"
31
- - chart_options.merge!(library: {tooltips: {intersect: false}})
32
- - elsif ["bar", "bar2"].include?(chart_type)
33
- - chart_options.merge!(library: {tooltips: {intersect: false, axis: 'x'}})
34
- - elsif chart_type != "pie"
35
- - if column_types.size == 2 || @forecast
36
- - chart_options.merge!(library: {tooltips: {intersect: false, axis: 'x'}})
37
- - else
38
- - chart_options.merge!(library: {tooltips: {intersect: false}})
39
- - series_library = {}
40
- - target_index = @columns.index { |k| k.downcase == "target" }
41
- - if target_index
42
- - series_library[target_index - 1] = {pointStyle: "line", hitRadius: 5, borderColor: "#109618", pointBackgroundColor: "#109618", backgroundColor: "#109618"}
43
- - if @forecast
44
- - color = "#54a3ee"
45
- - series_library[1] = {borderDash: [8], borderColor: color, pointBackgroundColor: color, backgroundColor: color, pointHoverBackgroundColor: color}
23
+ #main-chart
24
+ = render 'chart', rows: @rows, columns: @columns, result: @result, forecast: @forecast, only_chart: @only_chart, boom: @boom
46
25
  - if blazer_maps? && @markers.any?
47
- #map{style: "height: #{@only_chart ? 300 : 500}px;"}
26
+ #map{style: "height: 500px; width: 100%"}
48
27
  :javascript
28
+ $('#map').html('');
49
29
  L.mapbox.accessToken = '#{Blazer.mapbox_access_token}';
50
30
  var map = L.mapbox.map('map', 'ankane.ioo8nki0');
51
31
  #{blazer_js_var "markers", @markers}
@@ -71,34 +51,12 @@
71
51
  }
72
52
  featureLayer.setGeoJSON(geojson);
73
53
  map.fitBounds(featureLayer.getBounds());
74
- - elsif chart_type == "line"
75
- - chart_data = @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]} }
76
- = line_chart chart_data, chart_options
77
- - elsif chart_type == "line2"
78
- = 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
79
- - elsif chart_type == "pie"
80
- = pie_chart @rows.map { |r| [(@boom[@columns[0]] || {})[r[0].to_s] || r[0], r[1]] }, chart_options
81
- - elsif chart_type == "bar"
82
- = 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]] } } }, chart_options
83
- - elsif chart_type == "bar2"
84
- - first_20 = @rows.group_by { |r| r[0] }.values.first(20).flatten(1)
85
- - labels = first_20.map { |r| r[0] }.uniq
86
- - series = first_20.map { |r| r[1] }.uniq
87
- - labels.each do |l|
88
- - series.each do |s|
89
- - first_20 << [l, s, 0] unless first_20.find { |r| r[0] == l && r[1] == s }
90
- = 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]] }} }, chart_options
91
- - elsif chart_type == "scatter"
92
- = scatter_chart @rows, xtitle: @columns[0], ytitle: @columns[1], **chart_options
93
- - elsif @only_chart
94
- - if @rows.size == 1 && @rows.first.size == 1
95
- - v = @rows.first.first
96
- - if v.is_a?(String) && v == ""
97
- .text-muted empty string
98
- - else
99
- %p{style: "font-size: 160px;"}= blazer_format_value(@columns.first, v)
100
- - else
101
- - @no_chart = true
54
+ map.setZoom(5)._onResize();
55
+ - elsif @no_chart
56
+ :javascript
57
+ $('#chart-tab').hide();
58
+ $('#table-tab').click();
59
+
102
60
  - unless @only_chart && !@no_chart
103
61
  - header_width = 100 / @columns.size.to_f
104
62
  .results-container
@@ -110,7 +68,7 @@
110
68
  %code= @rows[0][0]
111
69
  - else
112
70
  %p.text-muted{style: "margin-bottom: 10px; margin-top: 15px"}
113
- = pluralize(@rows.size, "row")
71
+ = "#{@rows.size} rows" if @rows.size > 1
114
72
  - @checks.select(&:state).each do |check|
115
73
  ·
116
74
  %small{:class => "check-state #{check.state.parameterize.gsub("-", "_")}"}= link_to check.state.upcase, edit_check_path(check)
@@ -120,8 +78,14 @@
120
78
  ·
121
79
  \#{link_to "Forecast", query_path(@query, {forecast: "t"}.merge(variable_params))}
122
80
  %span.pull-right
123
- - if @rows.size > 0
81
+ - if (1..preview_rows_number).cover?(@rows.size)
124
82
  = link_to 'Copy to clipboard', '#results-table', class: 'click2CopyTable btn btn-xs btn-info'
83
+
84
+ - if @rows.size > preview_rows_number
85
+ %hr
86
+ %h4.text-center.text-info
87
+ %strong Notice: Now we show maximum is #{preview_rows_number} rows for preview
88
+ %hr
125
89
  .scroll-content
126
90
  %table#results-table.table.results-table
127
91
  %thead
@@ -133,7 +97,7 @@
133
97
  %div{style: "min-width: #{@min_width_types.include?(i) ? 180 : 60}px;"}
134
98
  = key
135
99
  %tbody
136
- - @rows.each do |row|
100
+ - @rows.first(preview_rows_number).each do |row|
137
101
  %tr
138
102
  - row.each_with_index do |v, i|
139
103
  - k = @columns[i]
@@ -151,3 +115,7 @@
151
115
  .text-muted= v2
152
116
  - else
153
117
  %p.text-muted.text-center{style: "margin-top: 15px"} No rows
118
+
119
+ :javascript
120
+ $('#main-chart').appendTo('#chart');
121
+ $('#map').appendTo('#chart');
@@ -1,17 +1,19 @@
1
1
  - blazer_title @query.name
2
+
2
3
  .topbar
3
4
  .container
4
5
  .row{:style => "padding-top: 13px;"}
5
6
  .col-sm-8
6
7
  = render partial: "blazer/nav"
7
- %h3{:style => "line-height: 34px; display: inline; margin-left: 5px;"}
8
+ %h4{style: "line-height: 34px; display: inline; margin-left: 5px;"}
8
9
  = @query.name
9
10
  .col-sm-4.text-right
10
11
  = link_to "Edit", edit_query_path(@query, variable_params), class: "btn btn-default", disabled: !@query.editable?(blazer_user)
11
12
  = 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"
12
13
  - if !@error && @success
13
- = button_to "⤓ .csv", run_queries_path(query_id: @query.id, format: "csv", forecast: params[:forecast]), params: {statement: @statement}, class: "btn btn-primary"
14
- = button_to "⤓ .xlsx", run_queries_path(query_id: @query.id, format: "xlsx"), params: {statement: @statement}, class: "btn btn-primary"
14
+ = button_to "⤓ .csv", run_queries_path(query_id: @query.id, format: "csv", forecast: params[:forecast]), params: { statement: @statement, filename: @filename }, class: "btn btn-primary"
15
+ = button_to "⤓ .xlsx", run_queries_path(query_id: @query.id, format: "xlsx"), params: { statement: @statement, filename: @filename }, class: "btn btn-primary"
16
+
15
17
  %div{:style => "margin-bottom: 60px;"}
16
18
  - if @sql_errors.any?
17
19
  .alert.alert-danger
@@ -20,31 +22,54 @@
20
22
  %li= message
21
23
  - if @query.description.present?
22
24
  %p= @query.description
25
+
23
26
  = render partial: "blazer/variables", locals: {action: query_path(@query)}
24
- %pre#code
25
- %code= @statement
26
- - if @success
27
- #results
28
- %p.text-muted Loading...
29
- :javascript
30
- function showRun(data) {
31
- $("#results").html(data);
32
- $("#results table").stupidtable().stickyTableHeaders({
33
- fixedOffset: 60,
34
- });
35
- }
36
-
37
- function showError(message) {
38
- $("#results").addClass("query-error").html(message);
39
- }
40
-
41
- #{blazer_js_var "data", variable_params.merge(statement: @statement, query_id: @query.id, data_source: @query.data_source)}
42
-
43
- runQuery(data, showRun, showError)
44
- - unless %w(mongodb).include?(Blazer.data_sources[@query.data_source].adapter)
45
- :javascript
46
- // do not highlight really long queries
47
- // this can lead to performance issues
48
- if ($("code").text().length < 10000) {
49
- hljs.highlightBlock(document.getElementById("code"));
50
- }
27
+
28
+ %ul.nav.nav-tabs
29
+ %li#chart-tab.active= link_to 'Chart', '#chart', data: { toggle: :tab }
30
+ %li= link_to 'Table', '#table', data: { toggle: :tab }, id: 'table-tab'
31
+ %li= link_to 'Query', '#query', data: { toggle: :tab }
32
+ - if @query.integration.present?
33
+ %li= link_to 'Integration', '#integration', data: { toggle: :tab }
34
+
35
+ .tab-content
36
+ #chart.tab-pane.fade.in.active
37
+ #query.tab-pane.fade
38
+ %pre#code
39
+ %code= @statement.gsub("\r", "\n")
40
+ - if @query.integration.present?
41
+ #integration.tab-pane.fade
42
+ = @query.integration
43
+ #table.tab-pane.fade
44
+ - if @success
45
+ #results
46
+ %p.text-muted Loading...
47
+ :javascript
48
+ function showRun(data) {
49
+ $("#results").html(data);
50
+ $("#results table").stupidtable().stickyTableHeaders({
51
+ fixedOffset: 60,
52
+ });
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, data_source: @query.data_source)}
60
+
61
+ runQuery(data, showRun, showError)
62
+ - unless %w(mongodb).include?(Blazer.data_sources[@query.data_source].adapter)
63
+ :javascript
64
+ // do not highlight really long queries
65
+ // this can lead to performance issues
66
+ if ($("code").text().length < 10000) {
67
+ hljs.highlightBlock(document.getElementById("code"));
68
+ }
69
+
70
+ :javascript
71
+ $('ul.nav.nav-tabs li a').click(function(event) {
72
+ localStorage.setItem('currentQueryTab', $(event.currentTarget).attr('href'));
73
+ });
74
+ var currentQueryTab = localStorage.getItem('currentQueryTab');
75
+ $("ul.nav.nav-tabs li a[href='" + currentQueryTab + "']").click();