sql-jarvis 2.1 → 2.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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();