Browse Source

Added variables to dashboards

Andrew Kane 9 years ago
parent
commit
e82c51c2f5

+ 26 - 0
app/controllers/blazer/base_controller.rb

@@ -18,5 +18,31 @@ module Blazer
     def ensure_database_url
       render text: "BLAZER_DATABASE_URL required" if !ENV["BLAZER_DATABASE_URL"] && !Rails.env.development?
     end
+
+    def process_vars(statement)
+      (@bind_vars ||= []).concat extract_vars(statement)
+      @success = @bind_vars.all? { |v| params[v] }
+
+      if @success
+        @bind_vars.each do |var|
+          value = params[var].presence
+          value = value.to_i if value.to_i.to_s == value
+          if var.end_with?("_at")
+            value = Blazer.time_zone.parse(value) rescue nil
+          end
+          statement.gsub!("{#{var}}", ActiveRecord::Base.connection.quote(value))
+        end
+      end
+    end
+
+    def extract_vars(statement)
+      statement.scan(/\{.*?\}/).map { |v| v[1...-1] }.uniq
+    end
+    helper_method :extract_vars
+
+    def variable_params
+      params.except(:controller, :action, :id, :host, :query, :table_names, :authenticity_token, :utf8, :_method, :commit, :statement)
+    end
+    helper_method :variable_params
   end
 end

+ 15 - 0
app/controllers/blazer/dashboards_controller.rb

@@ -21,6 +21,21 @@ module Blazer
     end
 
     def show
+      @queries = @dashboard.blazer_dashboard_queries.order(:position).preload(:blazer_query).map(&:blazer_query)
+      @queries.each do |query|
+        process_vars(query.statement)
+      end
+
+      @smart_vars = {}
+      @sql_errors = []
+      @bind_vars.each do |var|
+        query = Blazer.smart_variables[var]
+        if query
+          rows, error = Blazer.run_statement(query)
+          @smart_vars[var] = rows.map { |v| v.values.reverse }
+          @sql_errors << error if error
+        end
+      end
     end
 
     def edit

+ 0 - 26
app/controllers/blazer/queries_controller.rb

@@ -142,31 +142,5 @@ module Blazer
         end
       end
     end
-
-    def extract_vars(statement)
-      statement.scan(/\{.*?\}/).map { |v| v[1...-1] }.uniq
-    end
-    helper_method :extract_vars
-
-    def process_vars(statement)
-      @bind_vars = extract_vars(statement)
-      @success = @bind_vars.all? { |v| params[v] }
-
-      if @success
-        @bind_vars.each do |var|
-          value = params[var].presence
-          value = value.to_i if value.to_i.to_s == value
-          if var.end_with?("_at")
-            value = Blazer.time_zone.parse(value) rescue nil
-          end
-          statement.gsub!("{#{var}}", ActiveRecord::Base.connection.quote(value))
-        end
-      end
-    end
-
-    def variable_params
-      params.except(:controller, :action, :id, :host, :query, :table_names, :authenticity_token, :utf8, :_method, :commit, :statement)
-    end
-    helper_method :variable_params
   end
 end

+ 118 - 2
app/views/blazer/dashboards/show.html.erb

@@ -1,5 +1,19 @@
 <% title @dashboard.name %>
 
+<script>
+  function submitIfCompleted($form) {
+    var completed = true;
+    $form.find("input[name], select").each( function () {
+      if ($(this).val() == "") {
+        completed = false;
+      }
+    });
+    if (completed) {
+      $form.submit();
+    }
+  }
+</script>
+
 <div style="position: fixed; top: 0; left: 0; right: 0; background-color: whitesmoke; height: 60px; z-index: 1001;">
   <div class="container">
     <div class="row" style="padding-top: 13px;">
@@ -18,9 +32,105 @@
 
 <div style="margin-bottom: 80px;"></div>
 
-<% @dashboard.blazer_dashboard_queries.order(:position).map(&:blazer_query).each_with_index do |query, i| %>
+<% if @bind_vars.any? %>
+  <form id="bind" method="get" action="<%= url_for(params) %>" class="form-inline" style="margin-bottom: 10px;">
+    <% date_vars = ["start_time", "end_time"] %>
+    <% if (date_vars - @bind_vars).empty? %>
+      <% @bind_vars = @bind_vars - date_vars %>
+    <% else %>
+      <% date_vars = nil %>
+    <% end %>
+
+    <% @bind_vars.each_with_index do |var, i| %>
+      <%= label_tag var, var %>
+      <% if (data = @smart_vars[var]) %>
+        <%= select_tag var, options_for_select([[nil, nil]] + data, selected: params[var]), style: "margin-right: 20px; width: 200px;" %>
+        <script>
+          $("#<%= var %>").selectize({
+            create: true
+          });
+        </script>
+      <% else %>
+        <%= text_field_tag var, params[var], style: "width: 120px; margin-right: 20px;", autofocus: i == 0 && !var.end_with?("_at") && !params[var], class: "form-control" %>
+        <% if var.end_with?("_at") %>
+          <script>
+            $("#<%= var %>").datepicker({format: "yyyy-mm-dd", autoclose: true, todayBtn: "linked"})
+          </script>
+        <% end %>
+      <% end %>
+    <% end %>
+
+    <% if date_vars %>
+      <% date_vars.each do |var| %>
+        <%= hidden_field_tag var, params[var] %>
+      <% end %>
+
+      <%= label_tag nil, date_vars.join(" & ") %>
+      <div class="selectize-control single" style="width: 300px;">
+        <div id="reportrange" class="selectize-input" style="display: inline-block;">
+          <span>Select a time range</span>
+        </div>
+      </div>
+
+      <script>
+        var timeZone = "<%= Blazer.time_zone.tzinfo.name %>";
+        var format = "YYYY-MM-DD";
+        var now = moment.tz(timeZone);
+
+        function dateStr(daysAgo) {
+          return now.clone().subtract(daysAgo || 0, "days").format(format);
+        }
+
+        function toDate(time) {
+          return moment.tz(time.format(format), timeZone);
+        }
+
+        function setTimeInputs(start, end) {
+          $("#start_time").val(toDate(start).utc().format());
+          $("#end_time").val(toDate(end).endOf("day").utc().format());
+        }
+
+        $('#reportrange').daterangepicker(
+          {
+            ranges: {
+             "Today": [dateStr(), dateStr()],
+             "Last 7 Days": [dateStr(6), dateStr()],
+             "Last 30 Days": [dateStr(29), dateStr()]
+            },
+            format: format,
+            startDate: dateStr(29),
+            endDate: dateStr(),
+            opens: "left"
+          },
+          function(start, end) {
+            setTimeInputs(start, end);
+            submitIfCompleted($("#start_time").closest("form"));
+          }
+        ).on('apply.daterangepicker', function(ev, picker) {
+          setTimeInputs(picker.startDate, picker.endDate);
+          $('#reportrange span').html(toDate(picker.startDate).format('MMMM D, YYYY') + ' - ' + toDate(picker.endDate).format('MMMM D, YYYY'));
+        })
+
+        if ($("#start_time").val().length > 0) {
+          var picker = $("#reportrange").data('daterangepicker');
+          picker.setStartDate(moment.tz($("#start_time").val(), timeZone));
+          picker.setEndDate(moment.tz($("#end_time").val(), timeZone));
+          $("#reportrange").trigger('apply.daterangepicker', picker)
+        } else {
+          var picker = $("#reportrange").data('daterangepicker');
+          $("#reportrange").trigger('apply.daterangepicker', picker);
+          submitIfCompleted($("#start_time").closest("form"));
+        }
+      </script>
+    <% end %>
+
+    <input type="submit" class="btn btn-success" value="Run" style="vertical-align: top;" />
+  </form>
+<% end %>
+
+<% @queries.each_with_index do |query, i| %>
   <div style="margin-top: 40px;">
-    <h4 style="text-align: center;"><%= link_to query.name, query_path(query), style: "color: inherit;" %></h4>
+    <h4 style="text-align: center;"><%= link_to query.name, query_path(query, variable_params), style: "color: inherit;" %></h4>
     <div id="chart-<%= i %>" style="height: 300px; text-align: center; line-height: 300px;">Loading...</div>
   </div>
   <script>
@@ -29,3 +139,9 @@
     });
   </script>
 <% end %>
+
+<script>
+  $(".form-inline input, .form-inline select").change( function () {
+    submitIfCompleted($(this).closest("form"));
+  });
+</script>

+ 12 - 2
app/views/blazer/queries/run.html.erb

@@ -1,7 +1,15 @@
 <% if @error %>
-  <div class="alert alert-danger"><%= @error %></div>
+  <% if @only_chart %>
+    <p><%= @error %></p>
+  <% else %>
+    <div class="alert alert-danger"><%= @error %></div>
+  <% end %>
 <% elsif !@success %>
-  <div class="alert alert-info">Can’t preview queries with variables...yet!</div>
+  <% if @only_chart %>
+    <p>Choose variables</p>
+  <% else %>
+    <div class="alert alert-info">Can’t preview queries with variables...yet!</div>
+  <% end %>
 <% else %>
   <% unless @only_chart %>
     <p class="text-muted"><%= pluralize(@rows.size, "row") %></p>
@@ -17,6 +25,8 @@
       <%= line_chart @rows.group_by { |v| v[keys[1]] }.map { |name, v| {name: name, data: v.map { |v2| [v2[keys[0]].in_time_zone(Blazer.time_zone), v2[keys[2]]] } } }, id: chart_id, min: nil %>
     <% elsif values.size == 2 && values.first.is_a?(String) && values.last.is_a?(Numeric) %>
       <%= pie_chart @rows.map(&:values), library: {sliceVisibilityThreshold: 1 / 40.0}, id: chart_id %>
+    <% elsif @only_chart %>
+      <p>No chart</p>
     <% end %>
 
     <% unless @only_chart %>