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
@@ -0,0 +1,184 @@
|
|
1
|
+
define("ace/theme/ambiance",["require","exports","module","ace/lib/dom"], function(require, exports, module) {
|
2
|
+
|
3
|
+
exports.isDark = true;
|
4
|
+
exports.cssClass = "ace-ambiance";
|
5
|
+
exports.cssText = ".ace-ambiance .ace_gutter {\
|
6
|
+
background-color: #3d3d3d;\
|
7
|
+
background-image: linear-gradient(left, #3D3D3D, #333);\
|
8
|
+
background-repeat: repeat-x;\
|
9
|
+
border-right: 1px solid #4d4d4d;\
|
10
|
+
text-shadow: 0px 1px 1px #4d4d4d;\
|
11
|
+
color: #222;\
|
12
|
+
}\
|
13
|
+
.ace-ambiance .ace_gutter-layer {\
|
14
|
+
background: repeat left top;\
|
15
|
+
}\
|
16
|
+
.ace-ambiance .ace_gutter-active-line {\
|
17
|
+
background-color: #3F3F3F;\
|
18
|
+
}\
|
19
|
+
.ace-ambiance .ace_fold-widget {\
|
20
|
+
text-align: center;\
|
21
|
+
}\
|
22
|
+
.ace-ambiance .ace_fold-widget:hover {\
|
23
|
+
color: #777;\
|
24
|
+
}\
|
25
|
+
.ace-ambiance .ace_fold-widget.ace_start,\
|
26
|
+
.ace-ambiance .ace_fold-widget.ace_end,\
|
27
|
+
.ace-ambiance .ace_fold-widget.ace_closed{\
|
28
|
+
background: none;\
|
29
|
+
border: none;\
|
30
|
+
box-shadow: none;\
|
31
|
+
}\
|
32
|
+
.ace-ambiance .ace_fold-widget.ace_start:after {\
|
33
|
+
content: '▾'\
|
34
|
+
}\
|
35
|
+
.ace-ambiance .ace_fold-widget.ace_end:after {\
|
36
|
+
content: '▴'\
|
37
|
+
}\
|
38
|
+
.ace-ambiance .ace_fold-widget.ace_closed:after {\
|
39
|
+
content: '‣'\
|
40
|
+
}\
|
41
|
+
.ace-ambiance .ace_print-margin {\
|
42
|
+
border-left: 1px dotted #2D2D2D;\
|
43
|
+
right: 0;\
|
44
|
+
background: #262626;\
|
45
|
+
}\
|
46
|
+
.ace-ambiance .ace_scroller {\
|
47
|
+
-webkit-box-shadow: inset 0 0 10px black;\
|
48
|
+
-moz-box-shadow: inset 0 0 10px black;\
|
49
|
+
-o-box-shadow: inset 0 0 10px black;\
|
50
|
+
box-shadow: inset 0 0 10px black;\
|
51
|
+
}\
|
52
|
+
.ace-ambiance {\
|
53
|
+
color: #E6E1DC;\
|
54
|
+
background-color: #202020;\
|
55
|
+
}\
|
56
|
+
.ace-ambiance .ace_cursor {\
|
57
|
+
border-left: 1px solid #7991E8;\
|
58
|
+
}\
|
59
|
+
.ace-ambiance .ace_overwrite-cursors .ace_cursor {\
|
60
|
+
border: 1px solid #FFE300;\
|
61
|
+
background: #766B13;\
|
62
|
+
}\
|
63
|
+
.ace-ambiance.normal-mode .ace_cursor-layer {\
|
64
|
+
z-index: 0;\
|
65
|
+
}\
|
66
|
+
.ace-ambiance .ace_marker-layer .ace_selection {\
|
67
|
+
background: rgba(221, 240, 255, 0.20);\
|
68
|
+
}\
|
69
|
+
.ace-ambiance .ace_marker-layer .ace_selected-word {\
|
70
|
+
border-radius: 4px;\
|
71
|
+
border: 8px solid #3f475d;\
|
72
|
+
box-shadow: 0 0 4px black;\
|
73
|
+
}\
|
74
|
+
.ace-ambiance .ace_marker-layer .ace_step {\
|
75
|
+
background: rgb(198, 219, 174);\
|
76
|
+
}\
|
77
|
+
.ace-ambiance .ace_marker-layer .ace_bracket {\
|
78
|
+
margin: -1px 0 0 -1px;\
|
79
|
+
border: 1px solid rgba(255, 255, 255, 0.25);\
|
80
|
+
}\
|
81
|
+
.ace-ambiance .ace_marker-layer .ace_active-line {\
|
82
|
+
background: rgba(255, 255, 255, 0.031);\
|
83
|
+
}\
|
84
|
+
.ace-ambiance .ace_invisible {\
|
85
|
+
color: #333;\
|
86
|
+
}\
|
87
|
+
.ace-ambiance .ace_paren {\
|
88
|
+
color: #24C2C7;\
|
89
|
+
}\
|
90
|
+
.ace-ambiance .ace_keyword {\
|
91
|
+
color: #cda869;\
|
92
|
+
}\
|
93
|
+
.ace-ambiance .ace_keyword.ace_operator {\
|
94
|
+
color: #fa8d6a;\
|
95
|
+
}\
|
96
|
+
.ace-ambiance .ace_punctuation.ace_operator {\
|
97
|
+
color: #fa8d6a;\
|
98
|
+
}\
|
99
|
+
.ace-ambiance .ace_identifier {\
|
100
|
+
}\
|
101
|
+
.ace-ambiance .ace-statement {\
|
102
|
+
color: #cda869;\
|
103
|
+
}\
|
104
|
+
.ace-ambiance .ace_constant {\
|
105
|
+
color: #CF7EA9;\
|
106
|
+
}\
|
107
|
+
.ace-ambiance .ace_constant.ace_language {\
|
108
|
+
color: #CF7EA9;\
|
109
|
+
}\
|
110
|
+
.ace-ambiance .ace_constant.ace_library {\
|
111
|
+
}\
|
112
|
+
.ace-ambiance .ace_constant.ace_numeric {\
|
113
|
+
color: #78CF8A;\
|
114
|
+
}\
|
115
|
+
.ace-ambiance .ace_invalid {\
|
116
|
+
text-decoration: underline;\
|
117
|
+
}\
|
118
|
+
.ace-ambiance .ace_invalid.ace_illegal {\
|
119
|
+
color:#F8F8F8;\
|
120
|
+
background-color: rgba(86, 45, 86, 0.75);\
|
121
|
+
}\
|
122
|
+
.ace-ambiance .ace_invalid,\
|
123
|
+
.ace-ambiance .ace_deprecated {\
|
124
|
+
text-decoration: underline;\
|
125
|
+
font-style: italic;\
|
126
|
+
color: #D2A8A1;\
|
127
|
+
}\
|
128
|
+
.ace-ambiance .ace_support {\
|
129
|
+
color: #9B859D;\
|
130
|
+
}\
|
131
|
+
.ace-ambiance .ace_support.ace_function {\
|
132
|
+
color: #DAD085;\
|
133
|
+
}\
|
134
|
+
.ace-ambiance .ace_function.ace_buildin {\
|
135
|
+
color: #9b859d;\
|
136
|
+
}\
|
137
|
+
.ace-ambiance .ace_string {\
|
138
|
+
color: #8f9d6a;\
|
139
|
+
}\
|
140
|
+
.ace-ambiance .ace_string.ace_regexp {\
|
141
|
+
color: #DAD085;\
|
142
|
+
}\
|
143
|
+
.ace-ambiance .ace_comment {\
|
144
|
+
font-style: italic;\
|
145
|
+
color: #555;\
|
146
|
+
}\
|
147
|
+
.ace-ambiance .ace_comment.ace_doc {\
|
148
|
+
}\
|
149
|
+
.ace-ambiance .ace_comment.ace_doc.ace_tag {\
|
150
|
+
color: #666;\
|
151
|
+
font-style: normal;\
|
152
|
+
}\
|
153
|
+
.ace-ambiance .ace_definition,\
|
154
|
+
.ace-ambiance .ace_type {\
|
155
|
+
color: #aac6e3;\
|
156
|
+
}\
|
157
|
+
.ace-ambiance .ace_variable {\
|
158
|
+
color: #9999cc;\
|
159
|
+
}\
|
160
|
+
.ace-ambiance .ace_variable.ace_language {\
|
161
|
+
color: #9b859d;\
|
162
|
+
}\
|
163
|
+
.ace-ambiance .ace_xml-pe {\
|
164
|
+
color: #494949;\
|
165
|
+
}\
|
166
|
+
.ace-ambiance .ace_gutter-layer,\
|
167
|
+
.ace-ambiance .ace_text-layer {\
|
168
|
+
background-image: url(\"data:image/png;base64,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\");\
|
169
|
+
}\
|
170
|
+
.ace-ambiance .ace_indent-guide {\
|
171
|
+
background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNQUFD4z6Crq/sfAAuYAuYl+7lfAAAAAElFTkSuQmCC\") right repeat-y;\
|
172
|
+
}";
|
173
|
+
|
174
|
+
var dom = require("../lib/dom");
|
175
|
+
dom.importCssString(exports.cssText, exports.cssClass);
|
176
|
+
|
177
|
+
}); (function() {
|
178
|
+
window.require(["ace/theme/ambiance"], function(m) {
|
179
|
+
if (typeof module == "object" && typeof exports == "object" && module) {
|
180
|
+
module.exports = m;
|
181
|
+
}
|
182
|
+
});
|
183
|
+
})();
|
184
|
+
|
@@ -61,7 +61,7 @@ input.search:focus {
|
|
61
61
|
margin-right: 0;
|
62
62
|
}
|
63
63
|
|
64
|
-
#editor-container {
|
64
|
+
#editor-container, #integration-editor {
|
65
65
|
background-color: #141414;
|
66
66
|
padding-top: 10px;
|
67
67
|
padding-bottom: 10px;
|
@@ -175,7 +175,7 @@ input.search:focus {
|
|
175
175
|
}
|
176
176
|
|
177
177
|
#code {
|
178
|
-
max-height:
|
178
|
+
max-height: 80vh;
|
179
179
|
overflow: hidden;
|
180
180
|
}
|
181
181
|
|
@@ -65,7 +65,11 @@ module Blazer
|
|
65
65
|
end
|
66
66
|
value = Blazer.transform_variable.call(var, value) if Blazer.transform_variable
|
67
67
|
if value.is_a?(Array)
|
68
|
-
|
68
|
+
if value.include?('select-all')
|
69
|
+
var_value = Blazer.data_sources[data_source].select_all_variables[var]
|
70
|
+
else
|
71
|
+
var_value = value.map{|v| ActiveRecord::Base.connection.quote(v)}.join(', ')
|
72
|
+
end
|
69
73
|
else
|
70
74
|
var_value = ActiveRecord::Base.connection.quote(value)
|
71
75
|
end
|
@@ -76,7 +80,9 @@ module Blazer
|
|
76
80
|
|
77
81
|
def parse_smart_variables(var, data_source)
|
78
82
|
smart_var_data_source =
|
79
|
-
([data_source] + Array(data_source.settings["inherit_smart_settings"])
|
83
|
+
([data_source] + Array(data_source.settings["inherit_smart_settings"])
|
84
|
+
.map { |ds| Blazer.data_sources[ds] })
|
85
|
+
.find { |ds| ds.smart_variables[var] }
|
80
86
|
|
81
87
|
if smart_var_data_source
|
82
88
|
query = smart_var_data_source.smart_variables[var]
|
@@ -88,6 +94,9 @@ module Blazer
|
|
88
94
|
elsif query
|
89
95
|
result = smart_var_data_source.run_statement(query)
|
90
96
|
smart_var = result.rows.map { |v| v.reverse }
|
97
|
+
if data_source.select_all_variables.keys.include?(var)
|
98
|
+
smart_var = [['All', 'select-all']] + smart_var
|
99
|
+
end
|
91
100
|
error = result.error if result.error
|
92
101
|
end
|
93
102
|
end
|
@@ -2,7 +2,7 @@ module Blazer
|
|
2
2
|
class QueriesController < BaseController
|
3
3
|
before_action :set_query, only: [:show, :edit, :update, :destroy, :refresh]
|
4
4
|
before_action :set_data_source, only: [:new, :edit, :tables, :docs, :schema, :cancel, :columns]
|
5
|
-
before_action :
|
5
|
+
before_action :set_accessible, only: [:new, :create, :show, :edit, :update, :destroy, :refresh]
|
6
6
|
|
7
7
|
def home
|
8
8
|
set_queries(1000)
|
@@ -85,6 +85,7 @@ module Blazer
|
|
85
85
|
|
86
86
|
def run
|
87
87
|
@statement = params[:statement]
|
88
|
+
@integration = params[:integration]
|
88
89
|
data_source = params[:data_source]
|
89
90
|
process_vars(@statement, data_source)
|
90
91
|
@only_chart = params[:only_chart]
|
@@ -139,9 +140,9 @@ module Blazer
|
|
139
140
|
|
140
141
|
if @result
|
141
142
|
@data_source.delete_results(@run_id) if @run_id
|
142
|
-
|
143
|
-
@columns = @result.columns
|
144
|
-
@rows = @result.rows
|
143
|
+
@integration_output = Blazer::RunIntegration.new(@result, @integration).call
|
144
|
+
@columns = @integration_output&.dig(:columns) || @result.columns
|
145
|
+
@rows = @integration_output&.dig(:rows) || @result.rows
|
145
146
|
@error = @result.error
|
146
147
|
@cached_at = @result.cached_at
|
147
148
|
@just_cached = @result.just_cached
|
@@ -223,179 +224,189 @@ module Blazer
|
|
223
224
|
|
224
225
|
private
|
225
226
|
|
226
|
-
|
227
|
-
|
227
|
+
def set_data_source
|
228
|
+
@data_source = Blazer.data_sources[params[:data_source]]
|
229
|
+
render_forbidden unless Query.new(data_source: @data_source.id).editable?(blazer_user)
|
230
|
+
end
|
231
|
+
|
232
|
+
def continue_run
|
233
|
+
render json: {run_id: @run_id, timestamp: @timestamp}, status: :accepted
|
234
|
+
end
|
228
235
|
|
229
|
-
|
230
|
-
|
236
|
+
def render_run
|
237
|
+
@checks = @query ? @query.checks.order(:id) : []
|
238
|
+
|
239
|
+
@first_row = @rows.first || []
|
240
|
+
@column_types = []
|
241
|
+
if @rows.any?
|
242
|
+
@columns.each_with_index do |_, i|
|
243
|
+
@column_types << (
|
244
|
+
case @first_row[i]
|
245
|
+
when Integer
|
246
|
+
"int"
|
247
|
+
when Float, BigDecimal
|
248
|
+
"float"
|
249
|
+
else
|
250
|
+
"string-ins"
|
251
|
+
end
|
252
|
+
)
|
231
253
|
end
|
232
254
|
end
|
233
255
|
|
234
|
-
|
235
|
-
|
236
|
-
end
|
256
|
+
@filename = @query.name.parameterize if @query
|
257
|
+
@min_width_types = @columns.each_with_index.select { |c, i| @first_row[i].is_a?(Time) || @first_row[i].is_a?(String) || @data_source.smart_columns[c] }.map(&:last)
|
237
258
|
|
238
|
-
|
239
|
-
@checks = @query ? @query.checks.order(:id) : []
|
240
|
-
|
241
|
-
@first_row = @rows.first || []
|
242
|
-
@column_types = []
|
243
|
-
if @rows.any?
|
244
|
-
@columns.each_with_index do |_, i|
|
245
|
-
@column_types << (
|
246
|
-
case @first_row[i]
|
247
|
-
when Integer
|
248
|
-
"int"
|
249
|
-
when Float, BigDecimal
|
250
|
-
"float"
|
251
|
-
else
|
252
|
-
"string-ins"
|
253
|
-
end
|
254
|
-
)
|
255
|
-
end
|
256
|
-
end
|
259
|
+
@boom = @result.boom if @result
|
257
260
|
|
258
|
-
|
259
|
-
@min_width_types = @columns.each_with_index.select { |c, i| @first_row[i].is_a?(Time) || @first_row[i].is_a?(String) || @data_source.smart_columns[c] }.map(&:last)
|
260
|
-
|
261
|
-
@boom = @result.boom if @result
|
262
|
-
|
263
|
-
@linked_columns = @data_source.linked_columns
|
264
|
-
|
265
|
-
@markers = []
|
266
|
-
[["latitude", "longitude"], ["lat", "lon"], ["lat", "lng"]].each do |keys|
|
267
|
-
lat_index = @columns.index(keys.first)
|
268
|
-
lon_index = @columns.index(keys.last)
|
269
|
-
if lat_index && lon_index
|
270
|
-
@markers =
|
271
|
-
@rows.select do |r|
|
272
|
-
r[lat_index] && r[lon_index]
|
273
|
-
end.map do |r|
|
274
|
-
{
|
275
|
-
title: r.each_with_index.map{ |v, i| i == lat_index || i == lon_index ? nil : "<strong>#{@columns[i]}:</strong> #{v}" }.compact.join("<br />").truncate(140),
|
276
|
-
latitude: r[lat_index],
|
277
|
-
longitude: r[lon_index]
|
278
|
-
}
|
279
|
-
end
|
280
|
-
end
|
281
|
-
end
|
261
|
+
@linked_columns = @data_source.linked_columns
|
282
262
|
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
263
|
+
@markers = []
|
264
|
+
[["latitude", "longitude"], ["lat", "lon"], ["lat", "lng"]].each do |keys|
|
265
|
+
lat_index = @columns.index(keys.first)
|
266
|
+
lon_index = @columns.index(keys.last)
|
267
|
+
if lat_index && lon_index
|
268
|
+
@markers =
|
269
|
+
@rows.select do |r|
|
270
|
+
r[lat_index] && r[lon_index]
|
271
|
+
end.map do |r|
|
272
|
+
{
|
273
|
+
title: r.each_with_index.map{ |v, i| i == lat_index || i == lon_index ? nil : "<strong>#{@columns[i]}:</strong> #{v}" }.compact.join("<br />").truncate(140),
|
274
|
+
latitude: r[lat_index],
|
275
|
+
longitude: r[lon_index]
|
276
|
+
}
|
277
|
+
end
|
296
278
|
end
|
297
279
|
end
|
298
280
|
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
if blazer_user && params[:filter] == "mine"
|
304
|
-
@queries = @queries.where(creator_id: blazer_user.id).reorder(updated_at: :desc)
|
305
|
-
elsif blazer_user && params[:filter] == "viewed" && Blazer.audit
|
306
|
-
@queries = queries_by_ids(Blazer::Audit.where(user_id: blazer_user.id).order(created_at: :desc).limit(500).pluck(:query_id).uniq)
|
307
|
-
else
|
308
|
-
@queries = @queries.limit(limit) if limit
|
309
|
-
@queries = @queries.order(:name)
|
281
|
+
filename = @query.try(:name).try(:parameterize).presence || 'query'
|
282
|
+
respond_to do |format|
|
283
|
+
format.html do
|
284
|
+
render layout: false
|
310
285
|
end
|
311
|
-
|
312
|
-
|
313
|
-
|
286
|
+
format.xlsx do
|
287
|
+
parser = ::Blazer::ExcelParser.new(@query, @columns, @rows)
|
288
|
+
tmp_file = parser.export
|
289
|
+
send_file tmp_file, type: "application/xlsx; charset=utf-8; header=present", disposition: "attachment; filename=\"#{parser.filename}\""
|
290
|
+
end
|
291
|
+
format.csv do
|
292
|
+
send_data csv_data(@columns, @rows, @data_source), type: "text/csv; charset=utf-8; header=present", disposition: "attachment; filename=\"#{filename}.csv\""
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
314
296
|
|
315
|
-
|
297
|
+
def set_queries(limit = nil)
|
298
|
+
@queries = Blazer::Query.named.select(:id, :name, :creator_id, :statement)
|
299
|
+
@queries = @queries.includes(:creator) if Blazer.user_class
|
316
300
|
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
to_param: q.to_param
|
325
|
-
}
|
326
|
-
end
|
301
|
+
if blazer_user && params[:filter] == "mine"
|
302
|
+
@queries = @queries.where(creator_id: blazer_user.id).reorder(updated_at: :desc)
|
303
|
+
elsif blazer_user && params[:filter] == "viewed" && Blazer.audit
|
304
|
+
@queries = queries_by_ids(Blazer::Audit.where(user_id: blazer_user.id).order(created_at: :desc).limit(500).pluck(:query_id).uniq)
|
305
|
+
else
|
306
|
+
@queries = @queries.limit(limit) if limit
|
307
|
+
@queries = @queries.order(:name)
|
327
308
|
end
|
309
|
+
@queries = @queries.to_a
|
328
310
|
|
329
|
-
|
330
|
-
queries = Blazer::Query.named.where(id: favorite_query_ids)
|
331
|
-
queries = queries.includes(:creator) if Blazer.user_class
|
332
|
-
queries = queries.index_by(&:id)
|
333
|
-
favorite_query_ids.map { |query_id| queries[query_id] }.compact
|
334
|
-
end
|
311
|
+
@more = limit && @queries.size >= limit
|
335
312
|
|
336
|
-
|
337
|
-
@query = Blazer::Query.find(params[:id].to_s.split("-").first)
|
313
|
+
@queries = @queries.select { |q| !q.name.to_s.start_with?("#") || q.try(:creator).try(:id) == blazer_user.try(:id) }
|
338
314
|
|
339
|
-
|
340
|
-
|
315
|
+
@queries =
|
316
|
+
@queries.map do |q|
|
317
|
+
{
|
318
|
+
id: q.id,
|
319
|
+
name: q.name,
|
320
|
+
creator: blazer_user && q.try(:creator) == blazer_user ? "You" : q.try(:creator).try(Blazer.user_name),
|
321
|
+
vars: q.variables.join(", "),
|
322
|
+
to_param: q.to_param
|
323
|
+
}
|
341
324
|
end
|
342
|
-
|
325
|
+
end
|
343
326
|
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
end
|
351
|
-
else
|
352
|
-
@assignees = []
|
353
|
-
end
|
354
|
-
end
|
327
|
+
def queries_by_ids(favorite_query_ids)
|
328
|
+
queries = Blazer::Query.named.where(id: favorite_query_ids)
|
329
|
+
queries = queries.includes(:creator) if Blazer.user_class
|
330
|
+
queries = queries.index_by(&:id)
|
331
|
+
favorite_query_ids.map { |query_id| queries[query_id] }.compact
|
332
|
+
end
|
355
333
|
|
356
|
-
|
357
|
-
|
358
|
-
end
|
334
|
+
def set_query
|
335
|
+
@query = Blazer::Query.find(params[:id].to_s.split("-").first)
|
359
336
|
|
360
|
-
|
361
|
-
|
337
|
+
unless @query.viewable?(blazer_user)
|
338
|
+
render_forbidden
|
362
339
|
end
|
340
|
+
end
|
363
341
|
|
364
|
-
|
365
|
-
|
342
|
+
def set_accessible
|
343
|
+
@teams = Rails.cache.fetch('jarvis_teams') { get_teams } if Blazer.settings.key?('teams')
|
344
|
+
@assignees = Rails.cache.fetch('jarvis_assignees') { get_assignees } if Blazer.settings.key?('assignees')
|
345
|
+
ensure
|
346
|
+
@teams ||= []
|
347
|
+
@assignees ||= []
|
348
|
+
end
|
349
|
+
|
350
|
+
def get_assignees
|
351
|
+
Blazer::RunStatement.new.perform(@data_source, Blazer.settings['assignees'], {}).rows.map do |row|
|
352
|
+
[row.first, row.last.to_s.titleize]
|
366
353
|
end
|
354
|
+
rescue
|
355
|
+
[]
|
356
|
+
end
|
367
357
|
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
rows.each do |row|
|
372
|
-
csv << row.each_with_index.map { |v, i| v.is_a?(Time) ? blazer_time_value(data_source, columns[i], v) : v }
|
373
|
-
end
|
374
|
-
end
|
358
|
+
def get_teams
|
359
|
+
Blazer::RunStatement.new.perform(@data_source, Blazer.settings['teams'], {}).rows.map do |row|
|
360
|
+
[row.first, row.last.to_s.titleize]
|
375
361
|
end
|
362
|
+
rescue
|
363
|
+
[]
|
364
|
+
end
|
376
365
|
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
366
|
+
def render_forbidden
|
367
|
+
render plain: "Access denied", status: :forbidden
|
368
|
+
end
|
369
|
+
|
370
|
+
def query_params
|
371
|
+
params.require(:query).permit!
|
372
|
+
end
|
373
|
+
|
374
|
+
def blazer_params
|
375
|
+
params[:blazer] || {}
|
376
|
+
end
|
377
|
+
|
378
|
+
def csv_data(columns, rows, data_source)
|
379
|
+
CSV.generate do |csv|
|
380
|
+
csv << columns
|
381
|
+
rows.each do |row|
|
382
|
+
csv << row.each_with_index.map { |v, i| v.is_a?(Time) ? blazer_time_value(data_source, columns[i], v) : v }
|
386
383
|
end
|
387
|
-
rescue
|
388
|
-
return v
|
389
384
|
end
|
390
|
-
|
385
|
+
end
|
391
386
|
|
392
|
-
|
393
|
-
|
387
|
+
def blazer_time_value(data_source, k, v)
|
388
|
+
if k.end_with?('_date')
|
389
|
+
v.in_time_zone(Blazer.time_zone).strftime("%Y/%m/%d")
|
390
|
+
elsif k.end_with?('_time')
|
391
|
+
v.in_time_zone(Blazer.time_zone).strftime("%H:%M")
|
392
|
+
elsif data_source.local_time_suffix.any? { |s| k.ends_with?(s) }
|
393
|
+
v.to_s.sub(" UTC", "")
|
394
|
+
else
|
395
|
+
v.in_time_zone(Blazer.time_zone)
|
394
396
|
end
|
397
|
+
rescue
|
398
|
+
return v
|
399
|
+
end
|
400
|
+
helper_method :blazer_time_value
|
401
|
+
|
402
|
+
def blazer_run_id
|
403
|
+
params[:run_id].to_s.gsub(/[^a-z0-9\-]/i, "")
|
404
|
+
end
|
405
|
+
|
406
|
+
def preview_rows_number
|
407
|
+
Blazer.settings['preview_rows_number'] || 365
|
408
|
+
end
|
409
|
+
helper_method :preview_rows_number
|
395
410
|
|
396
|
-
def preview_rows_number
|
397
|
-
Blazer.settings['preview_rows_number'] || 365
|
398
|
-
end
|
399
|
-
helper_method :preview_rows_number
|
400
411
|
end
|
401
412
|
end
|