finery 3.0.0 → 3.0.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2e078ca59bdbb5792903b2a057557b43165d682a2c7a5e31980fc7b3f8db04a8
4
- data.tar.gz: de20ac5f79093919a5241ca654368bfe40cebbee45d52b87626d05227a87a80f
3
+ metadata.gz: 4a40d95bfaaec38b95bad08470391cd99a51a83fe31644fc72cf513b6ac0b69f
4
+ data.tar.gz: e0e41fd7197e9f4a14b288f253bb865ce97cc85a4937b5f2e64112468fe1940b
5
5
  SHA512:
6
- metadata.gz: 9ff36e58770bcfcb9aad2e699c69ee92dc1f2fffa2c87ab880f693eff439d48c915c43f0eeb4dc5fa06dc6baaaed71118a9b8bd60ae5d2d2f37b562be4c1107d
7
- data.tar.gz: aacececa615434984234722176cf89b11ded36cc8923d6235f754f7537ce9cb2bd6db09c36157a3173dd7ca1083fedd4744702df40de1a27d95f7fe4303db4c5
6
+ metadata.gz: 6df58aa1566ca58dbb5f0fcfdae18ba56657a1fdba72a87a4e77e1415cef15852efb2522703939870906523fb099e28849d4788a6a8ef6eb1e9f6f90fe1f1645
7
+ data.tar.gz: a4e647be9599ba0869f71be477f3829de5d6e26e266f879b9b5f37ddf740af7404a90801b06b68d427c18f5450a610371cbb16a6170c666d220902d35716073c
@@ -23,65 +23,6 @@
23
23
  //= require ./queries
24
24
  //= require ./fuzzysearch
25
25
 
26
- $(document).on('mouseenter', '.dropdown-toggle', function () {
27
- $(this).parent().addClass('open')
28
- })
29
-
30
- $(document).on("change", "#bind input, #bind select", function () {
31
- submitIfCompleted($(this).closest("form"))
32
- })
33
-
34
- $(document).on("click", "#code", function () {
35
- $(this).addClass("expanded")
36
- })
37
-
38
26
  $(document).on("click", "a[disabled]", function (e) {
39
27
  e.preventDefault()
40
28
  })
41
-
42
- function submitIfCompleted($form) {
43
- var completed = true
44
- $form.find("input[name], select").each( function () {
45
- if ($(this).val() == "") {
46
- completed = false
47
- }
48
- })
49
- if (completed) {
50
- $form.submit()
51
- }
52
- }
53
-
54
- // Prevent backspace from navigating backwards.
55
- // Adapted from Biff MaGriff: http://stackoverflow.com/a/7895814/1196499
56
- function preventBackspaceNav() {
57
- $(document).keydown(function (e) {
58
- var preventKeyPress
59
- if (e.keyCode == 8) {
60
- var d = e.srcElement || e.target
61
- switch (d.tagName.toUpperCase()) {
62
- case 'TEXTAREA':
63
- preventKeyPress = d.readOnly || d.disabled
64
- break
65
- case 'INPUT':
66
- preventKeyPress = d.readOnly || d.disabled || (d.attributes["type"] && $.inArray(d.attributes["type"].value.toLowerCase(), ["radio", "reset", "checkbox", "submit", "button"]) >= 0)
67
- break
68
- case 'DIV':
69
- preventKeyPress = d.readOnly || d.disabled || !(d.attributes["contentEditable"] && d.attributes["contentEditable"].value == "true")
70
- break
71
- default:
72
- preventKeyPress = true
73
- break
74
- }
75
- }
76
- else {
77
- preventKeyPress = false
78
- }
79
-
80
- if (preventKeyPress) {
81
- e.preventDefault()
82
- }
83
- })
84
- }
85
-
86
- preventBackspaceNav()
87
-
@@ -0,0 +1,2 @@
1
+ import { Application, Controller } from "https://unpkg.com/@hotwired/stimulus/dist/stimulus.js"
2
+ window.Stimulus = Application.start()
@@ -0,0 +1,11 @@
1
+ Stimulus.register("autosubmit", class extends Controller {
2
+ call(event) {
3
+ for (let e of this.element.elements) {
4
+ if (e.name && $(e).val() == "") {
5
+ return
6
+ }
7
+ }
8
+
9
+ this.element.requestSubmit()
10
+ }
11
+ })
@@ -0,0 +1,7 @@
1
+ Stimulus.register("code", class extends Controller {
2
+ connect() {
3
+ if (code.innerText.length < 10000) {
4
+ hljs.highlightElement(this.element)
5
+ }
6
+ }
7
+ })
@@ -0,0 +1,31 @@
1
+ Stimulus.register("datepicker", class extends Controller {
2
+ static targets = [ "input", "span" ]
3
+
4
+ connect() {
5
+ const now = moment.tz(timeZone)
6
+ const format = "YYYY-MM-DD"
7
+
8
+ function toDate(time) {
9
+ return moment.tz(time.format(format), timeZone)
10
+ }
11
+
12
+ const datePicker = $(this.element).daterangepicker({
13
+ singleDatePicker: true,
14
+ locale: { format: format },
15
+ autoUpdateInput: false,
16
+ autoApply: true,
17
+ startDate: this.inputTarget.value.length > 0 ? moment.tz(this.inputTarget.value, timeZone) : now
18
+ })
19
+
20
+ // hack to start with empty date
21
+ datePicker.on("apply.daterangepicker", (ev, picker) => {
22
+ this.spanTarget.innerHTML = toDate(picker.startDate).format("MMMM D, YYYY")
23
+ this.inputTarget.value = toDate(picker.startDate).utc().format()
24
+ this.element.dispatchEvent(new Event("change", { bubbles: true }))
25
+ })
26
+
27
+ if (this.inputTarget.value.length > 0) {
28
+ this.spanTarget.innerHTML = toDate(datePicker.data("daterangepicker").startDate).format("MMMM D, YYYY")
29
+ }
30
+ }
31
+ })
@@ -0,0 +1,49 @@
1
+ Stimulus.register("daterangepicker", class extends Controller {
2
+ connect() {
3
+ const now = moment.tz(timeZone)
4
+ const format = "YYYY-MM-DD"
5
+
6
+ function toDate(time) {
7
+ return moment.tz(time.format(format), timeZone)
8
+ }
9
+ function dateStr(daysAgo) {
10
+ return now.clone().subtract(daysAgo || 0, "days").format(format)
11
+ }
12
+ function setTimeInputs(start, end) {
13
+ $("#start_time").val(toDate(start).utc().format())
14
+ $("#end_time").val(toDate(end).endOf("day").utc().format())
15
+ }
16
+
17
+ const datePicker = $(this.element).daterangepicker({
18
+ ranges: {
19
+ "Today": [dateStr(), dateStr()],
20
+ "Last 7 Days": [dateStr(6), dateStr()],
21
+ "Last 30 Days": [dateStr(29), dateStr()]
22
+ },
23
+ locale: {
24
+ format: format
25
+ },
26
+ startDate: dateStr(29),
27
+ endDate: dateStr(),
28
+ opens: "right",
29
+ alwaysShowCalendars: true
30
+ },
31
+ function(start, end) {
32
+ setTimeInputs(start, end)
33
+ this.element.dispatchEvent(new Event("change", { bubbles: true }))
34
+ }.bind(this)).on("apply.daterangepicker", function(ev, picker) {
35
+ setTimeInputs(picker.startDate, picker.endDate)
36
+ $("#reportrange span").html(toDate(picker.startDate).format("MMMM D, YYYY") + " - " + toDate(picker.endDate).format("MMMM D, YYYY"))
37
+ })
38
+
39
+ const picker = datePicker.data("daterangepicker")
40
+ if ($("#start_time").val().length > 0) {
41
+ picker.setStartDate(moment.tz($("#start_time").val(), timeZone))
42
+ picker.setEndDate(moment.tz($("#end_time").val(), timeZone))
43
+ $(this.element).trigger("apply.daterangepicker", picker)
44
+ } else {
45
+ $(this.element).trigger("apply.daterangepicker", picker)
46
+ this.element.dispatchEvent(new Event("change", { bubbles: true }))
47
+ }
48
+ }
49
+ })
@@ -0,0 +1,11 @@
1
+ // This file is auto-generated by ./bin/rails stimulus:manifest:update
2
+ // Run that command whenever you add a new controller or create them with
3
+ // ./bin/rails generate stimulus controllerName
4
+
5
+ //= require ./application
6
+ //= require ./autosubmit_controller
7
+ //= require ./code_controller
8
+ //= require ./datepicker_controller
9
+ //= require ./daterangepicker_controller
10
+ //= require ./selectize_controller
11
+ //= require ./unsaved_controller
@@ -0,0 +1,8 @@
1
+ Stimulus.register("selectize", class extends Controller {
2
+ connect() {
3
+ $(this.element).selectize({
4
+ create: true,
5
+ onChange: function() { this.$input[0].dispatchEvent(new Event("change", { bubbles: true })) },
6
+ })
7
+ }
8
+ })
@@ -0,0 +1,24 @@
1
+ Stimulus.register("unsaved", class extends Controller {
2
+ changed = false
3
+
4
+ check(event) {
5
+ if (this.changed) {
6
+ event.preventDefault()
7
+ return (event.returnValue = "")
8
+ }
9
+ }
10
+
11
+ clear(event) {
12
+ if (this.changed) {
13
+ window.removeEventListener("beforeunload", this.check.bind(this), { capture: true })
14
+ this.changed = false
15
+ }
16
+ }
17
+
18
+ set(event) {
19
+ if (!this.changed) {
20
+ window.addEventListener("beforeunload", this.check.bind(this), { capture: true })
21
+ this.changed = true
22
+ }
23
+ }
24
+ })
@@ -0,0 +1 @@
1
+ //= require ./controllers
@@ -177,15 +177,6 @@ input.search:focus {
177
177
  color: #999;
178
178
  }
179
179
 
180
- #code {
181
- max-height: 236px;
182
- overflow: hidden;
183
- }
184
-
185
- #code.expanded {
186
- max-height: none;
187
- }
188
-
189
180
  [v-cloak] {
190
181
  display: none;
191
182
  }
@@ -22,11 +22,11 @@ module Blazer
22
22
  before_action Blazer.before_action.to_sym
23
23
  end
24
24
 
25
- # if Blazer.override_csp
26
- # after_action do
27
- # response.headers['Content-Security-Policy'] = "default-src 'self' https: 'unsafe-inline' 'unsafe-eval' data: blob:"
28
- # end
29
- # end
25
+ if Blazer.override_csp
26
+ after_action do
27
+ response.headers['Content-Security-Policy'] = "default-src 'self' https: 'unsafe-inline' 'unsafe-eval' data: blob:"
28
+ end
29
+ end
30
30
 
31
31
  layout "blazer/application"
32
32
 
@@ -273,7 +273,9 @@ module Blazer
273
273
  raise Error, @error if @error && Rails.env.test?
274
274
 
275
275
  data = csv_data(@columns, @rows, @data_source)
276
- filename = "#{@query.try(:name).try(:parameterize).presence || 'query'}.csv"
276
+ query_params = variable_params.select { |k| @query.variables.include?(k) }
277
+ name = @query.try(:name).presence || "query"
278
+ filename = "#{name}-#{query_params.to_query}".parameterize + ".csv"
277
279
  send_data data, type: "text/csv; charset=utf-8", disposition: "attachment", filename: filename
278
280
  end
279
281
  end
@@ -2,14 +2,8 @@
2
2
  <% var_params = request.query_parameters %>
3
3
  <script>
4
4
  <%= blazer_js_var "timeZone", Blazer.time_zone.tzinfo.name %>
5
- var now = moment.tz(timeZone)
6
- var format = "YYYY-MM-DD"
7
-
8
- function toDate(time) {
9
- return moment.tz(time.format(format), timeZone)
10
- }
11
5
  </script>
12
- <form id="bind" method="get" action="<%= action %>" class="form-inline" style="margin-bottom: 15px;">
6
+ <form id="bind" method="get" action="<%= action %>" class="form-inline" style="margin-bottom: 15px;" data-controller="autosubmit" data-action="change->autosubmit#call">
13
7
  <% date_vars = ["start_time", "end_time"] %>
14
8
  <% if (date_vars - @bind_vars).empty? %>
15
9
  <% @bind_vars = @bind_vars - date_vars %>
@@ -18,49 +12,23 @@
18
12
  <% end %>
19
13
 
20
14
  <% @bind_vars.each_with_index do |var, i| %>
15
+ <div class="form-group">
21
16
  <%= label_tag var, var %>
22
17
  <% if (data = @smart_vars[var]) %>
23
- <%= select_tag var, options_for_select([[nil, nil]] + data, selected: var_params[var]), style: "margin-right: 20px; width: 200px; display: none;" %>
24
- <script>
25
- $("#<%= var %>").selectize({
26
- create: true
27
- });
28
- </script>
18
+ <%= select_tag var, options_for_select([[nil, nil]] + data, selected: var_params[var]), data: { controller: "selectize" }, style: "margin-right: 20px; width: 200px; display: none;" %>
29
19
  <% elsif var.end_with?("_at") || var == "start_time" || var == "end_time" %>
30
- <%= hidden_field_tag var, var_params[var] %>
31
20
 
32
21
  <div class="selectize-control single" style="width: 200px;">
33
- <div id="<%= var %>-select" class="selectize-input" style="display: inline-block;">
34
- <span>Select a date</span>
22
+ <div id="<%= var %>-select" class="selectize-input" style="display: inline-block;" data-controller="datepicker">
23
+ <%= hidden_field_tag var, var_params[var], data: { datepicker_target: "input" } %>
24
+ <span data-datepicker-target="span">Select a date</span>
35
25
  </div>
36
26
  </div>
37
27
 
38
- <script>
39
- (function() {
40
- var input = $("#<%= var %>")
41
- var datePicker = $("#<%= var %>-select")
42
- datePicker.daterangepicker({
43
- singleDatePicker: true,
44
- locale: {format: format},
45
- autoUpdateInput: false,
46
- autoApply: true,
47
- startDate: input.val().length > 0 ? moment.tz(input.val(), timeZone) : now
48
- })
49
- // hack to start with empty date
50
- datePicker.on("apply.daterangepicker", function(ev, picker) {
51
- datePicker.find("span").html(toDate(picker.startDate).format("MMMM D, YYYY"))
52
- input.val(toDate(picker.startDate).utc().format())
53
- submitIfCompleted($("#<%= var %>").closest("form"))
54
- })
55
- if (input.val().length > 0) {
56
- var picker = datePicker.data("daterangepicker")
57
- datePicker.find("span").html(toDate(picker.startDate).format("MMMM D, YYYY"))
58
- }
59
- })()
60
- </script>
61
28
  <% else %>
62
- <%= text_field_tag var, var_params[var], style: "width: 120px; margin-right: 20px;", autofocus: i == 0 && !var.end_with?("_at") && !var_params[var], class: "form-control" %>
29
+ <%= text_field_tag var, var_params[var], autofocus: i == 0 && !var.end_with?("_at") && !var_params[var], class: "form-control" %>
63
30
  <% end %>
31
+ </div>
64
32
  <% end %>
65
33
 
66
34
  <% if date_vars %>
@@ -70,56 +38,10 @@
70
38
 
71
39
  <%= label_tag nil, date_vars.join(" & ") %>
72
40
  <div class="selectize-control single" style="width: 300px;">
73
- <div id="reportrange" class="selectize-input" style="display: inline-block;">
41
+ <div id="reportrange" class="selectize-input" style="display: inline-block;" data-controller="daterangepicker">
74
42
  <span>Select a time range</span>
75
43
  </div>
76
44
  </div>
77
-
78
- <script>
79
- function dateStr(daysAgo) {
80
- return now.clone().subtract(daysAgo || 0, "days").format(format)
81
- }
82
-
83
- function setTimeInputs(start, end) {
84
- $("#start_time").val(toDate(start).utc().format())
85
- $("#end_time").val(toDate(end).endOf("day").utc().format())
86
- }
87
-
88
- $("#reportrange").daterangepicker(
89
- {
90
- ranges: {
91
- "Today": [dateStr(), dateStr()],
92
- "Last 7 Days": [dateStr(6), dateStr()],
93
- "Last 30 Days": [dateStr(29), dateStr()]
94
- },
95
- locale: {
96
- format: format
97
- },
98
- startDate: dateStr(29),
99
- endDate: dateStr(),
100
- opens: "right",
101
- alwaysShowCalendars: true
102
- },
103
- function(start, end) {
104
- setTimeInputs(start, end)
105
- submitIfCompleted($("#start_time").closest("form"))
106
- }
107
- ).on("apply.daterangepicker", function(ev, picker) {
108
- setTimeInputs(picker.startDate, picker.endDate)
109
- $("#reportrange span").html(toDate(picker.startDate).format("MMMM D, YYYY") + " - " + toDate(picker.endDate).format("MMMM D, YYYY"))
110
- })
111
-
112
- if ($("#start_time").val().length > 0) {
113
- var picker = $("#reportrange").data("daterangepicker")
114
- picker.setStartDate(moment.tz($("#start_time").val(), timeZone))
115
- picker.setEndDate(moment.tz($("#end_time").val(), timeZone))
116
- $("#reportrange").trigger("apply.daterangepicker", picker)
117
- } else {
118
- var picker = $("#reportrange").data("daterangepicker")
119
- $("#reportrange").trigger("apply.daterangepicker", picker)
120
- submitIfCompleted($("#start_time").closest("form"))
121
- }
122
- </script>
123
45
  <% end %>
124
46
 
125
47
  <input type="submit" class="btn btn-success" value="Run" style="vertical-align: top;" />
@@ -5,7 +5,7 @@
5
5
  <% @variable_params = @query.persisted? ? variable_params(@query) : nested_variable_params(@query) %>
6
6
 
7
7
  <div id="app" v-cloak>
8
- <%= form_for @query, url: (@query.persisted? ? query_path(@query, params: @variable_params) : queries_path(params: @variable_params)), html: {autocomplete: "off"} do |f| %>
8
+ <%= form_for @query, url: (@query.persisted? ? query_path(@query, params: @variable_params) : queries_path(params: @variable_params)), html: {autocomplete: "off"}, data: { controller: "unsaved", action: "unsaved#clear input->unsaved#set" } do |f| %>
9
9
  <div class="row">
10
10
  <div id="statement-box" class="col-xs-8">
11
11
  <div class= "form-group">
@@ -39,7 +39,12 @@
39
39
 
40
40
  <%= render partial: "blazer/variables", locals: {action: query_path(@query)} %>
41
41
 
42
- <pre id="code"><code><%= @statement.display_statement %></code></pre>
42
+ <details class="row">
43
+ <summary class="col-md-1 col-md-offset-11 btn btn-sm btn-info">Show source</summary>
44
+ <pre id="code" class="col-md-12">
45
+ <code data-controller="code"><%= @statement.display_statement %></code>
46
+ </pre>
47
+ </details>
43
48
 
44
49
  <% if @success %>
45
50
  <div id="results">
@@ -61,12 +66,3 @@
61
66
  runQuery(data, showRun, showError)
62
67
  </script>
63
68
  <% end %>
64
-
65
- <script>
66
- // do not highlight really long queries
67
- // this can lead to performance issues
68
- var code = $("#code code")
69
- if (code.text().length < 10000) {
70
- hljs.highlightElement(code.get(0))
71
- }
72
- </script>
@@ -11,6 +11,7 @@
11
11
  <% else %>
12
12
  <%= stylesheet_link_tag "blazer/application" %>
13
13
  <%= javascript_include_tag "blazer/application" %>
14
+ <%= javascript_include_tag "blazer/module", type: "module" %>
14
15
  <% end %>
15
16
  <script>
16
17
  <%= blazer_js_var "rootPath", root_path %>
data/lib/blazer/engine.rb CHANGED
@@ -6,6 +6,7 @@ module Blazer
6
6
  if defined?(Sprockets) && Sprockets::VERSION.to_i >= 4
7
7
  app.config.assets.precompile += [
8
8
  "blazer/application.js",
9
+ "blazer/module.js",
9
10
  "blazer/application.css",
10
11
  "blazer/glyphicons-halflings-regular.eot",
11
12
  "blazer/glyphicons-halflings-regular.svg",
@@ -1,3 +1,3 @@
1
1
  module Blazer
2
- VERSION = "3.0.0"
2
+ VERSION = "3.0.1"
3
3
  end
data/lib/blazer.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # dependencies
2
2
  require "chartkick"
3
3
  require "safely/core"
4
+ require "stimulus-rails"
4
5
 
5
6
  # stdlib
6
7
  require "csv"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: finery
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 3.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane, Chris Hasinski, Tomasz Ratajczak and contributors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-01 00:00:00.000000000 Z
11
+ date: 2023-10-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0.4'
69
+ - !ruby/object:Gem::Dependency
70
+ name: stimulus-rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.2'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.2'
69
83
  description:
70
84
  email: krzysztof.hasinski+finery@gmail.com
71
85
  executables: []
@@ -96,12 +110,21 @@ files:
96
110
  - app/assets/javascripts/blazer/chartjs-adapter-date-fns.bundle.js
97
111
  - app/assets/javascripts/blazer/chartjs-plugin-annotation.min.js
98
112
  - app/assets/javascripts/blazer/chartkick.js
113
+ - app/assets/javascripts/blazer/controllers/application.js
114
+ - app/assets/javascripts/blazer/controllers/autosubmit_controller.js
115
+ - app/assets/javascripts/blazer/controllers/code_controller.js
116
+ - app/assets/javascripts/blazer/controllers/datepicker_controller.js
117
+ - app/assets/javascripts/blazer/controllers/daterangepicker_controller.js
118
+ - app/assets/javascripts/blazer/controllers/index.js
119
+ - app/assets/javascripts/blazer/controllers/selectize_controller.js
120
+ - app/assets/javascripts/blazer/controllers/unsaved_controller.js
99
121
  - app/assets/javascripts/blazer/daterangepicker.js
100
122
  - app/assets/javascripts/blazer/fuzzysearch.js
101
123
  - app/assets/javascripts/blazer/highlight.min.js
102
124
  - app/assets/javascripts/blazer/jquery.js
103
125
  - app/assets/javascripts/blazer/jquery.stickytableheaders.js
104
126
  - app/assets/javascripts/blazer/mapkick.bundle.js
127
+ - app/assets/javascripts/blazer/module.js
105
128
  - app/assets/javascripts/blazer/moment-timezone-with-data.js
106
129
  - app/assets/javascripts/blazer/moment.js
107
130
  - app/assets/javascripts/blazer/queries.js