blazer 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of blazer might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/Gemfile +1 -1
- data/README.md +14 -2
- data/Rakefile +0 -1
- data/app/assets/javascripts/blazer/application.js +1 -0
- data/app/assets/javascripts/blazer/daterangepicker.js +350 -96
- data/app/assets/javascripts/blazer/moment-timezone.js +1007 -0
- data/app/assets/javascripts/blazer/moment.js +1179 -536
- data/app/assets/stylesheets/blazer/daterangepicker-bs3.css +59 -7
- data/app/controllers/blazer/queries_controller.rb +13 -13
- data/app/helpers/blazer/queries_helper.rb +1 -3
- data/app/models/blazer/connection.rb +1 -0
- data/app/models/blazer/query.rb +1 -2
- data/app/views/blazer/queries/index.html.erb +1 -1
- data/app/views/blazer/queries/show.html.erb +35 -16
- data/blazer.gemspec +4 -4
- data/lib/blazer.rb +1 -1
- data/lib/blazer/engine.rb +1 -2
- data/lib/blazer/version.rb +1 -1
- metadata +4 -2
@@ -1,9 +1,8 @@
|
|
1
1
|
/*!
|
2
2
|
* Stylesheet for the Date Range Picker, for use with Bootstrap 3.x
|
3
3
|
*
|
4
|
-
* Copyright 2013 Dan Grossman ( http://www.dangrossman.info )
|
5
|
-
* Licensed under the
|
6
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
4
|
+
* Copyright 2013-2015 Dan Grossman ( http://www.dangrossman.info )
|
5
|
+
* Licensed under the MIT license. See http://www.opensource.org/licenses/mit-license.php
|
7
6
|
*
|
8
7
|
* Built for http://www.improvely.com
|
9
8
|
*/
|
@@ -18,11 +17,16 @@
|
|
18
17
|
margin: 4px;
|
19
18
|
}
|
20
19
|
|
21
|
-
.daterangepicker.opensright .ranges, .daterangepicker.opensright .calendar
|
20
|
+
.daterangepicker.opensright .ranges, .daterangepicker.opensright .calendar,
|
21
|
+
.daterangepicker.openscenter .ranges, .daterangepicker.openscenter .calendar {
|
22
22
|
float: right;
|
23
23
|
margin: 4px;
|
24
24
|
}
|
25
25
|
|
26
|
+
.daterangepicker.single .ranges, .daterangepicker.single .calendar {
|
27
|
+
float: none;
|
28
|
+
}
|
29
|
+
|
26
30
|
.daterangepicker .ranges {
|
27
31
|
width: 160px;
|
28
32
|
text-align: left;
|
@@ -75,7 +79,6 @@
|
|
75
79
|
}
|
76
80
|
|
77
81
|
.daterangepicker .ranges .input-mini {
|
78
|
-
background-color: #eee;
|
79
82
|
border: 1px solid #ccc;
|
80
83
|
border-radius: 4px;
|
81
84
|
color: #555;
|
@@ -162,6 +165,37 @@
|
|
162
165
|
content: '';
|
163
166
|
}
|
164
167
|
|
168
|
+
.daterangepicker.openscenter:before {
|
169
|
+
position: absolute;
|
170
|
+
top: -7px;
|
171
|
+
left: 0;
|
172
|
+
right: 0;
|
173
|
+
width: 0;
|
174
|
+
margin-left: auto;
|
175
|
+
margin-right: auto;
|
176
|
+
display: inline-block;
|
177
|
+
border-right: 7px solid transparent;
|
178
|
+
border-bottom: 7px solid #ccc;
|
179
|
+
border-left: 7px solid transparent;
|
180
|
+
border-bottom-color: rgba(0, 0, 0, 0.2);
|
181
|
+
content: '';
|
182
|
+
}
|
183
|
+
|
184
|
+
.daterangepicker.openscenter:after {
|
185
|
+
position: absolute;
|
186
|
+
top: -6px;
|
187
|
+
left: 0;
|
188
|
+
right: 0;
|
189
|
+
width: 0;
|
190
|
+
margin-left: auto;
|
191
|
+
margin-right: auto;
|
192
|
+
display: inline-block;
|
193
|
+
border-right: 6px solid transparent;
|
194
|
+
border-bottom: 6px solid #fff;
|
195
|
+
border-left: 6px solid transparent;
|
196
|
+
content: '';
|
197
|
+
}
|
198
|
+
|
165
199
|
.daterangepicker.opensright:before {
|
166
200
|
position: absolute;
|
167
201
|
top: -7px;
|
@@ -205,7 +239,7 @@
|
|
205
239
|
color: #999;
|
206
240
|
}
|
207
241
|
|
208
|
-
.daterangepicker td.disabled {
|
242
|
+
.daterangepicker td.disabled, .daterangepicker option.disabled {
|
209
243
|
color: #999;
|
210
244
|
}
|
211
245
|
|
@@ -220,6 +254,24 @@
|
|
220
254
|
border-radius: 0;
|
221
255
|
}
|
222
256
|
|
257
|
+
.daterangepicker td.start-date {
|
258
|
+
-webkit-border-radius: 4px 0 0 4px;
|
259
|
+
-moz-border-radius: 4px 0 0 4px;
|
260
|
+
border-radius: 4px 0 0 4px;
|
261
|
+
}
|
262
|
+
|
263
|
+
.daterangepicker td.end-date {
|
264
|
+
-webkit-border-radius: 0 4px 4px 0;
|
265
|
+
-moz-border-radius: 0 4px 4px 0;
|
266
|
+
border-radius: 0 4px 4px 0;
|
267
|
+
}
|
268
|
+
|
269
|
+
.daterangepicker td.start-date.end-date {
|
270
|
+
-webkit-border-radius: 4px;
|
271
|
+
-moz-border-radius: 4px;
|
272
|
+
border-radius: 4px;
|
273
|
+
}
|
274
|
+
|
223
275
|
.daterangepicker td.active, .daterangepicker td.active:hover {
|
224
276
|
background-color: #357ebd;
|
225
277
|
border-color: #3071a9;
|
@@ -248,7 +300,7 @@
|
|
248
300
|
width: 40%;
|
249
301
|
}
|
250
302
|
|
251
|
-
.daterangepicker select.hourselect, .daterangepicker select.minuteselect, .daterangepicker select.ampmselect {
|
303
|
+
.daterangepicker select.hourselect, .daterangepicker select.minuteselect, .daterangepicker select.secondselect, .daterangepicker select.ampmselect {
|
252
304
|
width: 50px;
|
253
305
|
margin-bottom: 0;
|
254
306
|
}
|
@@ -15,8 +15,9 @@ module Blazer
|
|
15
15
|
before_action :set_query, only: [:show, :edit, :update, :destroy]
|
16
16
|
|
17
17
|
def index
|
18
|
-
@queries = Blazer::Query.order(:name)
|
19
|
-
@
|
18
|
+
@queries = Blazer::Query.order(:name)
|
19
|
+
@queries = @queries.includes(:creator) if Blazer.user_class
|
20
|
+
@trending_queries = Blazer::Audit.group(:query_id).where("created_at > ?", 2.days.ago).having("COUNT(DISTINCT user_id) >= 3").uniq.count(:user_id)
|
20
21
|
end
|
21
22
|
|
22
23
|
def new
|
@@ -25,7 +26,7 @@ module Blazer
|
|
25
26
|
|
26
27
|
def create
|
27
28
|
@query = Blazer::Query.new(query_params)
|
28
|
-
@query.creator = current_user if respond_to?(:current_user)
|
29
|
+
@query.creator = current_user if respond_to?(:current_user) && Blazer.user_class
|
29
30
|
|
30
31
|
if @query.save
|
31
32
|
redirect_to @query
|
@@ -44,7 +45,7 @@ module Blazer
|
|
44
45
|
query = smart_variables[var]
|
45
46
|
if query
|
46
47
|
rows, error = run_statement(query)
|
47
|
-
@smart_vars[var] = rows.map{|v| v.values.reverse }
|
48
|
+
@smart_vars[var] = rows.map { |v| v.values.reverse }
|
48
49
|
@sql_errors << error if error
|
49
50
|
end
|
50
51
|
end
|
@@ -64,7 +65,7 @@ module Blazer
|
|
64
65
|
if Blazer.audit
|
65
66
|
audit = Blazer::Audit.new(statement: @statement)
|
66
67
|
audit.query = @query
|
67
|
-
audit.user = current_user if respond_to?(:current_user)
|
68
|
+
audit.user = current_user if respond_to?(:current_user) && Blazer.user_class
|
68
69
|
audit.save!
|
69
70
|
end
|
70
71
|
|
@@ -87,15 +88,15 @@ module Blazer
|
|
87
88
|
|
88
89
|
@filename = @query.name.parameterize if @query
|
89
90
|
|
90
|
-
@min_width_types = (@rows.first || {}).select{|k, v| v.is_a?(Time)
|
91
|
+
@min_width_types = (@rows.first || {}).select { |k, v| v.is_a?(Time) || v.is_a?(String) || smart_columns[k] }.keys
|
91
92
|
|
92
93
|
@boom = {}
|
93
94
|
@columns.keys.each do |key|
|
94
95
|
query = smart_columns[key]
|
95
96
|
if query
|
96
|
-
values = @rows.map{|r| r[key] }.compact.uniq
|
97
|
+
values = @rows.map { |r| r[key] }.compact.uniq
|
97
98
|
rows, error = run_statement(ActiveRecord::Base.send(:sanitize_sql_array, [query.sub("{value}", "(?)"), values]))
|
98
|
-
@boom[key] = Hash[
|
99
|
+
@boom[key] = Hash[rows.map(&:values)]
|
99
100
|
end
|
100
101
|
end
|
101
102
|
|
@@ -107,7 +108,7 @@ module Blazer
|
|
107
108
|
render layout: false
|
108
109
|
end
|
109
110
|
format.csv do
|
110
|
-
send_data csv_data(@rows), type:
|
111
|
+
send_data csv_data(@rows), type: "text/csv; charset=utf-8; header=present", disposition: "attachment; filename=\"#{@query ? @query.name.parameterize : 'query'}.csv\""
|
111
112
|
end
|
112
113
|
end
|
113
114
|
end
|
@@ -173,12 +174,12 @@ module Blazer
|
|
173
174
|
end
|
174
175
|
|
175
176
|
def extract_vars(statement)
|
176
|
-
statement.scan(/\{.*?\}/).map{|v| v[1...-1] }.uniq
|
177
|
+
statement.scan(/\{.*?\}/).map { |v| v[1...-1] }.uniq
|
177
178
|
end
|
178
179
|
|
179
180
|
def process_vars(statement)
|
180
181
|
@bind_vars = extract_vars(statement)
|
181
|
-
@success = @bind_vars.all?{|v| params[v] }
|
182
|
+
@success = @bind_vars.all? { |v| params[v] }
|
182
183
|
|
183
184
|
if @success
|
184
185
|
@bind_vars.each do |var|
|
@@ -212,13 +213,12 @@ module Blazer
|
|
212
213
|
default_schema = postgresql? ? "public" : Blazer::Connection.connection_config[:database]
|
213
214
|
schema = Blazer::Connection.connection_config[:schema] || default_schema
|
214
215
|
rows, error = run_statement(Blazer::Connection.send(:sanitize_sql_array, ["SELECT table_name, column_name, ordinal_position, data_type FROM information_schema.columns WHERE table_schema = ?", schema]))
|
215
|
-
Hash[
|
216
|
+
Hash[rows.group_by { |r| r["table_name"] }.map { |t, f| [t, f.sort_by { |f| f["ordinal_position"] }.map { |f| f.slice("column_name", "data_type") }] }.sort_by { |t, _f| t }]
|
216
217
|
end
|
217
218
|
helper_method :tables
|
218
219
|
|
219
220
|
def postgresql?
|
220
221
|
Blazer::Connection.connection.adapter_name == "PostgreSQL"
|
221
222
|
end
|
222
|
-
|
223
223
|
end
|
224
224
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module Blazer
|
2
2
|
module QueriesHelper
|
3
|
-
|
4
3
|
def title(title = nil)
|
5
4
|
if title
|
6
5
|
content_for(:title) { title }
|
@@ -10,12 +9,11 @@ module Blazer
|
|
10
9
|
end
|
11
10
|
|
12
11
|
def format_value(key, value)
|
13
|
-
if value.is_a?(Integer)
|
12
|
+
if value.is_a?(Integer) && !key.to_s.end_with?("id")
|
14
13
|
number_with_delimiter(value)
|
15
14
|
else
|
16
15
|
value
|
17
16
|
end
|
18
17
|
end
|
19
|
-
|
20
18
|
end
|
21
19
|
end
|
data/app/models/blazer/query.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Blazer
|
2
2
|
class Query < ActiveRecord::Base
|
3
|
-
belongs_to :creator, class_name: Blazer.user_class.to_s
|
3
|
+
belongs_to :creator, class_name: Blazer.user_class.to_s if Blazer.user_class
|
4
4
|
|
5
5
|
validates :name, presence: true
|
6
6
|
validates :statement, presence: true
|
@@ -8,6 +8,5 @@ module Blazer
|
|
8
8
|
def to_param
|
9
9
|
[id, name.gsub("'", "").parameterize].join("-")
|
10
10
|
end
|
11
|
-
|
12
11
|
end
|
13
12
|
end
|
@@ -26,7 +26,7 @@
|
|
26
26
|
<% end %>
|
27
27
|
</td>
|
28
28
|
<td class="creator text-right text-muted">
|
29
|
-
<% if (creator = query.creator)
|
29
|
+
<% if query.respond_to?(:creator) && (creator = query.creator) && creator.respond_to?(Blazer.user_name) %>
|
30
30
|
<% name = creator.send(Blazer.user_name) %>
|
31
31
|
<% if respond_to?(:current_user) and creator == current_user %>
|
32
32
|
You
|
@@ -11,6 +11,7 @@
|
|
11
11
|
</div>
|
12
12
|
<div class="col-sm-3 text-right">
|
13
13
|
<%= link_to "Edit", edit_query_path(@query), class: "btn btn-default" %>
|
14
|
+
<%= link_to "Fork", new_query_path(statement: @query.statement), class: "btn btn-info" %>
|
14
15
|
|
15
16
|
<% if !@error and @success %>
|
16
17
|
<%= button_to "Download", run_queries_path(statement: @query.statement, query_id: @query.id, format: "csv"), class: "btn btn-primary" %>
|
@@ -77,32 +78,48 @@
|
|
77
78
|
</div>
|
78
79
|
|
79
80
|
<script>
|
81
|
+
var timeZone = "<%= Blazer.time_zone.tzinfo.name %>";
|
82
|
+
var format = "YYYY-MM-DD";
|
83
|
+
var now = moment.tz(timeZone);
|
84
|
+
|
85
|
+
function dateStr(daysAgo) {
|
86
|
+
return now.clone().subtract(daysAgo || 0, "days").format(format);
|
87
|
+
}
|
88
|
+
|
89
|
+
function toDate(time) {
|
90
|
+
return moment.tz(time.format(format), timeZone);
|
91
|
+
}
|
92
|
+
|
93
|
+
function setTimeInputs(start, end) {
|
94
|
+
$("#start_time").val(toDate(start).utc().format());
|
95
|
+
$("#end_time").val(toDate(end).endOf("day").utc().format());
|
96
|
+
}
|
97
|
+
|
80
98
|
$('#reportrange').daterangepicker(
|
81
99
|
{
|
82
100
|
ranges: {
|
83
|
-
|
84
|
-
|
85
|
-
|
101
|
+
"Today": [dateStr(), dateStr()],
|
102
|
+
"Last 7 Days": [dateStr(6), dateStr()],
|
103
|
+
"Last 30 Days": [dateStr(29), dateStr()]
|
86
104
|
},
|
87
|
-
|
88
|
-
|
105
|
+
format: format,
|
106
|
+
startDate: dateStr(29),
|
107
|
+
endDate: dateStr(),
|
89
108
|
opens: "left"
|
90
109
|
},
|
91
110
|
function(start, end) {
|
92
|
-
|
93
|
-
$("#
|
94
|
-
$("#start_time").closest("form").submit();
|
111
|
+
setTimeInputs(start, end);
|
112
|
+
submitIfCompleted($("#start_time").closest("form"));
|
95
113
|
}
|
96
114
|
).on('apply.daterangepicker', function(ev, picker) {
|
97
|
-
|
98
|
-
$(
|
99
|
-
$('#reportrange span').html(picker.startDate.format('MMMM D, YYYY') + ' - ' + picker.endDate.format('MMMM D, YYYY'));
|
115
|
+
setTimeInputs(picker.startDate, picker.endDate);
|
116
|
+
$('#reportrange span').html(toDate(picker.startDate).format('MMMM D, YYYY') + ' - ' + toDate(picker.endDate).format('MMMM D, YYYY'));
|
100
117
|
})
|
101
118
|
|
102
119
|
if ($("#start_time").val().length > 0) {
|
103
120
|
var picker = $("#reportrange").data('daterangepicker');
|
104
|
-
picker.setStartDate(moment($("#start_time").val()));
|
105
|
-
picker.setEndDate(moment($("#end_time").val()));
|
121
|
+
picker.setStartDate(moment.tz($("#start_time").val(), timeZone));
|
122
|
+
picker.setEndDate(moment.tz($("#end_time").val(), timeZone));
|
106
123
|
$("#reportrange").trigger('apply.daterangepicker', picker)
|
107
124
|
}
|
108
125
|
</script>
|
@@ -130,9 +147,7 @@
|
|
130
147
|
<script>
|
131
148
|
hljs.initHighlightingOnLoad();
|
132
149
|
|
133
|
-
|
134
|
-
// see if all value are entered
|
135
|
-
var $form = $(this).closest("form");
|
150
|
+
function submitIfCompleted($form) {
|
136
151
|
var completed = true;
|
137
152
|
$form.find("input[name], select").each( function () {
|
138
153
|
if ($(this).val() == "") {
|
@@ -142,5 +157,9 @@
|
|
142
157
|
if (completed) {
|
143
158
|
$form.submit();
|
144
159
|
}
|
160
|
+
}
|
161
|
+
|
162
|
+
$(".form-inline input, .form-inline select").change( function () {
|
163
|
+
submitIfCompleted($(this).closest("form"));
|
145
164
|
});
|
146
165
|
</script>
|
data/blazer.gemspec
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
lib = File.expand_path(
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
4
|
+
require "blazer/version"
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "blazer"
|
8
8
|
spec.version = Blazer::VERSION
|
9
9
|
spec.authors = ["Andrew Kane"]
|
10
10
|
spec.email = ["andrew@chartkick.com"]
|
11
|
-
spec.summary =
|
12
|
-
spec.description =
|
11
|
+
spec.summary = "Share data effortlessly with your team"
|
12
|
+
spec.description = "Share data effortlessly with your team"
|
13
13
|
spec.homepage = "https://github.com/ankane/blazer"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
data/lib/blazer.rb
CHANGED
@@ -14,7 +14,7 @@ module Blazer
|
|
14
14
|
self.audit = true
|
15
15
|
self.user_name = :name
|
16
16
|
self.timeout = 15
|
17
|
-
self.user_class =
|
17
|
+
self.user_class = "User"
|
18
18
|
|
19
19
|
def self.time_zone=(time_zone)
|
20
20
|
@time_zone = time_zone.is_a?(ActiveSupport::TimeZone) ? time_zone : ActiveSupport::TimeZone[time_zone.to_s]
|
data/lib/blazer/engine.rb
CHANGED
@@ -4,8 +4,7 @@ module Blazer
|
|
4
4
|
|
5
5
|
initializer "precompile" do |app|
|
6
6
|
# use a proc instead of a string
|
7
|
-
app.config.assets.precompile <<
|
7
|
+
app.config.assets.precompile << proc { |path| path =~ /\Ablazer\/application\.(js|css)\z/ }
|
8
8
|
end
|
9
|
-
|
10
9
|
end
|
11
10
|
end
|
data/lib/blazer/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: blazer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-06-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -92,6 +92,7 @@ files:
|
|
92
92
|
- app/assets/javascripts/blazer/jquery.stickytableheaders.js
|
93
93
|
- app/assets/javascripts/blazer/jquery_ujs.js
|
94
94
|
- app/assets/javascripts/blazer/list.js
|
95
|
+
- app/assets/javascripts/blazer/moment-timezone.js
|
95
96
|
- app/assets/javascripts/blazer/moment.js
|
96
97
|
- app/assets/javascripts/blazer/selectize.js
|
97
98
|
- app/assets/javascripts/blazer/stupidtable.js
|
@@ -145,3 +146,4 @@ signing_key:
|
|
145
146
|
specification_version: 4
|
146
147
|
summary: Share data effortlessly with your team
|
147
148
|
test_files: []
|
149
|
+
has_rdoc:
|