sql-jarvis 2.1.1 → 2.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/blazer/Sortable.js +1489 -1489
- data/app/assets/javascripts/blazer/ace.js +2 -0
- data/app/assets/javascripts/blazer/ace/mode-ruby.js +498 -0
- data/app/assets/javascripts/blazer/ace/theme-ambiance.js +184 -0
- data/app/assets/javascripts/blazer/stupidtable.js +2 -0
- data/app/assets/stylesheets/blazer/application.css +2 -2
- data/app/controllers/blazer/base_controller.rb +11 -2
- data/app/controllers/blazer/queries_controller.rb +157 -146
- data/app/models/blazer/query.rb +9 -0
- data/app/views/blazer/_variables.html.haml +3 -4
- data/app/views/blazer/queries/_chart.html.haml +52 -0
- data/app/views/blazer/queries/_form.html.haml +45 -12
- data/app/views/blazer/queries/run.html.haml +15 -53
- data/app/views/blazer/queries/show.html.haml +48 -25
- data/app/views/layouts/blazer/application.html.haml +1 -1
- data/lib/blazer.rb +9 -0
- data/lib/blazer/adapters/sql_adapter.rb +3 -3
- data/lib/blazer/data_source.rb +4 -0
- data/lib/blazer/excel_parser.rb +1 -1
- data/lib/blazer/run_integration.rb +24 -0
- data/lib/blazer/version.rb +1 -1
- data/lib/generators/blazer/templates/config.yml.tt +1 -0
- data/lib/generators/blazer/templates/install.rb.tt +2 -0
- metadata +7 -4
data/app/models/blazer/query.rb
CHANGED
@@ -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(
|
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
|
@@ -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: '80vh' }
|
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
|
@@ -7,17 +7,24 @@
|
|
7
7
|
.form-group
|
8
8
|
= f.hidden_field :statement
|
9
9
|
#editor-container
|
10
|
-
#editor{
|
11
|
-
.form-group.text-right{:
|
12
|
-
.pull-left{:
|
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
|
-
|
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{:
|
17
|
-
%select#table_names{:
|
18
|
-
%a.btn.btn-info{:
|
19
|
-
%a.btn.btn-danger{:
|
20
|
-
|
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, {
|
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,25 @@
|
|
121
137
|
selectize.refreshOptions(false)
|
122
138
|
})
|
123
139
|
},
|
140
|
+
showIntegrationEditor: function() {
|
141
|
+
integrationEditor = ace.edit("integration-editor")
|
142
|
+
integrationEditor.setTheme("ace/theme/twilight")
|
143
|
+
integrationEditor.getSession().setMode("ace/mode/ruby")
|
144
|
+
integrationEditor.setOptions({
|
145
|
+
fontSize: 12,
|
146
|
+
minLines: 10,
|
147
|
+
enableSnippets: false,
|
148
|
+
highlightActiveLine: false,
|
149
|
+
enableLiveAutocompletion: true,
|
150
|
+
enableBasicAutocompletion: true
|
151
|
+
})
|
152
|
+
integrationEditor.renderer.setShowGutter(true)
|
153
|
+
integrationEditor.renderer.setPrintMarginColumn(false)
|
154
|
+
integrationEditor.renderer.setPadding(10)
|
155
|
+
integrationEditor.getSession().setUseWrapMode(true)
|
156
|
+
},
|
124
157
|
showEditor: function() {
|
125
158
|
var _this = this
|
126
|
-
|
127
159
|
editor = ace.edit("editor")
|
128
160
|
editor.setTheme("ace/theme/twilight")
|
129
161
|
editor.getSession().setMode("ace/mode/sql")
|
@@ -278,6 +310,7 @@
|
|
278
310
|
})
|
279
311
|
|
280
312
|
this.showEditor()
|
313
|
+
this.showIntegrationEditor()
|
281
314
|
}
|
282
315
|
})
|
283
316
|
|
@@ -292,7 +325,7 @@
|
|
292
325
|
}
|
293
326
|
|
294
327
|
$(document).ready(function() {
|
295
|
-
$('#query_assignee_ids').select2();
|
328
|
+
$('#query_assignee_ids, #query_team_ids').select2();
|
296
329
|
setInterval(function() {
|
297
330
|
var lastVersion = $('#query_statement').val();
|
298
331
|
if (localStorage.getItem('lastVersion') !== lastVersion) {
|
@@ -20,32 +20,12 @@
|
|
20
20
|
- if @forecast_error
|
21
21
|
.alert.alert-danger= @forecast_error
|
22
22
|
- if @rows.any?
|
23
|
-
-
|
24
|
-
|
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:
|
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
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
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
|
-
=
|
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)
|
@@ -157,3 +115,7 @@
|
|
157
115
|
.text-muted= v2
|
158
116
|
- else
|
159
117
|
%p.text-muted.text-center{style: "margin-top: 15px"} No rows
|
118
|
+
|
119
|
+
:javascript
|
120
|
+
$('#main-chart').appendTo('#chart');
|
121
|
+
$('#map').appendTo('#chart');
|
@@ -4,7 +4,7 @@
|
|
4
4
|
.row{:style => "padding-top: 13px;"}
|
5
5
|
.col-sm-8
|
6
6
|
= render partial: "blazer/nav"
|
7
|
-
%
|
7
|
+
%h4{style: "line-height: 34px; display: inline; margin-left: 5px;"}
|
8
8
|
= @query.name
|
9
9
|
.col-sm-4.text-right
|
10
10
|
= link_to "Edit", edit_query_path(@query, variable_params), class: "btn btn-default", disabled: !@query.editable?(blazer_user)
|
@@ -20,31 +20,54 @@
|
|
20
20
|
%li= message
|
21
21
|
- if @query.description.present?
|
22
22
|
%p= @query.description
|
23
|
+
|
23
24
|
= 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
25
|
|
37
|
-
|
38
|
-
|
39
|
-
|
26
|
+
%ul.nav.nav-tabs
|
27
|
+
%li#chart-tab.active= link_to 'Chart', '#chart', data: { toggle: :tab }
|
28
|
+
%li= link_to 'Table', '#table', data: { toggle: :tab }, id: 'table-tab'
|
29
|
+
%li= link_to 'Query', '#query', data: { toggle: :tab }
|
30
|
+
- if @query.integration.present?
|
31
|
+
%li= link_to 'Integration', '#integration', data: { toggle: :tab }
|
32
|
+
|
33
|
+
.tab-content
|
34
|
+
#chart.tab-pane.fade.in.active
|
35
|
+
#query.tab-pane.fade
|
36
|
+
%pre#code
|
37
|
+
%code= @statement.gsub("\r", "\n")
|
38
|
+
- if @query.integration.present?
|
39
|
+
#integration.tab-pane.fade
|
40
|
+
= @query.integration
|
41
|
+
#table.tab-pane.fade
|
42
|
+
- if @success
|
43
|
+
#results
|
44
|
+
%p.text-muted Loading...
|
45
|
+
:javascript
|
46
|
+
function showRun(data) {
|
47
|
+
$("#results").html(data);
|
48
|
+
$("#results table").stupidtable().stickyTableHeaders({
|
49
|
+
fixedOffset: 60,
|
50
|
+
});
|
51
|
+
}
|
52
|
+
|
53
|
+
function showError(message) {
|
54
|
+
$("#results").addClass("query-error").html(message);
|
55
|
+
}
|
56
|
+
|
57
|
+
#{blazer_js_var "data", variable_params.merge(statement: @statement, query_id: @query.id, data_source: @query.data_source)}
|
40
58
|
|
41
|
-
|
59
|
+
runQuery(data, showRun, showError)
|
60
|
+
- unless %w(mongodb).include?(Blazer.data_sources[@query.data_source].adapter)
|
61
|
+
:javascript
|
62
|
+
// do not highlight really long queries
|
63
|
+
// this can lead to performance issues
|
64
|
+
if ($("code").text().length < 10000) {
|
65
|
+
hljs.highlightBlock(document.getElementById("code"));
|
66
|
+
}
|
42
67
|
|
43
|
-
|
44
|
-
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
hljs.highlightBlock(document.getElementById("code"));
|
50
|
-
}
|
68
|
+
:javascript
|
69
|
+
$('ul.nav.nav-tabs li a').click(function(event) {
|
70
|
+
localStorage.setItem('currentQueryTab', $(event.currentTarget).attr('href'));
|
71
|
+
});
|
72
|
+
var currentQueryTab = localStorage.getItem('currentQueryTab');
|
73
|
+
$("ul.nav.nav-tabs li a[href='" + currentQueryTab + "']").click();
|
data/lib/blazer.rb
CHANGED
@@ -12,6 +12,7 @@ require "blazer/data_source"
|
|
12
12
|
require "blazer/result"
|
13
13
|
require "blazer/excel_parser"
|
14
14
|
require "blazer/run_statement"
|
15
|
+
require "blazer/run_integration"
|
15
16
|
|
16
17
|
# adapters
|
17
18
|
require "blazer/adapters/base_adapter"
|
@@ -49,9 +50,11 @@ module Blazer
|
|
49
50
|
attr_accessor :check_schedules
|
50
51
|
attr_accessor :mapbox_access_token
|
51
52
|
attr_accessor :assignees
|
53
|
+
attr_accessor :teams
|
52
54
|
attr_accessor :anomaly_checks
|
53
55
|
attr_accessor :forecasting
|
54
56
|
attr_accessor :async
|
57
|
+
attr_accessor :integration
|
55
58
|
attr_accessor :images
|
56
59
|
attr_accessor :query_viewable
|
57
60
|
attr_accessor :query_editable
|
@@ -65,6 +68,7 @@ module Blazer
|
|
65
68
|
self.check_schedules = ["5 minutes", "1 hour", "1 day"]
|
66
69
|
self.mapbox_access_token = nil
|
67
70
|
self.assignees = []
|
71
|
+
self.teams = []
|
68
72
|
self.host = nil
|
69
73
|
self.preview_rows_number = 365
|
70
74
|
self.anomaly_checks = false
|
@@ -89,6 +93,11 @@ module Blazer
|
|
89
93
|
@time_zone = time_zone.is_a?(ActiveSupport::TimeZone) ? time_zone : ActiveSupport::TimeZone[time_zone.to_s]
|
90
94
|
end
|
91
95
|
|
96
|
+
def self.integration
|
97
|
+
return @integration if defined?(@integration)
|
98
|
+
@integration = settings.key?("integration") ? settings["integration"] : false
|
99
|
+
end
|
100
|
+
|
92
101
|
def self.user_class
|
93
102
|
if !defined?(@user_class)
|
94
103
|
@user_class = settings.key?("user_class") ? settings["user_class"] : (User.name rescue nil)
|
@@ -52,11 +52,11 @@ module Blazer
|
|
52
52
|
|
53
53
|
def preview_statement
|
54
54
|
if postgresql?
|
55
|
-
"SELECT * FROM \"{table}\" LIMIT
|
55
|
+
"SELECT * FROM \"{table}\" LIMIT 30"
|
56
56
|
elsif sqlserver?
|
57
|
-
"SELECT TOP (
|
57
|
+
"SELECT TOP (30) * FROM {table}"
|
58
58
|
else
|
59
|
-
"SELECT *\nFROM {table}\nORDER BY id DESC\nLIMIT
|
59
|
+
"SELECT *\nFROM {table}\nORDER BY id DESC\nLIMIT 30"
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|