sql-jarvis 2.0.9 → 2.1
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/main.js +4 -3
- data/app/helpers/blazer/base_helper.rb +1 -1
- data/app/views/blazer/_nav.html.haml +12 -0
- data/app/views/blazer/{_variables.html.erb → _variables.html.haml} +35 -57
- data/app/views/blazer/check_mailer/failing_checks.html.haml +6 -0
- data/app/views/blazer/check_mailer/state_change.html.haml +31 -0
- data/app/views/blazer/checks/_form.html.haml +51 -0
- data/app/views/blazer/checks/edit.html.haml +2 -0
- data/app/views/blazer/checks/index.html.haml +48 -0
- data/app/views/blazer/checks/new.html.haml +2 -0
- data/app/views/blazer/dashboards/_form.html.haml +64 -0
- data/app/views/blazer/dashboards/edit.html.haml +2 -0
- data/app/views/blazer/dashboards/new.html.haml +2 -0
- data/app/views/blazer/dashboards/show.html.haml +33 -0
- data/app/views/blazer/queries/{_form.html.erb → _form.html.haml} +54 -81
- data/app/views/blazer/queries/_tips.html.haml +92 -0
- data/app/views/blazer/queries/docs.html.haml +115 -0
- data/app/views/blazer/queries/edit.html.haml +2 -0
- data/app/views/blazer/queries/{home.html.erb → home.html.haml} +38 -58
- data/app/views/blazer/queries/new.html.haml +2 -0
- data/app/views/blazer/queries/run.html.haml +153 -0
- data/app/views/blazer/queries/schema.html.haml +43 -0
- data/app/views/blazer/queries/show.html.haml +50 -0
- data/app/views/layouts/blazer/application.html.haml +19 -0
- data/lib/blazer/version.rb +1 -1
- metadata +38 -24
- data/app/views/blazer/_nav.html.erb +0 -15
- data/app/views/blazer/check_mailer/failing_checks.html.erb +0 -6
- data/app/views/blazer/check_mailer/state_change.html.erb +0 -47
- data/app/views/blazer/checks/_form.html.erb +0 -79
- data/app/views/blazer/checks/edit.html.erb +0 -3
- data/app/views/blazer/checks/index.html.erb +0 -69
- data/app/views/blazer/checks/new.html.erb +0 -3
- data/app/views/blazer/dashboards/_form.html.erb +0 -76
- data/app/views/blazer/dashboards/edit.html.erb +0 -3
- data/app/views/blazer/dashboards/new.html.erb +0 -3
- data/app/views/blazer/dashboards/show.html.erb +0 -51
- data/app/views/blazer/queries/_tips.html.erb +0 -69
- data/app/views/blazer/queries/docs.html.erb +0 -131
- data/app/views/blazer/queries/edit.html.erb +0 -2
- data/app/views/blazer/queries/new.html.erb +0 -2
- data/app/views/blazer/queries/run.html.erb +0 -202
- data/app/views/blazer/queries/schema.html.erb +0 -58
- data/app/views/blazer/queries/show.html.erb +0 -76
- data/app/views/layouts/blazer/application.html.erb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c6ac3baeeb351f06d68988d5f2828002dcbc4edb6c07fb841bf2c316655398f4
|
4
|
+
data.tar.gz: 9d898978f1b770f769393cb2db0e6803392a15a9df23e5318a76263f77701b7f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 56535c70ff300b1d818abf4d868002b00aec750ca5b569a0774d8944892599a4335d728f8115bd6d543029cc774e4337a0d9d1272f7733ba4000b02a261d1617
|
7
|
+
data.tar.gz: 5e7af8d4b27e85f9e14a2e502a6d72657499717cc981a9edec88c60732a662d84af73a8a6830eed0da5f8b938b58081163f0a2fdd8f8b3ce0a74f1ca190fe97c
|
@@ -19,19 +19,20 @@ $(document).on("click", "a.click2CopyTable", function (event) {
|
|
19
19
|
copyToClipboard(selector)
|
20
20
|
})
|
21
21
|
|
22
|
-
$(document).on("mouseover", "table th[data-popup
|
22
|
+
$(document).on("mouseover", "table th[data-popup]", function (event) {
|
23
23
|
var sum = 0, numbers = [];
|
24
24
|
var columns = $(this).parents('thead').find('th');
|
25
25
|
var columnIndex = columns.index(this) + 1;
|
26
26
|
var cells = $(this).parents('table').find('tbody tr td:nth-child('+columnIndex+')');
|
27
27
|
cells.each(function(index, cell) {
|
28
28
|
content = $(cell).text();
|
29
|
-
content = content.split('
|
29
|
+
content = content.split(',').join('');
|
30
30
|
float = parseFloat(content);
|
31
31
|
if (isNaN(float)) float = 0;
|
32
32
|
numbers.push(float);
|
33
33
|
sum += float
|
34
34
|
});
|
35
|
+
sum = parseFloat(sum.toFixed(2));
|
35
36
|
showTooltip({
|
36
37
|
el: this,
|
37
38
|
min: Math.min.apply(null, numbers),
|
@@ -42,7 +43,7 @@ $(document).on("mouseover", "table th[data-popup='true']", function (event) {
|
|
42
43
|
})
|
43
44
|
})
|
44
45
|
|
45
|
-
$(document).on("mouseleave", "table th[data-popup
|
46
|
+
$(document).on("mouseleave", "table th[data-popup]", function (event) {
|
46
47
|
$('#summanyPopup').remove();
|
47
48
|
})
|
48
49
|
|
@@ -13,7 +13,7 @@ module Blazer
|
|
13
13
|
|
14
14
|
def blazer_format_value(key, value)
|
15
15
|
if value.is_a?(Numeric) && !key.to_s.end_with?("id") && !key.to_s.start_with?("id")
|
16
|
-
number_with_delimiter(value)
|
16
|
+
number_with_delimiter(value, delimiter: ',', separator: '.')
|
17
17
|
elsif value =~ BLAZER_URL_REGEX
|
18
18
|
# see if image or link
|
19
19
|
if Blazer.images && (key.include?("image") || BLAZER_IMAGE_EXT.include?(value.split(".").last.split("?").first.try(:downcase)))
|
@@ -0,0 +1,12 @@
|
|
1
|
+
.btn-group{:style => "vertical-align: top; margin-right: 5px;"}
|
2
|
+
= link_to "Home", root_path, class: "btn btn-primary"
|
3
|
+
%button.btn.btn-primary.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-toggle" => "dropdown", :type => "button"}
|
4
|
+
%span.caret
|
5
|
+
%span.sr-only Toggle Dropdown
|
6
|
+
%ul.dropdown-menu
|
7
|
+
%li= link_to "Checks", checks_path
|
8
|
+
%li.divider{:role => "separator"}
|
9
|
+
%li= link_to "New Query", new_query_path
|
10
|
+
%li= link_to "New Dashboard", new_dashboard_path
|
11
|
+
- check_params = @query ? {query_id: @query.id} : {}
|
12
|
+
%li= link_to "New Check", new_check_path(check_params)
|
@@ -1,43 +1,35 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
- if @bind_vars.any?
|
2
|
+
:javascript
|
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
6
|
|
7
7
|
function toDate(time) {
|
8
8
|
return moment.tz(time.format(format), timeZone)
|
9
9
|
}
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
<%= select_tag var, options_for_select([[nil, nil]] + data, selected: params[var]), style: "margin-right: 20px; width: 200px; display: none;", multiple: true %>
|
23
|
-
<script>
|
24
|
-
$("#<%= var %>").selectize({
|
10
|
+
%form#bind.form-inline{:action => action, :method => "get", :style => "margin-bottom: 15px;"}
|
11
|
+
- date_vars = ["start_time", "end_time"]
|
12
|
+
- if (date_vars - @bind_vars).empty?
|
13
|
+
- @bind_vars = @bind_vars - date_vars
|
14
|
+
- else
|
15
|
+
- date_vars = nil
|
16
|
+
- @bind_vars.each_with_index do |var, i|
|
17
|
+
= label_tag var, var
|
18
|
+
- if (data = @smart_vars[var])
|
19
|
+
= select_tag var, options_for_select([[nil, nil]] + data, selected: params[var]), style: "margin-right: 20px; width: 200px; display: none;", multiple: true
|
20
|
+
:javascript
|
21
|
+
$("##{var}").selectize({
|
25
22
|
create: true
|
26
23
|
});
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
<span>Select a date</span>
|
34
|
-
</div>
|
35
|
-
</div>
|
36
|
-
|
37
|
-
<script>
|
24
|
+
- elsif var.end_with?("_at") || var == "start_time" || var == "end_time"
|
25
|
+
= hidden_field_tag var, params[var]
|
26
|
+
.selectize-control.single{:style => "width: 200px;"}
|
27
|
+
.selectize-input{:id => "#{var}-select", :style => "display: inline-block;"}
|
28
|
+
%span Select a date
|
29
|
+
:javascript
|
38
30
|
(function() {
|
39
|
-
var input = $("
|
40
|
-
var datePicker = $("
|
31
|
+
var input = $("##{var}")
|
32
|
+
var datePicker = $("##{var}-select")
|
41
33
|
datePicker.daterangepicker({
|
42
34
|
singleDatePicker: true,
|
43
35
|
locale: {format: format},
|
@@ -48,32 +40,23 @@
|
|
48
40
|
datePicker.on("apply.daterangepicker", function(ev, picker) {
|
49
41
|
datePicker.find("span").html(toDate(picker.startDate).format("MMMM D, YYYY"))
|
50
42
|
input.val(toDate(picker.startDate).utc().format())
|
51
|
-
submitIfCompleted($("
|
43
|
+
submitIfCompleted($("##{var}").closest("form"))
|
52
44
|
})
|
53
45
|
if (input.val().length > 0) {
|
54
46
|
var picker = datePicker.data("daterangepicker")
|
55
47
|
datePicker.find("span").html(toDate(picker.startDate).format("MMMM D, YYYY"))
|
56
48
|
}
|
57
49
|
})()
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
<%= label_tag nil, date_vars.join(" & ") %>
|
70
|
-
<div class="selectize-control single" style="width: 300px;">
|
71
|
-
<div id="reportrange" class="selectize-input" style="display: inline-block;">
|
72
|
-
<span>Select a time range</span>
|
73
|
-
</div>
|
74
|
-
</div>
|
75
|
-
|
76
|
-
<script>
|
50
|
+
- else
|
51
|
+
= text_field_tag var, params[var], style: "width: 120px; margin-right: 20px;", autofocus: i == 0 && !var.end_with?("_at") && !params[var], class: "form-control"
|
52
|
+
- if date_vars
|
53
|
+
- date_vars.each do |var|
|
54
|
+
= hidden_field_tag var, params[var]
|
55
|
+
= label_tag nil, date_vars.join(" & ")
|
56
|
+
.selectize-control.single{:style => "width: 300px;"}
|
57
|
+
#reportrange.selectize-input{:style => "display: inline-block;"}
|
58
|
+
%span Select a time range
|
59
|
+
:javascript
|
77
60
|
function dateStr(daysAgo) {
|
78
61
|
return now.clone().subtract(daysAgo || 0, "days").format(format)
|
79
62
|
}
|
@@ -116,9 +99,4 @@
|
|
116
99
|
$("#reportrange").trigger("apply.daterangepicker", picker)
|
117
100
|
submitIfCompleted($("#start_time").closest("form"))
|
118
101
|
}
|
119
|
-
|
120
|
-
<% end %>
|
121
|
-
|
122
|
-
<input type="submit" class="btn btn-success" value="Run" style="vertical-align: top;" />
|
123
|
-
</form>
|
124
|
-
<% end %>
|
102
|
+
%input.btn.btn-success{:style => "vertical-align: top;", :type => "submit", :value => "Run"}/
|
@@ -0,0 +1,31 @@
|
|
1
|
+
!!!
|
2
|
+
%html
|
3
|
+
%head
|
4
|
+
%meta{:content => "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}/
|
5
|
+
%body{:style => "font-family: 'Helvetica Neue', Arial, Helvetica; font-size: 14px; color: #333;"}
|
6
|
+
%p= link_to "View", query_url(@check.query_id, host: Blazer.host)
|
7
|
+
- if @error
|
8
|
+
%p= @error
|
9
|
+
- elsif @rows_count > 0 && @check_type == "bad_data"
|
10
|
+
%p
|
11
|
+
- if @rows_count <= 10
|
12
|
+
= pluralize(@rows_count, "row")
|
13
|
+
- else
|
14
|
+
Showing 10 of #{@rows_count} rows
|
15
|
+
%table{:style => "width: 100%; border-spacing: 0; border-collapse: collapse;"}
|
16
|
+
%thead
|
17
|
+
%tr
|
18
|
+
- @columns.first(5).each do |column|
|
19
|
+
%th{:style => "padding: 8px; line-height: 1.4; text-align: left; vertical-align: bottom; border-bottom: 2px solid #ddd; width: #{(100 / @columns.size).round(2)}%;"}
|
20
|
+
= column
|
21
|
+
%tbody
|
22
|
+
- @rows.first(10).each do |row|
|
23
|
+
%tr
|
24
|
+
- @columns.first(5).each_with_index do |column, i|
|
25
|
+
%td{:style => "padding: 8px; line-height: 1.4; vertical-align: top; border-top: 1px solid #ddd;"}
|
26
|
+
- value = row[i]
|
27
|
+
- if @column_types[i] == "time" && value.to_s.length > 10
|
28
|
+
- value = Time.parse(value).in_time_zone(Blazer.time_zone) rescue value
|
29
|
+
= value
|
30
|
+
- if @columns.size > 5
|
31
|
+
%p{:style => "color: #999;"} Only first 5 columns shown
|
@@ -0,0 +1,51 @@
|
|
1
|
+
= form_for @check, html: {class: "small-form"} do |f|
|
2
|
+
- unless @check.respond_to?(:check_type) || @check.respond_to?(:invert)
|
3
|
+
%p.text-muted Checks are designed to identify bad data. A check fails if there are any results.
|
4
|
+
- if @check.errors.any?
|
5
|
+
.alert.alert-danger= @check.errors.full_messages.first
|
6
|
+
.form-group
|
7
|
+
= f.label :query_id, "Query"
|
8
|
+
.hide
|
9
|
+
= f.select :query_id, [], {include_blank: true}
|
10
|
+
:javascript
|
11
|
+
#{blazer_js_var "queries", Blazer::Query.named.order(:name).select("id, name").map { |q| {text: q.name, value: q.id} }}
|
12
|
+
#{blazer_js_var "items", [@check.query_id].compact}
|
13
|
+
|
14
|
+
$("#check_query_id").selectize({options: queries, items: items, highlight: false, maxOptions: 100}).parents(".hide").removeClass("hide");
|
15
|
+
- if @check.respond_to?(:check_type)
|
16
|
+
.form-group
|
17
|
+
= f.label :check_type, "Alert if"
|
18
|
+
.hide
|
19
|
+
- check_options = [["Any results (bad data)", "bad_data"], ["No results (missing data)", "missing_data"]]
|
20
|
+
- check_options << ["Anomaly (most recent data point)", "anomaly"] if Blazer.anomaly_checks
|
21
|
+
= f.select :check_type, check_options
|
22
|
+
:javascript
|
23
|
+
$("#check_check_type").selectize({}).parent().removeClass("hide");
|
24
|
+
- elsif @check.respond_to?(:invert)
|
25
|
+
.form-group
|
26
|
+
= f.label :invert, "Fails if"
|
27
|
+
.hide
|
28
|
+
= f.select :invert, [["Any results (bad data)", false], ["No results (missing data)", true]]
|
29
|
+
:javascript
|
30
|
+
$("#check_invert").selectize({}).parent().removeClass("hide");
|
31
|
+
- if @check.respond_to?(:schedule) && Blazer.check_schedules
|
32
|
+
.form-group
|
33
|
+
= f.label :schedule, "Run every"
|
34
|
+
.hide
|
35
|
+
= f.select :schedule, Blazer.check_schedules.map { |v| [v, v] }
|
36
|
+
:javascript
|
37
|
+
$("#check_schedule").selectize({}).parent().removeClass("hide");
|
38
|
+
.form-group
|
39
|
+
= f.label :emails
|
40
|
+
= f.text_field :emails, placeholder: "Optional, comma separated", class: "form-control"
|
41
|
+
- if Blazer.slack?
|
42
|
+
.form-group
|
43
|
+
= f.label :slack_channels
|
44
|
+
= f.text_field :slack_channels, placeholder: "Optional, comma separated", class: "form-control"
|
45
|
+
%p.text-muted
|
46
|
+
Emails #{Blazer.slack? ? "and Slack notifications " : nil}are sent when a check starts failing, and when it starts passing again.
|
47
|
+
%p
|
48
|
+
- if @check.persisted?
|
49
|
+
= link_to "Delete", check_path(@check), method: :delete, "data-confirm" => "Are you sure?", class: "btn btn-danger"
|
50
|
+
= f.submit "Save", class: "btn btn-success"
|
51
|
+
= link_to "Back", :back, class: "btn btn-link"
|
@@ -0,0 +1,48 @@
|
|
1
|
+
- blazer_title "Checks"
|
2
|
+
#header
|
3
|
+
.pull-right{:style => "line-height: 34px;"}
|
4
|
+
.btn-group
|
5
|
+
= link_to "New Check", new_check_path, class: "btn btn-info"
|
6
|
+
%button.btn.btn-info.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-toggle" => "dropdown", :type => "button"}
|
7
|
+
%span.caret
|
8
|
+
%span.sr-only Toggle Dropdown
|
9
|
+
%ul.dropdown-menu
|
10
|
+
%li= link_to "Home", root_path
|
11
|
+
%li.divider{:role => "separator"}
|
12
|
+
%li= link_to "New Query", new_query_path
|
13
|
+
%li= link_to "New Dashboard", new_dashboard_path
|
14
|
+
%input#search.search.form-control{:placeholder => "Start typing a query or state", :style => "width: 300px; display: inline-block;", :type => "text"}/
|
15
|
+
%table#checks.table
|
16
|
+
%thead
|
17
|
+
%tr
|
18
|
+
%th Query
|
19
|
+
%th{:style => "width: 10%;"} State
|
20
|
+
%th{:style => "width: 10%;"} Run
|
21
|
+
%th{:style => "width: 20%;"} Notify
|
22
|
+
%th{:style => "width: 15%;"}
|
23
|
+
%tbody
|
24
|
+
- @checks.each do |check|
|
25
|
+
%tr
|
26
|
+
%td
|
27
|
+
= link_to check.query.name, check.query
|
28
|
+
%span.text-muted= check.try(:check_type).to_s.gsub("_", " ")
|
29
|
+
%td
|
30
|
+
- if check.state
|
31
|
+
%small{:class => "check-state #{check.state.parameterize.gsub("-", "_")}"}= check.state.upcase
|
32
|
+
%td= check.schedule if check.respond_to?(:schedule)
|
33
|
+
%td
|
34
|
+
%ul.list-unstyled{:style => "margin-bottom: 0; word-break: break-all;"}
|
35
|
+
- check.split_emails.each do |email|
|
36
|
+
%li= email
|
37
|
+
- check.split_slack_channels.each do |channel|
|
38
|
+
%li= channel
|
39
|
+
%td{:style => "text-align: right; padding: 1px;"}
|
40
|
+
= link_to "Edit", edit_check_path(check), class: "btn btn-info"
|
41
|
+
= link_to "Run Now", query_path(check.query), class: "btn btn-primary"
|
42
|
+
:javascript
|
43
|
+
$("#search").on("keyup", function() {
|
44
|
+
var value = $(this).val().toLowerCase()
|
45
|
+
$("#checks tbody tr").filter( function() {
|
46
|
+
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
|
47
|
+
})
|
48
|
+
}).focus()
|
@@ -0,0 +1,64 @@
|
|
1
|
+
= form_for @dashboard, url: (@dashboard.persisted? ? dashboard_path(@dashboard, variable_params) : dashboards_path(variable_params)), html: {id: "app", class: "small-form"} do |f|
|
2
|
+
- if @dashboard.errors.any?
|
3
|
+
.alert.alert-danger= @dashboard.errors.full_messages.first
|
4
|
+
.form-group
|
5
|
+
= f.label :name
|
6
|
+
= f.text_field :name, class: "form-control"
|
7
|
+
.form-group{"v-show" => "queries.length"}
|
8
|
+
= f.label :charts
|
9
|
+
%ul#queries.list-group
|
10
|
+
%li.list-group-item{":key" => "query.id", "v-cloak" => "", "v-for" => "(query, index) in queries"}
|
11
|
+
%span.glyphicon.glyphicon-remove{"aria-hidden" => "true", "v-on:click" => "remove(index)"}
|
12
|
+
{{ query.name }}
|
13
|
+
%input{":value" => "query.id", :name => "query_ids[]", :type => "hidden"}/
|
14
|
+
.form-group{"v-cloak" => ""}
|
15
|
+
= f.label :query_id, "Add Chart"
|
16
|
+
= select_tag :query_id, nil, {include_blank: true, placeholder: "Select chart"}
|
17
|
+
%p{:style => "padding-bottom: 140px;", "v-cloak" => ""}
|
18
|
+
- if @dashboard.persisted?
|
19
|
+
= link_to "Delete", dashboard_path(@dashboard), method: :delete, "data-confirm" => "Are you sure?", class: "btn btn-danger"
|
20
|
+
= f.submit "Save", class: "btn btn-success"
|
21
|
+
= link_to "Back", :back, class: "btn btn-link"
|
22
|
+
:javascript
|
23
|
+
#{blazer_js_var "queries", Blazer::Query.named.order(:name).select("id, name").map { |q| {text: q.name, value: q.id} }}
|
24
|
+
#{blazer_js_var "dashboardQueries", @queries || @dashboard.dashboard_queries.order(:position).map(&:query)}
|
25
|
+
|
26
|
+
var app = new Vue({
|
27
|
+
el: "#app",
|
28
|
+
data: {
|
29
|
+
queries: dashboardQueries
|
30
|
+
},
|
31
|
+
methods: {
|
32
|
+
remove: function(index) {
|
33
|
+
this.queries.splice(index, 1)
|
34
|
+
}
|
35
|
+
},
|
36
|
+
mounted: function() {
|
37
|
+
$("#query_id").selectize({
|
38
|
+
options: queries,
|
39
|
+
highlight: false,
|
40
|
+
maxOptions: 100,
|
41
|
+
onChange: function(val) {
|
42
|
+
if (val) {
|
43
|
+
var item = this.getItem(val)
|
44
|
+
|
45
|
+
// if duplicate query is added, remove the first one
|
46
|
+
for (var i = 0; i < app.queries.length; i++) {
|
47
|
+
if (app.queries[i].id == val) {
|
48
|
+
app.queries.splice(i, 1)
|
49
|
+
break
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
app.queries.push({id: val, name: item.text()})
|
54
|
+
this.setValue("")
|
55
|
+
}
|
56
|
+
}
|
57
|
+
})
|
58
|
+
}
|
59
|
+
})
|
60
|
+
Sortable.create($("#queries").get(0), {
|
61
|
+
onEnd: function(e) {
|
62
|
+
app.queries.splice(e.newIndex, 0, app.queries.splice(e.oldIndex, 1)[0])
|
63
|
+
}
|
64
|
+
})
|
@@ -0,0 +1,33 @@
|
|
1
|
+
- blazer_title @dashboard.name
|
2
|
+
.topbar
|
3
|
+
.container
|
4
|
+
.row{:style => "padding-top: 13px;"}
|
5
|
+
.col-sm-9
|
6
|
+
= render partial: "blazer/nav"
|
7
|
+
%h3{:style => "line-height: 34px; display: inline; margin-left: 5px;"}
|
8
|
+
= @dashboard.name
|
9
|
+
.col-sm-3.text-right
|
10
|
+
= link_to "Edit", edit_dashboard_path(@dashboard, variable_params), class: "btn btn-info"
|
11
|
+
%div{:style => "margin-bottom: 60px;"}
|
12
|
+
- if @data_sources.any? { |ds| ds.cache_mode != "off" }
|
13
|
+
%p.text-muted{:style => "float: right;"}
|
14
|
+
Some queries may be cached
|
15
|
+
\#{link_to "Refresh", refresh_dashboard_path(@dashboard, variable_params), method: :post}
|
16
|
+
- if @bind_vars.any?
|
17
|
+
= render partial: "blazer/variables", locals: {action: dashboard_path(@dashboard)}
|
18
|
+
- else
|
19
|
+
%div{:style => "padding-bottom: 15px;"}
|
20
|
+
- @queries.each_with_index do |query, i|
|
21
|
+
.chart-container
|
22
|
+
%h4= link_to query.friendly_name, query_path(query, variable_params), target: "_blank"
|
23
|
+
.chart{:id => "chart-#{i}"}
|
24
|
+
%p.text-muted Loading...
|
25
|
+
:javascript
|
26
|
+
#{blazer_js_var "data", {statement: query.statement, query_id: query.id, data_source: query.data_source, only_chart: true}}
|
27
|
+
|
28
|
+
runQuery(data, function (data) {
|
29
|
+
$("#chart-#{i}").html(data)
|
30
|
+
$("#chart-#{i} table").stupidtable()
|
31
|
+
}, function (message) {
|
32
|
+
$("#chart-#{i}").addClass("query-error").html(message)
|
33
|
+
});
|
@@ -1,81 +1,56 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
<% if @query.persisted? %>
|
55
|
-
<% dashboards_count = @query.dashboards.count %>
|
56
|
-
<% checks_count = @query.checks.count %>
|
57
|
-
<% words = [] %>
|
58
|
-
<% words << pluralize(dashboards_count, "dashboard") if dashboards_count > 0 %>
|
59
|
-
<% words << pluralize(checks_count, "check") if checks_count > 0 %>
|
60
|
-
<% if words.any? %>
|
61
|
-
<div class="alert alert-info" style="margin-bottom: 0;">
|
62
|
-
Part of <%= words.to_sentence %>. Be careful when editing.
|
63
|
-
</div>
|
64
|
-
<% end %>
|
65
|
-
<% end %>
|
66
|
-
</div>
|
67
|
-
</div>
|
68
|
-
<% end %>
|
69
|
-
|
70
|
-
<div id="results">
|
71
|
-
<p class="text-muted" v-if="running">Loading...</p>
|
72
|
-
<div id="results-html" v-if="!running" :class="{ 'query-error': error }"></div>
|
73
|
-
</div>
|
74
|
-
</div>
|
75
|
-
|
76
|
-
<script>
|
77
|
-
<%= blazer_js_var "params", variable_params %>
|
78
|
-
<%= blazer_js_var "previewStatement", Hash[Blazer.data_sources.map { |k, v| [k, (v.preview_statement rescue "")] }] %>
|
1
|
+
- if @query.errors.any?
|
2
|
+
.alert.alert-danger= @query.errors.full_messages.first
|
3
|
+
#app{"v-cloak" => ""}
|
4
|
+
= form_for @query, url: (@query.persisted? ? query_path(@query, variable_params) : queries_path(variable_params)), html: {autocomplete: "off"} do |f|
|
5
|
+
.row
|
6
|
+
#statement-box.col-xs-8
|
7
|
+
.form-group
|
8
|
+
= f.hidden_field :statement
|
9
|
+
#editor-container
|
10
|
+
#editor{":style" => "{ height: editorHeight }"}= @query.statement
|
11
|
+
.form-group.text-right{:style => "margin-bottom: 8px;"}
|
12
|
+
.pull-left{:style => "margin-top: 8px;"}
|
13
|
+
= link_to "Back", :back
|
14
|
+
%a{":href" => "schemaPath", :style => "margin-left: 40px;", :target => "_blank"} Schema
|
15
|
+
= 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{:style => "display: inline-block; width: 250px; margin-right: 10px;"}
|
17
|
+
%select#table_names{:placeholder => "Preview table", :style => "width: 240px;"}
|
18
|
+
%a.btn.btn-info{:style => "vertical-align: top; width: 70px;", "v-if" => "!running", "v-on:click" => "run"} Run
|
19
|
+
%a.btn.btn-danger{:style => "vertical-align: top; width: 70px;", "v-if" => "running", "v-on:click" => "cancel"} Cancel
|
20
|
+
%hr/
|
21
|
+
= render partial: "tips"
|
22
|
+
.col-xs-4
|
23
|
+
.form-group
|
24
|
+
= f.label :name
|
25
|
+
= f.text_field :name, class: "form-control"
|
26
|
+
.form-group
|
27
|
+
= f.label :description
|
28
|
+
= f.text_area :description, placeholder: "Optional", style: "height: 80px;", class: "form-control"
|
29
|
+
- if @assignees.any?
|
30
|
+
.form-group
|
31
|
+
= f.label :assignees
|
32
|
+
= f.collection_select :assignee_ids, @assignees, :first, :last, {}, { placeholder: "Assignees", style: "height: 80px;", class: "form-control", multiple: true }
|
33
|
+
.form-group.text-right
|
34
|
+
= f.submit "For Enter Press", class: "hide"
|
35
|
+
- if @query.persisted?
|
36
|
+
= link_to "Delete", query_path(@query), method: :delete, "data-confirm" => "Are you sure?", class: "btn btn-danger"
|
37
|
+
= f.submit "Fork", class: "btn btn-info"
|
38
|
+
= f.submit @query.persisted? ? "Update" : "Create", class: "btn btn-success"
|
39
|
+
- if @query.persisted?
|
40
|
+
- dashboards_count = @query.dashboards.count
|
41
|
+
- checks_count = @query.checks.count
|
42
|
+
- words = []
|
43
|
+
- words << pluralize(dashboards_count, "dashboard") if dashboards_count > 0
|
44
|
+
- words << pluralize(checks_count, "check") if checks_count > 0
|
45
|
+
- if words.any?
|
46
|
+
.alert.alert-info{:style => "margin-bottom: 0;"}
|
47
|
+
Part of #{words.to_sentence}. Be careful when editing.
|
48
|
+
#results
|
49
|
+
%p.text-muted{"v-if" => "running"} Loading...
|
50
|
+
#results-html{":class" => "{ 'query-error': error }", "v-if" => "!running"}
|
51
|
+
:javascript
|
52
|
+
#{blazer_js_var "params", variable_params}
|
53
|
+
#{blazer_js_var "previewStatement", Hash[Blazer.data_sources.map { |k, v| [k, (v.preview_statement rescue "")] }]}
|
79
54
|
|
80
55
|
var app = new Vue({
|
81
56
|
el: "#app",
|
@@ -308,7 +283,7 @@
|
|
308
283
|
|
309
284
|
function backupSQL() {
|
310
285
|
$.ajax({
|
311
|
-
url: "
|
286
|
+
url: "#{backup_queries_path}",
|
312
287
|
method: 'POST',
|
313
288
|
data: {
|
314
289
|
sql_query: $('#query_statement').val()
|
@@ -333,5 +308,3 @@
|
|
333
308
|
return false;
|
334
309
|
}
|
335
310
|
});
|
336
|
-
|
337
|
-
</script>
|