mirror of
https://github.com/prymitive/karma
synced 2026-08-23 11:56:20 +00:00
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"browser": true,
|
||||
"jquery": true,
|
||||
"devel": true,
|
||||
|
||||
"undef": true,
|
||||
"unused": true,
|
||||
|
||||
|
||||
"quotmark": "double"
|
||||
}
|
||||
+36
-37
@@ -1,7 +1,12 @@
|
||||
// jshint esversion: 6
|
||||
|
||||
var Alerts = (function() {
|
||||
/* globals LRUMap */ // lru.js
|
||||
/* globals moment */ // moment.js
|
||||
|
||||
/* globals Autocomplete, Colors, Config, Counter, Grid, Templates, Summary, UI, Unsee */
|
||||
|
||||
/* exported Alerts */
|
||||
var Alerts = (function() {
|
||||
|
||||
var silences = {},
|
||||
labelCache = new LRUMap(1000);
|
||||
@@ -12,7 +17,7 @@ var Alerts = (function() {
|
||||
}
|
||||
|
||||
Render() {
|
||||
return Templates.Render('alertGroup', {
|
||||
return Templates.Render("alertGroup", {
|
||||
group: this,
|
||||
silences: silences,
|
||||
static_color_label: Colors.GetStaticLabels(),
|
||||
@@ -22,39 +27,37 @@ var Alerts = (function() {
|
||||
|
||||
// called after group was rendered for the first time
|
||||
Added() {
|
||||
UI.SetupAlertGroupUI($('#' + this.id));
|
||||
UI.SetupAlertGroupUI($("#" + this.id));
|
||||
}
|
||||
|
||||
Update() {
|
||||
// hide popovers in this group
|
||||
$('#' + this.id + ' [data-label-type="filter"]').popover('hide');
|
||||
$("#" + this.id + " [data-label-type='filter']").popover("hide");
|
||||
|
||||
// remove all elements prior to content update to purge all event listeners and hooks
|
||||
$.each($('#' + this.id).find('.panel-body, .panel-heading'), function(i, elem) {
|
||||
$.each($("#" + this.id).find(".panel-body, .panel-heading"), function(i, elem) {
|
||||
$(elem).remove();
|
||||
});
|
||||
|
||||
$('#' + this.id).html($(this.Render()).html());
|
||||
$('#' + this.id).data('hash', this.hash);
|
||||
$("#" + this.id).html($(this.Render()).html());
|
||||
$("#" + this.id).data("hash", this.hash);
|
||||
|
||||
// pulse the badge to show that group content was changed, repeat it twice
|
||||
$('#' + this.id + ' > .panel > .panel-heading > .badge:in-viewport').finish().fadeOut(300).fadeIn(300).fadeOut(300).fadeIn(300);
|
||||
$("#" + this.id + " > .panel > .panel-heading > .badge:in-viewport").finish().fadeOut(300).fadeIn(300).fadeOut(300).fadeIn(300);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
destroyGroup = function(groupID) {
|
||||
$('#' + groupID + ' [data-label-type="filter"]').popover('hide');
|
||||
$('#' + groupID + ' [data-toggle=tooltip]').tooltip('hide');
|
||||
$.each($('#' + groupID).find('.panel-body, .panel-heading'), function(i, elem) {
|
||||
var destroyGroup = function(groupID) {
|
||||
$("#" + groupID + " [data-label-type='filter']").popover("hide");
|
||||
$("#" + groupID + " [data-toggle='tooltip']").tooltip("hide");
|
||||
$.each($("#" + groupID).find(".panel-body, .panel-heading"), function(i, elem) {
|
||||
$(elem).remove();
|
||||
});
|
||||
Grid.Remove($('#' + groupID));
|
||||
Grid.Remove($("#" + groupID));
|
||||
};
|
||||
|
||||
|
||||
sortMapByKey = function(mapToSort) {
|
||||
var sortMapByKey = function(mapToSort) {
|
||||
var keys = Object.keys(mapToSort);
|
||||
keys.sort();
|
||||
var sorted = [];
|
||||
@@ -62,51 +65,48 @@ var Alerts = (function() {
|
||||
sorted.push({
|
||||
key: key,
|
||||
value: mapToSort[key],
|
||||
text: key + ': ' + mapToSort[key]
|
||||
text: key + ": " + mapToSort[key]
|
||||
});
|
||||
});
|
||||
return sorted;
|
||||
};
|
||||
|
||||
|
||||
labelAttrs = function(key, value) {
|
||||
var label = key + ': ' + value;
|
||||
var labelAttrs = function(key, value) {
|
||||
var label = key + ": " + value;
|
||||
|
||||
var attrs = labelCache.get(label);
|
||||
if (attrs !== undefined) return attrs;
|
||||
|
||||
attrs = {
|
||||
text: label,
|
||||
class: 'label label-list ' + Colors.GetClass(key, value),
|
||||
class: "label label-list " + Colors.GetClass(key, value),
|
||||
style: Colors.Get(key, value)
|
||||
};
|
||||
labelCache.set(label, attrs);
|
||||
return attrs;
|
||||
};
|
||||
|
||||
|
||||
humanizeTimestamps = function() {
|
||||
var humanizeTimestamps = function() {
|
||||
var now = moment();
|
||||
// change timestamp labels to be relative
|
||||
$.each($('.label-ts'), function(i, elem) {
|
||||
var ts = moment($(elem).data('ts'), moment.ISO_8601);
|
||||
$.each($(".label-ts"), function(i, elem) {
|
||||
var ts = moment($(elem).data("ts"), moment.ISO_8601);
|
||||
var label = ts.fromNow();
|
||||
$(elem).find('.label-ts-span').text(label);
|
||||
$(elem).attr('data-ts-title', ts.toString());
|
||||
var ts_age = now.diff(ts, 'minutes');
|
||||
$(elem).find(".label-ts-span").text(label);
|
||||
$(elem).attr("data-ts-title", ts.toString());
|
||||
var ts_age = now.diff(ts, "minutes");
|
||||
if (ts_age < 3) {
|
||||
$(elem).addClass('recent-alert').find('.incident-indicator').removeClass('hidden');
|
||||
$(elem).addClass("recent-alert").find(".incident-indicator").removeClass("hidden");
|
||||
} else {
|
||||
$(elem).removeClass('recent-alert').find('.incident-indicator').addClass('hidden');
|
||||
$(elem).removeClass("recent-alert").find(".incident-indicator").addClass("hidden");
|
||||
}
|
||||
});
|
||||
|
||||
// flash recent alerts
|
||||
$('.recent-alert:in-viewport').finish().fadeToggle(300).fadeToggle(300).fadeToggle(300).fadeToggle(300);
|
||||
$(".recent-alert:in-viewport").finish().fadeToggle(300).fadeToggle(300).fadeToggle(300).fadeToggle(300);
|
||||
};
|
||||
|
||||
|
||||
updateAlerts = function(apiResponse) {
|
||||
var updateAlerts = function(apiResponse) {
|
||||
var alertCount = 0;
|
||||
var groups = {};
|
||||
|
||||
@@ -116,7 +116,7 @@ var Alerts = (function() {
|
||||
var summaryData = {};
|
||||
$.each(apiResponse.counters, function(label_key, counters){
|
||||
$.each(counters, function(label_val, hits){
|
||||
summaryData[label_key + ': ' + label_val] = hits;
|
||||
summaryData[label_key + ": " + label_val] = hits;
|
||||
});
|
||||
});
|
||||
Summary.Update(summaryData);
|
||||
@@ -164,7 +164,7 @@ var Alerts = (function() {
|
||||
});
|
||||
// append new groups in chunks
|
||||
if (content.length > 0) {
|
||||
Grid.Append($(content.splice(0, 100).join('\n')));
|
||||
Grid.Append($(content.splice(0, 100).join("\n")));
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
@@ -178,14 +178,13 @@ var Alerts = (function() {
|
||||
if (dirty) {
|
||||
Autocomplete.Reset();
|
||||
Grid.Redraw();
|
||||
if (Config.GetOption('flash').Get()) {
|
||||
if (Config.GetOption("flash").Get()) {
|
||||
Unsee.Flash();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
Update: updateAlerts,
|
||||
SortMapByKey: sortMapByKey,
|
||||
|
||||
@@ -1,54 +1,53 @@
|
||||
var Autocomplete = (function() {
|
||||
/* globals Bloodhound */ // typeahead.js
|
||||
|
||||
/* exported Autocomplete */
|
||||
var Autocomplete = (function() {
|
||||
|
||||
var autocomplete;
|
||||
|
||||
|
||||
init = function() {
|
||||
var init = function() {
|
||||
autocomplete = new Bloodhound({
|
||||
datumTokenizer: Bloodhound.tokenizers.whitespace,
|
||||
queryTokenizer: Bloodhound.tokenizers.whitespace,
|
||||
remote: {
|
||||
url: 'autocomplete.json?term=%QUERY',
|
||||
wildcard: '%QUERY',
|
||||
rateLimitBy: 'throttle',
|
||||
url: "autocomplete.json?term=%QUERY",
|
||||
wildcard: "%QUERY",
|
||||
rateLimitBy: "throttle",
|
||||
rateLimitWait: 300
|
||||
},
|
||||
sufficient: 12
|
||||
});
|
||||
};
|
||||
|
||||
reset = function() {
|
||||
var reset = function() {
|
||||
autocomplete.clear();
|
||||
};
|
||||
|
||||
|
||||
getAutocomplete = function() {
|
||||
var getAutocomplete = function() {
|
||||
return autocomplete;
|
||||
};
|
||||
|
||||
|
||||
// this is used to generate quick filters for label modal
|
||||
generateHints = function(label_key, label_val) {
|
||||
var generateHints = function(label_key, label_val) {
|
||||
var hints = [];
|
||||
if (label_key == '@silenced') {
|
||||
if (label_key == "@silenced") {
|
||||
// static list of hints for @silenced label
|
||||
hints.push('@silenced=true');
|
||||
hints.push('@silenced=false');
|
||||
} else if (label_key == '@inhibited') {
|
||||
hints.push("@silenced=true");
|
||||
hints.push("@silenced=false");
|
||||
} else if (label_key == "@inhibited") {
|
||||
// static list of hints for @inhibited label
|
||||
hints.push('@inhibited=true');
|
||||
hints.push('@inhibited=false');
|
||||
hints.push("@inhibited=true");
|
||||
hints.push("@inhibited=false");
|
||||
} else {
|
||||
// equal and non-equal hints for everything else
|
||||
hints.push(label_key + '=' + label_val);
|
||||
hints.push(label_key + '!=' + label_val);
|
||||
hints.push(label_key + "=" + label_val);
|
||||
hints.push(label_key + "!=" + label_val);
|
||||
|
||||
// if there's space in the label generate regexp hints for partials
|
||||
if (label_val.toString().indexOf(' ') >= 0) {
|
||||
$.each(label_val.toString().split(' '), function(l, label_part){
|
||||
hints.push(label_key + '=~' + label_part);
|
||||
hints.push(label_key + '!~' + label_part);
|
||||
if (label_val.toString().indexOf(" ") >= 0) {
|
||||
$.each(label_val.toString().split(" "), function(l, label_part){
|
||||
hints.push(label_key + "=~" + label_part);
|
||||
hints.push(label_key + "!~" + label_part);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -56,15 +55,14 @@ var Autocomplete = (function() {
|
||||
if ($.isNumeric(label_val)) {
|
||||
var valAsNumber = parseInt(label_val);
|
||||
if (!isNaN(valAsNumber)) {
|
||||
hints.push(label_key + '>' + label_val);
|
||||
hints.push(label_key + '<' + label_val);
|
||||
hints.push(label_key + ">" + label_val);
|
||||
hints.push(label_key + "<" + label_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
return hints;
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
Init: init,
|
||||
Reset: reset,
|
||||
|
||||
+19
-23
@@ -1,57 +1,53 @@
|
||||
/* exported Colors */
|
||||
var Colors = (function() {
|
||||
|
||||
|
||||
var colors,
|
||||
staticColorLabels;
|
||||
|
||||
var specialLabels = {
|
||||
'@silenced: false': 'label-danger',
|
||||
'@silenced: true': 'label-success',
|
||||
'@inhibited: false': 'label-danger',
|
||||
'@inhibited: true': 'label-success'
|
||||
"@silenced: false": "label-danger",
|
||||
"@silenced: true": "label-success",
|
||||
"@inhibited: false": "label-danger",
|
||||
"@inhibited: true": "label-success"
|
||||
};
|
||||
|
||||
|
||||
update = function(colorData) {
|
||||
var update = function(colorData) {
|
||||
colors = colorData;
|
||||
};
|
||||
|
||||
|
||||
getClass = function(key, value) {
|
||||
var label = key + ': ' + value;
|
||||
if (key == 'alertname') {
|
||||
return 'label-primary'; // special case for alertname label, which is the name of alert
|
||||
var getClass = function(key, value) {
|
||||
var label = key + ": " + value;
|
||||
if (key == "alertname") {
|
||||
return "label-primary"; // special case for alertname label, which is the name of alert
|
||||
} else if (specialLabels[label] !== undefined) {
|
||||
return specialLabels[label];
|
||||
} else if (Colors.IsStaticLabel(key)) {
|
||||
return 'label-info';
|
||||
return "label-info";
|
||||
} else {
|
||||
return 'label-warning';
|
||||
return "label-warning";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
getStyle = function(key, value) {
|
||||
var getStyle = function(key, value) {
|
||||
// get color data, returned as css style string
|
||||
var style = "";
|
||||
if (colors[key] !== undefined && colors[key][value] !== undefined) {
|
||||
var c = colors[key][value];
|
||||
style = 'background-color: rgba(' + [c.background.red, c.background.green, c.background.blue, c.background.alpha].join(', ') + '); ';
|
||||
style += 'color: rgba(' + [c.font.red, c.font.green, c.font.blue, c.font.alpha].join(', ') + '); ';
|
||||
style = "background-color: rgba(" + [c.background.red, c.background.green, c.background.blue, c.background.alpha].join(", ") + "); ";
|
||||
style += "color: rgba(" + [c.font.red, c.font.green, c.font.blue, c.font.alpha].join(", ") + "); ";
|
||||
}
|
||||
return style;
|
||||
};
|
||||
|
||||
|
||||
getStaticLabels = function() {
|
||||
return $('#alerts').data('static-color-labels').split(' ');
|
||||
var getStaticLabels = function() {
|
||||
return $("#alerts").data("static-color-labels").split(" ");
|
||||
};
|
||||
|
||||
isStaticLabel = function(key) {
|
||||
var isStaticLabel = function(key) {
|
||||
return ($.inArray(key, Colors.GetStaticLabels()) >= 0);
|
||||
};
|
||||
|
||||
init = function(staticColors) {
|
||||
var init = function(staticColors) {
|
||||
staticColorLabels = staticColors;
|
||||
};
|
||||
|
||||
|
||||
+41
-43
@@ -1,7 +1,12 @@
|
||||
// jshint esversion: 6
|
||||
|
||||
var Option = (function(params) {
|
||||
/* globals Clipboard */ // clipboard.js
|
||||
/* globals Cookies */ // js.cookie.js
|
||||
|
||||
/* globals Filters, Unsee, QueryString */
|
||||
|
||||
/* exported ConfigOption */
|
||||
var ConfigOption = (function() {
|
||||
|
||||
class optionClass {
|
||||
|
||||
@@ -13,12 +18,12 @@ var Option = (function(params) {
|
||||
return $(this.Selector).is(":checked");
|
||||
};
|
||||
this.Set = params.Setter || function(val) {
|
||||
$(this.Selector).bootstrapSwitch('state', $.parseJSON(val), true);
|
||||
$(this.Selector).bootstrapSwitch("state", $.parseJSON(val), true);
|
||||
};
|
||||
this.Action = params.Action || function(val) {};
|
||||
this.Action = params.Action || function() {};
|
||||
this.Init = params.Init || function() {
|
||||
var elem = this;
|
||||
$(this.Selector).on('switchChange.bootstrapSwitch', function(event, val) {
|
||||
$(this.Selector).on("switchChange.bootstrapSwitch", function(event, val) {
|
||||
elem.Save(val);
|
||||
elem.Action(val);
|
||||
});
|
||||
@@ -46,7 +51,7 @@ var Option = (function(params) {
|
||||
Save(val) {
|
||||
Cookies.set(this.Cookie, val, {
|
||||
expires: 365,
|
||||
path: ''
|
||||
path: ""
|
||||
});
|
||||
}
|
||||
|
||||
@@ -58,14 +63,12 @@ var Option = (function(params) {
|
||||
|
||||
}());
|
||||
|
||||
|
||||
/* exported Config */
|
||||
var Config = (function() {
|
||||
|
||||
|
||||
var options = {};
|
||||
|
||||
|
||||
loadFromCookies = function() {
|
||||
var loadFromCookies = function() {
|
||||
$.each(options, function(name, option) {
|
||||
var value = option.Load();
|
||||
if (value !== undefined) {
|
||||
@@ -74,8 +77,7 @@ var Config = (function() {
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
reset = function() {
|
||||
var reset = function() {
|
||||
// this is not part of options map
|
||||
Cookies.remove("defaultFilter.v2");
|
||||
$.each(options, function(name, option) {
|
||||
@@ -83,48 +85,47 @@ var Config = (function() {
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
init = function(params) {
|
||||
var init = function(params) {
|
||||
|
||||
// copy current filter button action
|
||||
new Clipboard(params.CopySelector, {
|
||||
text: function(elem) {
|
||||
var baseUrl = [location.protocol, '//', location.host, location.pathname].join('');
|
||||
var query = ['q=' + Filters.GetFilters().join(',')];
|
||||
var baseUrl = [location.protocol, "//", location.host, location.pathname].join("");
|
||||
var query = ["q=" + Filters.GetFilters().join(",")];
|
||||
$.each(options, function(name, option) {
|
||||
query.push(option.QueryParam + '=' + option.Get().toString());
|
||||
query.push(option.QueryParam + "=" + option.Get().toString());
|
||||
});
|
||||
$(elem).finish().fadeOut(100).fadeIn(300);
|
||||
return baseUrl + '?' + query.join('&');
|
||||
return baseUrl + "?" + query.join("&");
|
||||
}
|
||||
});
|
||||
|
||||
// save settings button action
|
||||
$(params.SaveSelector).on('click', function(elem) {
|
||||
var filter = Filters.GetFilters().join(',');
|
||||
Cookies.set('defaultFilter.v2', filter, {
|
||||
$(params.SaveSelector).on("click", function() {
|
||||
var filter = Filters.GetFilters().join(",");
|
||||
Cookies.set("defaultFilter.v2", filter, {
|
||||
expires: 365,
|
||||
path: ''
|
||||
path: ""
|
||||
});
|
||||
$(params.SaveSelector).finish().fadeOut(100).fadeIn(300);
|
||||
});
|
||||
|
||||
// reset settings button action
|
||||
$(params.ResetSelector).on('click', function(elem) {
|
||||
$(params.ResetSelector).on("click", function() {
|
||||
Config.Reset();
|
||||
QueryString.Remove('q');
|
||||
QueryString.Remove("q");
|
||||
location.reload();
|
||||
});
|
||||
|
||||
// https://github.com/twbs/bootstrap/issues/2097
|
||||
$(document).on('click', '.dropdown-menu.dropdown-menu-form', function(e) {
|
||||
$(document).on("click", ".dropdown-menu.dropdown-menu-form", function(e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
Config.NewOption({
|
||||
Cookie: 'autoRefresh',
|
||||
QueryParam: 'autorefresh',
|
||||
Selector: '#autorefresh',
|
||||
Cookie: "autoRefresh",
|
||||
QueryParam: "autorefresh",
|
||||
Selector: "#autorefresh",
|
||||
Action: function(val) {
|
||||
if (val) {
|
||||
Unsee.WaitForNextReload();
|
||||
@@ -135,12 +136,12 @@ var Config = (function() {
|
||||
});
|
||||
|
||||
Config.NewOption({
|
||||
Cookie: 'refreshInterval',
|
||||
QueryParam: 'refresh',
|
||||
Selector: '#refresh-interval',
|
||||
Cookie: "refreshInterval",
|
||||
QueryParam: "refresh",
|
||||
Selector: "#refresh-interval",
|
||||
Init: function() {
|
||||
var elem = this;
|
||||
$(this.Selector).on('change', function() {
|
||||
$(this.Selector).on("change", function() {
|
||||
var val = elem.Get();
|
||||
elem.Save(val);
|
||||
elem.Action(val);
|
||||
@@ -159,32 +160,29 @@ var Config = (function() {
|
||||
|
||||
|
||||
Config.NewOption({
|
||||
Cookie: 'showFlash',
|
||||
QueryParam: 'flash',
|
||||
Selector: '#show-flash'
|
||||
Cookie: "showFlash",
|
||||
QueryParam: "flash",
|
||||
Selector: "#show-flash"
|
||||
});
|
||||
|
||||
Config.NewOption({
|
||||
Cookie: 'appendTop',
|
||||
QueryParam: 'appendtop',
|
||||
Selector: '#append-top'
|
||||
Cookie: "appendTop",
|
||||
QueryParam: "appendtop",
|
||||
Selector: "#append-top"
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
|
||||
newOption = function(params) {
|
||||
var option = new Option.New(params);
|
||||
var newOption = function(params) {
|
||||
var option = new ConfigOption.New(params);
|
||||
option.Init();
|
||||
options[option.QueryParam] = option;
|
||||
};
|
||||
|
||||
|
||||
getOption = function(queryParam) {
|
||||
var getOption = function(queryParam) {
|
||||
return options[queryParam];
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
Init: init,
|
||||
Load: loadFromCookies,
|
||||
|
||||
+25
-32
@@ -1,75 +1,68 @@
|
||||
var Counter = (function(params) {
|
||||
/* globals Favico */ // favico.js
|
||||
|
||||
/* exported Counter */
|
||||
var Counter = (function() {
|
||||
|
||||
var selectors = {
|
||||
counter: '#alert-count',
|
||||
spinner: '#spinner'
|
||||
counter: "#alert-count",
|
||||
spinner: "#spinner"
|
||||
};
|
||||
|
||||
|
||||
var favicon = false;
|
||||
|
||||
|
||||
setCounter = function(val) {
|
||||
var setCounter = function(val) {
|
||||
favicon.badge(val);
|
||||
Counter.Show();
|
||||
$(selectors.counter).html(val);
|
||||
// set alert count css based on the number of alerts
|
||||
if (val === 0) {
|
||||
$(selectors.counter).removeClass('text-warning text-danger').addClass('text-success');
|
||||
$(selectors.counter).removeClass("text-warning text-danger").addClass("text-success");
|
||||
document.title = "(◕‿◕)";
|
||||
} else if (val < 10) {
|
||||
$(selectors.counter).removeClass('text-success text-danger').addClass('text-warning');
|
||||
$(selectors.counter).removeClass("text-success text-danger").addClass("text-warning");
|
||||
document.title = "(◕_◕)";
|
||||
} else {
|
||||
$(selectors.counter).removeClass('text-success text-warning').addClass('text-danger');
|
||||
$(selectors.counter).removeClass("text-success text-warning").addClass("text-danger");
|
||||
document.title = "(◕︵◕)";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
setUnknown = function() {
|
||||
favicon.badge('?');
|
||||
var setUnknown = function() {
|
||||
favicon.badge("?");
|
||||
Counter.Show();
|
||||
$(selectors.counter).html('?');
|
||||
$(selectors.counter).removeClass('text-success text-warning text-danger');
|
||||
$(selectors.counter).html("?");
|
||||
$(selectors.counter).removeClass("text-success text-warning text-danger");
|
||||
};
|
||||
|
||||
|
||||
hide = function() {
|
||||
var hide = function() {
|
||||
$(selectors.counter).hide();
|
||||
$(selectors.spinner).children().removeClass('spinner-success spinner-error');
|
||||
$(selectors.spinner).children().removeClass("spinner-success spinner-error");
|
||||
$(selectors.spinner).show();
|
||||
};
|
||||
|
||||
|
||||
show = function() {
|
||||
var show = function() {
|
||||
$(selectors.spinner).hide();
|
||||
$(selectors.counter).show();
|
||||
};
|
||||
|
||||
|
||||
markError = function() {
|
||||
$(selectors.spinner).children().removeClass('spinner-success').addClass('spinner-error');
|
||||
var markError = function() {
|
||||
$(selectors.spinner).children().removeClass("spinner-success").addClass("spinner-error");
|
||||
};
|
||||
|
||||
|
||||
markSuccess = function() {
|
||||
$(selectors.spinner).children().addClass('spinner-success');
|
||||
var markSuccess = function() {
|
||||
$(selectors.spinner).children().addClass("spinner-success");
|
||||
};
|
||||
|
||||
|
||||
init = function() {
|
||||
var init = function() {
|
||||
favicon = new Favico({
|
||||
animation: 'none',
|
||||
position: 'up',
|
||||
bgColor: '#333',
|
||||
textColor: '#ff0'
|
||||
animation: "none",
|
||||
position: "up",
|
||||
bgColor: "#333",
|
||||
textColor: "#ff0"
|
||||
});
|
||||
Counter.Unknown();
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
Init: init,
|
||||
Set: setCounter,
|
||||
|
||||
+49
-56
@@ -1,143 +1,137 @@
|
||||
/* globals sha1 */ // sha1.js
|
||||
|
||||
/* globals Autocomplete, Cookies, QueryString, Unsee */
|
||||
|
||||
/* exported Filters */
|
||||
var Filters = (function() {
|
||||
|
||||
|
||||
selectors = {
|
||||
filter: '#filter',
|
||||
icon: '#filter-icon'
|
||||
var selectors = {
|
||||
filter: "#filter",
|
||||
icon: "#filter-icon"
|
||||
};
|
||||
|
||||
|
||||
addBadge = function(text) {
|
||||
$.each($('span.tag'), function(i, tag) {
|
||||
var addBadge = function(text) {
|
||||
$.each($("span.tag"), function(i, tag) {
|
||||
if ($(tag).text() == text) {
|
||||
var chksum = sha1(text);
|
||||
$(tag).prepend('<span class="badge tag-badge" id="tag-counter-' + chksum + '" data-badge-id="' + chksum + '"></span>');
|
||||
$(tag).prepend("<span class='badge tag-badge' id='tag-counter-" + chksum + "' data-badge-id='" + chksum + "'></span>");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
update = function() {
|
||||
var update = function() {
|
||||
Filters.Updating();
|
||||
|
||||
// update location so it's easy to share it
|
||||
QueryString.Set('q', Filters.GetFilters().join(','));
|
||||
QueryString.Set("q", Filters.GetFilters().join(","));
|
||||
|
||||
// reload alerts
|
||||
Unsee.Reload();
|
||||
};
|
||||
|
||||
|
||||
init = function() {
|
||||
var init = function() {
|
||||
var initial_filter;
|
||||
|
||||
if ($(selectors.filter).data('default-used') == 'false' || $(selectors.filter).data('default-used') === false) {
|
||||
if ($(selectors.filter).data("default-used") == "false" || $(selectors.filter).data("default-used") === false) {
|
||||
// user passed ?q=filter string
|
||||
initial_filter = $(selectors.filter).val();
|
||||
} else {
|
||||
// no ?q=filter string, check if we have default filter cookie
|
||||
initial_filter = Cookies.get('defaultFilter.v2');
|
||||
initial_filter = Cookies.get("defaultFilter.v2");
|
||||
if (initial_filter === undefined) {
|
||||
// no cookie, use global default
|
||||
initial_filter = $(selectors.filter).data('default-filter');
|
||||
initial_filter = $(selectors.filter).data("default-filter");
|
||||
}
|
||||
}
|
||||
|
||||
var initial_filter_arr = initial_filter.split(',');
|
||||
$(selectors.filter).val('');
|
||||
$('.filterbar :input').tagsinput({
|
||||
var initial_filter_arr = initial_filter.split(",");
|
||||
$(selectors.filter).val("");
|
||||
$(".filterbar :input").tagsinput({
|
||||
typeaheadjs: {
|
||||
minLength: 1,
|
||||
hint: true,
|
||||
limit: 12,
|
||||
name: 'autocomplete',
|
||||
name: "autocomplete",
|
||||
source: Autocomplete.Autocomplete()
|
||||
}
|
||||
});
|
||||
$.each(initial_filter_arr, function(i, filter) {
|
||||
$(selectors.filter).tagsinput('add', filter);
|
||||
$(selectors.filter).tagsinput("add", filter);
|
||||
addBadge(filter);
|
||||
});
|
||||
|
||||
$(selectors.filter).on('itemAdded itemRemoved', function(event) {
|
||||
$(selectors.filter).on("itemAdded itemRemoved", function(event) {
|
||||
Filters.SetFilters();
|
||||
// add counter badge to new tag
|
||||
if (event.type == 'itemAdded') {
|
||||
if (event.type == "itemAdded") {
|
||||
addBadge(event.item);
|
||||
}
|
||||
});
|
||||
|
||||
$(selectors.filter).tagsinput('focus');
|
||||
$(selectors.filter).tagsinput("focus");
|
||||
|
||||
// stop when user is typing in the filter bar
|
||||
$('.bootstrap-tagsinput').typing({
|
||||
start: function(event, elem) {
|
||||
$(".bootstrap-tagsinput").typing({
|
||||
start: function(event) {
|
||||
if (event.keyCode != 8 && event.keyCode != 13) Unsee.Pause();
|
||||
},
|
||||
stop: function(event, elem) {
|
||||
stop: function(event) {
|
||||
if (event.keyCode != 8 && event.keyCode != 13) Unsee.WaitForNextReload();
|
||||
},
|
||||
delay: 1000
|
||||
});
|
||||
|
||||
// fix body padding if needed, input might endup using more than 1 line
|
||||
$('.bootstrap-tagsinput').bind("DOMSubtreeModified", function() {
|
||||
$('body').css('padding-top', $('.navbar').height());
|
||||
$(".bootstrap-tagsinput").bind("DOMSubtreeModified", function() {
|
||||
$("body").css("padding-top", $(".navbar").height());
|
||||
});
|
||||
$('input.tt-input').on("change keypress", function() {
|
||||
$('body').css('padding-top', $('.navbar').height());
|
||||
$("input.tt-input").on("change keypress", function() {
|
||||
$("body").css("padding-top", $(".navbar").height());
|
||||
});
|
||||
|
||||
$('.filterbar').on('resize', function(){
|
||||
$(".filterbar").on("resize", function(){
|
||||
// hack for fixing padding since input can grow and change height
|
||||
$('body').css('padding-top', $('.navbar').height());
|
||||
$("body").css("padding-top", $(".navbar").height());
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
|
||||
getFilters = function() {
|
||||
return $(selectors.filter).tagsinput('items');
|
||||
var getFilters = function() {
|
||||
return $(selectors.filter).tagsinput("items");
|
||||
};
|
||||
|
||||
|
||||
reloadBadges = function(filterData) {
|
||||
var reloadBadges = function(filterData) {
|
||||
$.each(filterData, function(i, filter) {
|
||||
$.each($('span.tag-badge'), function(j, tag) {
|
||||
if (sha1(filter.text) == $(tag).data('badge-id')) {
|
||||
$.each($("span.tag-badge"), function(j, tag) {
|
||||
if (sha1(filter.text) == $(tag).data("badge-id")) {
|
||||
$(tag).html(filter.hits.toString());
|
||||
if (filter.isValid === true) {
|
||||
$(tag).parent().addClass('label-info').removeClass('label-danger');
|
||||
$(tag).parent().addClass("label-info").removeClass("label-danger");
|
||||
} else {
|
||||
$(tag).parent().addClass('label-danger').removeClass('label-info');
|
||||
$(tag).parent().addClass("label-danger").removeClass("label-info");
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
addFilter = function(text) {
|
||||
$(selectors.filter).tagsinput('add', text);
|
||||
var addFilter = function(text) {
|
||||
$(selectors.filter).tagsinput("add", text);
|
||||
};
|
||||
|
||||
|
||||
setUpdating = function() {
|
||||
var setUpdating = function() {
|
||||
// visual hint that alerts are reloaded due to filter change
|
||||
$(selectors.icon).removeClass('fa-search fa-pause').addClass('fa-circle-o-notch fa-spin');
|
||||
$(selectors.icon).removeClass("fa-search fa-pause").addClass("fa-circle-o-notch fa-spin");
|
||||
};
|
||||
|
||||
|
||||
updateDone = function() {
|
||||
$(selectors.icon).removeClass('fa-circle-o-notch fa-spin fa-pause').addClass('fa-search');
|
||||
var updateDone = function() {
|
||||
$(selectors.icon).removeClass("fa-circle-o-notch fa-spin fa-pause").addClass("fa-search");
|
||||
};
|
||||
|
||||
|
||||
setPause = function() {
|
||||
$(selectors.icon).removeClass('fa-circle-o-notch fa-spin fa-search').addClass('fa-pause');
|
||||
var setPause = function() {
|
||||
$(selectors.icon).removeClass("fa-circle-o-notch fa-spin fa-search").addClass("fa-pause");
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
Init: init,
|
||||
AddFilter: addFilter,
|
||||
@@ -149,5 +143,4 @@ var Filters = (function() {
|
||||
Pause: setPause
|
||||
};
|
||||
|
||||
|
||||
}());
|
||||
|
||||
+22
-29
@@ -1,21 +1,22 @@
|
||||
var Grid = (function(params) {
|
||||
/* globals Config */
|
||||
|
||||
/* exported Grid */
|
||||
var Grid = (function() {
|
||||
|
||||
var selectors = {
|
||||
alerts: '#alerts',
|
||||
incident: '.incident',
|
||||
gridSizer: '.grid-sizer',
|
||||
alerts: "#alerts",
|
||||
incident: ".incident",
|
||||
gridSizer: ".grid-sizer",
|
||||
};
|
||||
|
||||
var grid;
|
||||
|
||||
|
||||
init = function() {
|
||||
var init = function() {
|
||||
grid = $(selectors.alerts).masonry({
|
||||
itemSelector: selectors.incident,
|
||||
columnWidth: selectors.gridSizer,
|
||||
percentPosition: true,
|
||||
transitionDuration: '0.4s',
|
||||
transitionDuration: "0.4s",
|
||||
hiddenStyle: {
|
||||
opacity: 0
|
||||
},
|
||||
@@ -25,46 +26,38 @@ var Grid = (function(params) {
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
clear = function() {
|
||||
grid.masonry('remove', $(selectors.incident));
|
||||
var clear = function() {
|
||||
grid.masonry("remove", $(selectors.incident));
|
||||
};
|
||||
|
||||
|
||||
redraw = function() {
|
||||
grid.masonry('layout');
|
||||
var redraw = function() {
|
||||
grid.masonry("layout");
|
||||
};
|
||||
|
||||
|
||||
remove = function(elem) {
|
||||
grid.masonry('remove', elem);
|
||||
var remove = function(elem) {
|
||||
grid.masonry("remove", elem);
|
||||
};
|
||||
|
||||
|
||||
append = function(elem) {
|
||||
if (Config.GetOption('appendtop').Get()) {
|
||||
grid.prepend(elem).masonry('prepended', elem);
|
||||
var append = function(elem) {
|
||||
if (Config.GetOption("appendtop").Get()) {
|
||||
grid.prepend(elem).masonry("prepended", elem);
|
||||
} else {
|
||||
grid.append(elem).masonry('appended', elem);
|
||||
grid.append(elem).masonry("appended", elem);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
items = function() {
|
||||
return grid.masonry('getItemElements');
|
||||
var items = function() {
|
||||
return grid.masonry("getItemElements");
|
||||
};
|
||||
|
||||
|
||||
hide = function() {
|
||||
var hide = function() {
|
||||
$(selectors.alerts).hide();
|
||||
};
|
||||
|
||||
|
||||
show = function() {
|
||||
var show = function() {
|
||||
$(selectors.alerts).show();
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
Init: init,
|
||||
Clear: clear,
|
||||
|
||||
+11
-13
@@ -1,39 +1,38 @@
|
||||
var Progress = (function() {
|
||||
/* globals NProgress */ // nprogress.js
|
||||
|
||||
/* globals Unsee */
|
||||
|
||||
/* exported Progress */
|
||||
var Progress = (function() {
|
||||
|
||||
var timer;
|
||||
|
||||
|
||||
init = function() {
|
||||
var init = function() {
|
||||
NProgress.configure({
|
||||
minimum: 0.01,
|
||||
showSpinner: false,
|
||||
easing: 'linear'
|
||||
easing: "linear"
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
resetTimer = function() {
|
||||
var resetTimer = function() {
|
||||
if (timer !== false) {
|
||||
clearInterval(timer);
|
||||
timer = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
complete = function() {
|
||||
var complete = function() {
|
||||
Progress.ResetTimer();
|
||||
NProgress.done();
|
||||
};
|
||||
|
||||
|
||||
pause = function() {
|
||||
var pause = function() {
|
||||
Progress.ResetTimer();
|
||||
NProgress.set(0.0);
|
||||
};
|
||||
|
||||
|
||||
start = function() {
|
||||
var start = function() {
|
||||
var step_ms = 250; // animation step in ms
|
||||
var steps = (Unsee.GetRefreshRate() * 1000) / step_ms; // how many steps we have
|
||||
NProgress.set(0.0);
|
||||
@@ -43,7 +42,6 @@ var Progress = (function() {
|
||||
}, step_ms);
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
Init: init,
|
||||
Pause: pause,
|
||||
|
||||
@@ -1,45 +1,43 @@
|
||||
/* exported QueryString */
|
||||
var QueryString = (function() {
|
||||
|
||||
|
||||
parse = function() {
|
||||
var parse = function() {
|
||||
var vars = [],
|
||||
hash;
|
||||
var q = document.URL.split('?')[1];
|
||||
var q = document.URL.split("?")[1];
|
||||
if (q !== undefined) {
|
||||
q = q.split('&');
|
||||
q = q.split("&");
|
||||
for (var i = 0; i < q.length; i++) {
|
||||
hash = q[i].split('=');
|
||||
vars[hash[0]] = hash.slice(1).join('=');
|
||||
hash = q[i].split("=");
|
||||
vars[hash[0]] = hash.slice(1).join("=");
|
||||
}
|
||||
}
|
||||
return vars;
|
||||
};
|
||||
|
||||
|
||||
update = function(key, value) {
|
||||
var update = function(key, value) {
|
||||
/* https://gist.github.com/excalq/2961415 */
|
||||
var baseUrl = [location.protocol, '//', location.host, location.pathname].join(''),
|
||||
var baseUrl = [location.protocol, "//", location.host, location.pathname].join(""),
|
||||
urlQueryString = document.location.search,
|
||||
newParam = key + '=' + value,
|
||||
params = '?' + newParam;
|
||||
newParam = key + "=" + value,
|
||||
params = "?" + newParam;
|
||||
|
||||
// If the "search" string exists, then build params from it
|
||||
if (urlQueryString) {
|
||||
keyRegex = new RegExp('([\?&])' + key + '[^&]*');
|
||||
var keyRegex = new RegExp("([\?&])" + key + "[^&]*");
|
||||
|
||||
// If param exists already, update it
|
||||
if (urlQueryString.match(keyRegex) !== null) {
|
||||
params = urlQueryString.replace(keyRegex, "$1" + newParam);
|
||||
} else { // Otherwise, add it to end of query string
|
||||
params = urlQueryString + '&' + newParam;
|
||||
params = urlQueryString + "&" + newParam;
|
||||
}
|
||||
}
|
||||
window.history.replaceState({}, "", baseUrl + params);
|
||||
};
|
||||
|
||||
|
||||
remove = function(key) {
|
||||
var baseUrl = [location.protocol, '//', location.host, location.pathname].join(''),
|
||||
var remove = function(key) {
|
||||
var baseUrl = [location.protocol, "//", location.host, location.pathname].join(""),
|
||||
q = QueryString.Parse();
|
||||
if (q[key] !== undefined) {
|
||||
delete q[key];
|
||||
@@ -47,7 +45,6 @@ var QueryString = (function() {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
Parse: parse,
|
||||
Set: update,
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
var Sentry = (function() {
|
||||
/* globals Raven */ // raven.js
|
||||
|
||||
(function() {
|
||||
|
||||
// init sentry client if sentry dsn is set
|
||||
if ($("body").data("raven-dsn")) {
|
||||
|
||||
+21
-24
@@ -1,9 +1,11 @@
|
||||
/* globals Colors, Templates */
|
||||
|
||||
/* exported Summary */
|
||||
var Summary = (function() {
|
||||
|
||||
var summary;
|
||||
|
||||
var summary, templates;
|
||||
|
||||
render = function() {
|
||||
var render = function() {
|
||||
var top_tags = [];
|
||||
$.each(summary, function(k, v) {
|
||||
top_tags.push({
|
||||
@@ -21,48 +23,44 @@ var Summary = (function() {
|
||||
|
||||
var tags = [];
|
||||
$.each(top_tags.slice(0, 10), function(i, tag) {
|
||||
var label_key = tag.name.split(': ')[0];
|
||||
var label_val = tag.name.split(': ')[1];
|
||||
var label_key = tag.name.split(": ")[0];
|
||||
var label_val = tag.name.split(": ")[1];
|
||||
tag.style = Colors.Get(label_key, label_val);
|
||||
tag.cls = Colors.GetClass(label_key, label_val);
|
||||
tags.push(tag);
|
||||
});
|
||||
|
||||
return Templates.Render('breakdownContent', {tags: tags});
|
||||
return Templates.Render("breakdownContent", {tags: tags});
|
||||
};
|
||||
|
||||
|
||||
init = function() {
|
||||
var init = function() {
|
||||
summary = {};
|
||||
$('.navbar-header').popover({
|
||||
trigger: 'hover',
|
||||
$(".navbar-header").popover({
|
||||
trigger: "hover",
|
||||
delay: {
|
||||
"show": 500,
|
||||
"hide": 100
|
||||
},
|
||||
container: 'body',
|
||||
container: "body",
|
||||
html: true,
|
||||
placement: 'bottom',
|
||||
title: 'Top labels',
|
||||
placement: "bottom",
|
||||
title: "Top labels",
|
||||
content: render,
|
||||
template: Templates.Render('breakdown', {})
|
||||
template: Templates.Render("breakdown", {})
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
update = function(data) {
|
||||
var update = function(data) {
|
||||
summary = data;
|
||||
};
|
||||
|
||||
|
||||
reset = function() {
|
||||
var reset = function() {
|
||||
summary = {};
|
||||
render();
|
||||
};
|
||||
|
||||
|
||||
push = function(labelKey, labelVal) {
|
||||
var l = labelKey + ': ' + labelVal;
|
||||
var push = function(labelKey, labelVal) {
|
||||
var l = labelKey + ": " + labelVal;
|
||||
if (summary[l] === undefined) {
|
||||
summary[l] = 1;
|
||||
} else {
|
||||
@@ -70,12 +68,11 @@ var Summary = (function() {
|
||||
}
|
||||
};
|
||||
|
||||
getCount = function(labelKey, labelVal) {
|
||||
var l = labelKey + ': ' + labelVal;
|
||||
var getCount = function(labelKey, labelVal) {
|
||||
var l = labelKey + ": " + labelVal;
|
||||
return summary[l];
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
Init: init,
|
||||
Update: update,
|
||||
|
||||
+30
-31
@@ -1,71 +1,70 @@
|
||||
var Templates = (function(params) {
|
||||
/* globals _ */ // underscore.js
|
||||
|
||||
/* exported Templates */
|
||||
var Templates = (function() {
|
||||
|
||||
var templates = {},
|
||||
config = {
|
||||
// popover with the list of most common labels
|
||||
breakdown: '#breakdown',
|
||||
breakdownContent: '#breakdown-content',
|
||||
breakdown: "#breakdown",
|
||||
breakdownContent: "#breakdown-content",
|
||||
|
||||
// reload message if backend version bump is detected
|
||||
reloadNeeded: '#reload-needed',
|
||||
reloadNeeded: "#reload-needed",
|
||||
|
||||
// errors
|
||||
fatalError: '#fatal-error',
|
||||
internalError: '#internal-error',
|
||||
updateError: '#update-error',
|
||||
fatalError: "#fatal-error",
|
||||
internalError: "#internal-error",
|
||||
updateError: "#update-error",
|
||||
|
||||
// modal popup with label filters
|
||||
modalTitle: '#modal-title',
|
||||
modalBody: '#modal-body',
|
||||
modalTitle: "#modal-title",
|
||||
modalBody: "#modal-body",
|
||||
|
||||
// modal popup with silence form
|
||||
silenceForm: '#silence-form',
|
||||
silenceFormSuccess: '#silence-form-success',
|
||||
silenceFormError: '#silence-form-error',
|
||||
silenceFormFatal: '#silence-form-fatal',
|
||||
silenceFormLoading: '#silence-form-loading',
|
||||
silenceForm: "#silence-form",
|
||||
silenceFormSuccess: "#silence-form-success",
|
||||
silenceFormError: "#silence-form-error",
|
||||
silenceFormFatal: "#silence-form-fatal",
|
||||
silenceFormLoading: "#silence-form-loading",
|
||||
|
||||
// label button
|
||||
buttonLabel: '#label-button-filter',
|
||||
buttonLabel: "#label-button-filter",
|
||||
|
||||
// alert group
|
||||
alertGroup: '#alert-group',
|
||||
alertGroupTitle: '#alert-group-title',
|
||||
alertGroupAnnotations: '#alert-group-annotations',
|
||||
alertGroupLabels: '#alert-group-labels',
|
||||
alertGroupElements: '#alert-group-elements',
|
||||
alertGroupSilence: '#alert-group-silence',
|
||||
alertGroupLabelMap: '#alert-group-label-map'
|
||||
alertGroup: "#alert-group",
|
||||
alertGroupTitle: "#alert-group-title",
|
||||
alertGroupAnnotations: "#alert-group-annotations",
|
||||
alertGroupLabels: "#alert-group-labels",
|
||||
alertGroupElements: "#alert-group-elements",
|
||||
alertGroupSilence: "#alert-group-silence",
|
||||
alertGroupLabelMap: "#alert-group-label-map"
|
||||
};
|
||||
|
||||
|
||||
init = function() {
|
||||
var init = function() {
|
||||
$.each(config, function(name, selector) {
|
||||
try {
|
||||
templates[name] = _.template($(selector).html());
|
||||
} catch (err) {
|
||||
console.error('Failed to parse template ' + name + ' ' + selector);
|
||||
console.error("Failed to parse template " + name + " " + selector);
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
renderTemplate = function(name, context) {
|
||||
var renderTemplate = function(name, context) {
|
||||
var t = templates[name];
|
||||
if (t === undefined) {
|
||||
console.error('Unknown template ' + name);
|
||||
return '<div class="jumbotron"><h1>Internal error: unknown template ' + name + '</h1></div>';
|
||||
console.error("Unknown template " + name);
|
||||
return "<div class='jumbotron'><h1>Internal error: unknown template " + name + "</h1></div>";
|
||||
}
|
||||
try {
|
||||
return t(context);
|
||||
} catch (err) {
|
||||
return '<div class="jumbotron">Failed to render template "' + name + '"<h1><p>' + err + '</p></h1></div>';
|
||||
return "<div class='jumbotron'>Failed to render template " + name + "<h1><p>" + err + "</p></h1></div>";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
Init: init,
|
||||
Render: renderTemplate
|
||||
|
||||
+72
-78
@@ -1,9 +1,13 @@
|
||||
var UI = (function(params) {
|
||||
/* globals moment */ // moment.js
|
||||
|
||||
/* globals Alerts, Autocomplete, Filters, Summary, Templates, Unsee */
|
||||
|
||||
/* exported UI */
|
||||
var UI = (function() {
|
||||
|
||||
// when user click on any alert label modal popup with a list of possible
|
||||
// filter will show, this function is used to setup that modal
|
||||
setupModal = function() {
|
||||
var setupModal = function() {
|
||||
$("#labelModal").on("show.bs.modal", function(event) {
|
||||
Unsee.Pause();
|
||||
var modal = $(this);
|
||||
@@ -28,7 +32,7 @@ var UI = (function(params) {
|
||||
Filters.AddFilter(filter);
|
||||
});
|
||||
});
|
||||
$("#labelModal").on("hidden.bs.modal", function(event) {
|
||||
$("#labelModal").on("hidden.bs.modal", function() {
|
||||
var modal = $(this);
|
||||
modal.find(".modal-title").children().remove();
|
||||
modal.find(".modal-body").children().remove();
|
||||
@@ -36,10 +40,9 @@ var UI = (function(params) {
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// each alert group have a link generated for it, but we hide it until
|
||||
// user hovers over that group so it doesn"t trash the UI
|
||||
setupGroupLinkHover = function(elem) {
|
||||
var setupGroupLinkHover = function(elem) {
|
||||
$(elem).on("mouseenter", function() {
|
||||
$(this).find(".alert-group-link > a").finish().animate({
|
||||
opacity: 100
|
||||
@@ -52,10 +55,9 @@ var UI = (function(params) {
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// find all elements inside alert group panel that will use tooltips
|
||||
// and setup those
|
||||
setupGroupTooltips = function(groupElem) {
|
||||
var setupGroupTooltips = function(groupElem) {
|
||||
$.each(groupElem.find("[data-toggle=tooltip]"), function(i, elem) {
|
||||
$(elem).tooltip({
|
||||
animation: false, // slows down tooltip removal
|
||||
@@ -69,20 +71,17 @@ var UI = (function(params) {
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
setupAlertGroupUI = function(elem) {
|
||||
var setupAlertGroupUI = function(elem) {
|
||||
setupGroupLinkHover(elem);
|
||||
setupGroupTooltips(elem);
|
||||
};
|
||||
|
||||
|
||||
init = function() {
|
||||
var init = function() {
|
||||
setupModal();
|
||||
setupSilenceForm();
|
||||
};
|
||||
|
||||
|
||||
silenceFormData = function() {
|
||||
var silenceFormData = function() {
|
||||
var values = $("#newSilenceForm").serializeArray();
|
||||
var payload = {
|
||||
matchers: [],
|
||||
@@ -98,18 +97,18 @@ var UI = (function(params) {
|
||||
break;
|
||||
}
|
||||
});
|
||||
if ($("#startsAt").data('DateTimePicker')) {
|
||||
payload.startsAt = $("#startsAt").data('DateTimePicker').date();
|
||||
if ($("#startsAt").data("DateTimePicker")) {
|
||||
payload.startsAt = $("#startsAt").data("DateTimePicker").date();
|
||||
}
|
||||
if ($("#endsAt").data('DateTimePicker')) {
|
||||
payload.endsAt = $("#endsAt").data('DateTimePicker').date();
|
||||
if ($("#endsAt").data("DateTimePicker")) {
|
||||
payload.endsAt = $("#endsAt").data("DateTimePicker").date();
|
||||
}
|
||||
$.each($("#newSilenceForm .selectpicker"), function(i, elem) {
|
||||
var label_key = $(elem).data('label-key');
|
||||
var values = $(elem).selectpicker('val');
|
||||
var label_key = $(elem).data("label-key");
|
||||
var values = $(elem).selectpicker("val");
|
||||
if (values && values.length > 0) {
|
||||
var pval;
|
||||
isRegex = false;
|
||||
var isRegex = false;
|
||||
if (values.length > 1) {
|
||||
pval = "^(?:" + values.join("|") + ")$";
|
||||
isRegex = true;
|
||||
@@ -126,17 +125,16 @@ var UI = (function(params) {
|
||||
return payload;
|
||||
};
|
||||
|
||||
|
||||
silenceFormCalculateDuration = function() {
|
||||
var silenceFormCalculateDuration = function() {
|
||||
// skip if datetimepicker isn't ready yet
|
||||
if (!$("#startsAt").data('DateTimePicker') || !$("#endsAt").data('DateTimePicker')) return false;
|
||||
if (!$("#startsAt").data("DateTimePicker") || !$("#endsAt").data("DateTimePicker")) return false;
|
||||
|
||||
var startsAt = $("#startsAt").data('DateTimePicker').date();
|
||||
var endsAt = $("#endsAt").data('DateTimePicker').date();
|
||||
var startsAt = $("#startsAt").data("DateTimePicker").date();
|
||||
var endsAt = $("#endsAt").data("DateTimePicker").date();
|
||||
|
||||
var totalDays = (endsAt.diff(startsAt, 'days'));
|
||||
var totalHours = (endsAt.diff(startsAt, 'hours')) % 24;
|
||||
var totalMinutes = endsAt.diff(startsAt, 'minutes') % 60;
|
||||
var totalDays = (endsAt.diff(startsAt, "days"));
|
||||
var totalHours = (endsAt.diff(startsAt, "hours")) % 24;
|
||||
var totalMinutes = endsAt.diff(startsAt, "minutes") % 60;
|
||||
$("#silence-duration-days").html(totalDays);
|
||||
$("#silence-duration-hours").html(totalHours);
|
||||
$("#silence-duration-minutes").html(totalMinutes);
|
||||
@@ -152,22 +150,20 @@ var UI = (function(params) {
|
||||
$("#silence-end-description").html(endsAtDesc);
|
||||
};
|
||||
|
||||
|
||||
silenceFormJSONRender = function() {
|
||||
var silenceFormJSONRender = function() {
|
||||
var d = "curl " + $("#silenceModal").data("silence-api") +
|
||||
"\n -X POST --data " +
|
||||
JSON.stringify(silenceFormData(), undefined, 2);
|
||||
$("#silenceJSONBlob").html(d);
|
||||
};
|
||||
|
||||
|
||||
silenceFormUpdateDuration = function(event) {
|
||||
var silenceFormUpdateDuration = function(event) {
|
||||
// skip if datetimepicker isn't ready yet
|
||||
if (!$("#startsAt").data('DateTimePicker') || !$("#endsAt").data('DateTimePicker')) return false;
|
||||
if (!$("#startsAt").data("DateTimePicker") || !$("#endsAt").data("DateTimePicker")) return false;
|
||||
|
||||
var startsAt = $("#startsAt").data('DateTimePicker').date();
|
||||
var endsAt = $("#endsAt").data('DateTimePicker').date();
|
||||
var endsAtMinDate = $("#endsAt").data('DateTimePicker').minDate();
|
||||
var startsAt = $("#startsAt").data("DateTimePicker").date();
|
||||
var endsAt = $("#endsAt").data("DateTimePicker").date();
|
||||
var endsAtMinDate = $("#endsAt").data("DateTimePicker").minDate();
|
||||
var action = $(event.target).data("duration-action");
|
||||
var unit = $(event.target).data("duration-unit");
|
||||
var step = parseInt($(event.target).data("duration-step"));
|
||||
@@ -203,13 +199,12 @@ var UI = (function(params) {
|
||||
endsAt = endsAtMinDate;
|
||||
}
|
||||
}
|
||||
$("#endsAt").data('DateTimePicker').date(endsAt);
|
||||
$("#endsAt").data("DateTimePicker").date(endsAt);
|
||||
silenceFormCalculateDuration();
|
||||
};
|
||||
|
||||
|
||||
// modal form for creating new silences
|
||||
setupSilenceForm = function() {
|
||||
var setupSilenceForm = function() {
|
||||
var modal = $("#silenceModal");
|
||||
modal.on("show.bs.modal", function(event) {
|
||||
Unsee.Pause();
|
||||
@@ -222,7 +217,7 @@ var UI = (function(params) {
|
||||
elemLabels[l.split("=")[0]] = l.split("=")[1];
|
||||
});
|
||||
$.ajax({
|
||||
url: 'alerts.json?q=alertname=' + elem.data('alertname'),
|
||||
url: "alerts.json?q=alertname=" + elem.data("alertname"),
|
||||
error: function(xhr, textStatus, errorThrown) {
|
||||
var err = xhr.responseText || errorThrown || textStatus;
|
||||
modal.find(".modal-body").html(
|
||||
@@ -254,71 +249,71 @@ var UI = (function(params) {
|
||||
);
|
||||
$.each($(".selectpicker"), function(i, elem) {
|
||||
$(elem).selectpicker({
|
||||
iconBase: 'fa',
|
||||
tickIcon: 'fa-check',
|
||||
width: 'fit',
|
||||
selectAllText: '<i class="fa fa-check-square-o"></i>',
|
||||
deselectAllText: '<i class="fa fa-square-o"></i>',
|
||||
noneSelectedText: '<span class="label label-list label-default">' + $(this).data('label-key') + ": </span>",
|
||||
multipleSeparator: ' ',
|
||||
selectedTextFormat: 'count > 1',
|
||||
countSelectedText: function (numSelected, numTotal) {
|
||||
return '<span class="label label-list label-warning">' +
|
||||
$(elem).data('label-key') + ": " + numSelected + " values selected</span>";
|
||||
iconBase: "fa",
|
||||
tickIcon: "fa-check",
|
||||
width: "fit",
|
||||
selectAllText: "<i class='fa fa-check-square-o'></i>",
|
||||
deselectAllText: "<i class='fa fa-square-o'></i>",
|
||||
noneSelectedText: "<span class='label label-list label-default'>" + $(this).data("label-key") + ": </span>",
|
||||
multipleSeparator: " ",
|
||||
selectedTextFormat: "count > 1",
|
||||
countSelectedText: function (numSelected) {
|
||||
return "<span class='label label-list label-warning'>" +
|
||||
$(elem).data("label-key") + ": " + numSelected + " values selected</span>";
|
||||
}
|
||||
});
|
||||
});
|
||||
$('.datetime-picker').datetimepicker({
|
||||
$(".datetime-picker").datetimepicker({
|
||||
format: "YYYY-MM-DD HH:mm",
|
||||
icons: {
|
||||
time: 'fa fa-clock-o',
|
||||
date: 'fa fa-calendar',
|
||||
up: 'fa fa-chevron-up',
|
||||
down: 'fa fa-chevron-down',
|
||||
previous: 'fa fa-chevron-left',
|
||||
next: 'fa fa-chevron-right',
|
||||
today: 'fa fa-asterisk',
|
||||
clear: 'fa fa-undo',
|
||||
close: 'fa fa-close'
|
||||
time: "fa fa-clock-o",
|
||||
date: "fa fa-calendar",
|
||||
up: "fa fa-chevron-up",
|
||||
down: "fa fa-chevron-down",
|
||||
previous: "fa fa-chevron-left",
|
||||
next: "fa fa-chevron-right",
|
||||
today: "fa fa-asterisk",
|
||||
clear: "fa fa-undo",
|
||||
close: "fa fa-close"
|
||||
},
|
||||
minDate: moment(),
|
||||
sideBySide: true,
|
||||
inline: true
|
||||
});
|
||||
setupGroupTooltips($("#newSilenceForm"));
|
||||
$('.select-label-badge').on('click', function(e) {
|
||||
var select = $(this).parent().parent().find('select');
|
||||
if (select.selectpicker('val')) {
|
||||
$(".select-label-badge").on("click", function() {
|
||||
var select = $(this).parent().parent().find("select");
|
||||
if (select.selectpicker("val")) {
|
||||
// if there's anything selected deselect all
|
||||
select.selectpicker('deselectAll');
|
||||
select.selectpicker("deselectAll");
|
||||
} else {
|
||||
// else select all
|
||||
select.selectpicker('selectAll');
|
||||
select.selectpicker("selectAll");
|
||||
}
|
||||
});
|
||||
// set endsAt minDate to now + 1 minute
|
||||
$("#endsAt").data('DateTimePicker').minDate(moment().add(1, 'minute'));
|
||||
$("#endsAt").data("DateTimePicker").minDate(moment().add(1, "minute"));
|
||||
// set endsAt time to +1 hour
|
||||
$("#endsAt").data('DateTimePicker').date(moment().add(1, 'hours'));
|
||||
$("#endsAt").data("DateTimePicker").date(moment().add(1, "hours"));
|
||||
// whenever startsAt changes set it as the minDate for endsAt
|
||||
// we can't have endsAt < startsAt
|
||||
$("#newSilenceForm").on("dp.change", "#startsAt", function(){
|
||||
if (!$("#startsAt").data('DateTimePicker')) return false;
|
||||
var startsAt = $("#startsAt").data('DateTimePicker').date();
|
||||
if (!$("#startsAt").data("DateTimePicker")) return false;
|
||||
var startsAt = $("#startsAt").data("DateTimePicker").date();
|
||||
// endsAt needs to be at least 1 minute after startsAt
|
||||
startsAt.add(1, "minute");
|
||||
$("#endsAt").data('DateTimePicker').minDate(startsAt);
|
||||
$("#endsAt").data("DateTimePicker").minDate(startsAt);
|
||||
});
|
||||
$("#newSilenceForm").on("click", "a.silence-duration-btn", silenceFormUpdateDuration);
|
||||
$("#newSilenceForm").on('show.bs.collapse, dp.change', function (e) {
|
||||
$("#newSilenceForm").on("show.bs.collapse, dp.change", function () {
|
||||
silenceFormJSONRender();
|
||||
silenceFormCalculateDuration();
|
||||
});
|
||||
$("#newSilenceForm").on('change', function (e) {
|
||||
$("#newSilenceForm").on("change", function () {
|
||||
silenceFormJSONRender();
|
||||
});
|
||||
$("#newSilenceForm").submit(function(event) {
|
||||
payload = silenceFormData();
|
||||
var payload = silenceFormData();
|
||||
if (payload.matchers.length === 0) {
|
||||
var errContent = Templates.Render("silenceFormError", {error: "Select at least on label"});
|
||||
$("#newSilenceAlert").html(errContent).removeClass("hidden");
|
||||
@@ -349,10 +344,10 @@ var UI = (function(params) {
|
||||
var errContent = Templates.Render("silenceFormError", {error: err});
|
||||
$("#newSilenceAlert").html(errContent).removeClass("hidden");
|
||||
},
|
||||
success: function(data, textStatus, xhr) {
|
||||
success: function(data) {
|
||||
if (data.status == "success") {
|
||||
$("#newSilenceAlert").addClass("hidden");
|
||||
$('#newSilenceForm').html(Templates.Render("silenceFormSuccess", {
|
||||
$("#newSilenceForm").html(Templates.Render("silenceFormSuccess", {
|
||||
silenceID: data.data.silenceId
|
||||
}));
|
||||
} else {
|
||||
@@ -371,14 +366,13 @@ var UI = (function(params) {
|
||||
});
|
||||
|
||||
});
|
||||
modal.on("hidden.bs.modal", function(event) {
|
||||
modal.on("hidden.bs.modal", function() {
|
||||
var modal = $(this);
|
||||
modal.find(".modal-body").children().remove();
|
||||
Unsee.WaitForNextReload();
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
Init: init,
|
||||
SetupAlertGroupUI: setupAlertGroupUI
|
||||
|
||||
+55
-65
@@ -1,23 +1,27 @@
|
||||
var Unsee = (function(params) {
|
||||
/* globals Raven */ // raven.js
|
||||
/* globals moment */ // moment.js
|
||||
|
||||
/* globals Alerts, Autocomplete, Colors, Config, Counter, Grid, Filters, Progress, Summary, Templates, UI, Watchdog */
|
||||
|
||||
/* exported Unsee */
|
||||
var Unsee = (function() {
|
||||
|
||||
var timer = false;
|
||||
var version = false;
|
||||
var refreshInterval = 15;
|
||||
|
||||
var selectors = {
|
||||
refreshButton: '#refresh',
|
||||
errors: '#errors'
|
||||
refreshButton: "#refresh",
|
||||
errors: "#errors"
|
||||
};
|
||||
|
||||
|
||||
init = function() {
|
||||
var init = function() {
|
||||
Progress.Init();
|
||||
|
||||
Config.Init({
|
||||
CopySelector: '#copy-settings-with-filter',
|
||||
SaveSelector: '#save-default-filter',
|
||||
ResetSelector: '#reset-settings'
|
||||
CopySelector: "#copy-settings-with-filter",
|
||||
SaveSelector: "#save-default-filter",
|
||||
ResetSelector: "#reset-settings"
|
||||
});
|
||||
Config.Load();
|
||||
|
||||
@@ -29,24 +33,22 @@ var Unsee = (function(params) {
|
||||
Watchdog.Init(30, 60*15); // set watchdog to 15 minutes
|
||||
|
||||
$(selectors.refreshButton).click(function() {
|
||||
if (!$(selectors.refreshButton).prop('disabled')) {
|
||||
if (!$(selectors.refreshButton).prop("disabled")) {
|
||||
Unsee.Reload();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
getRefreshRate = function() {
|
||||
var getRefreshRate = function() {
|
||||
return refreshInterval;
|
||||
};
|
||||
|
||||
|
||||
setRefreshRate = function(seconds) {
|
||||
var setRefreshRate = function(seconds) {
|
||||
var rate = parseInt(seconds);
|
||||
if (isNaN(rate)) {
|
||||
// if passed rate is incorrect use select value
|
||||
rate = Config.GetOption('refresh').Get();
|
||||
rate = Config.GetOption("refresh").Get();
|
||||
if (isNaN(rate)) {
|
||||
// if that's also borked use default 15
|
||||
rate = 15;
|
||||
@@ -56,8 +58,7 @@ var Unsee = (function(params) {
|
||||
Progress.Reset();
|
||||
};
|
||||
|
||||
|
||||
needsUpgrade = function(responseVersion) {
|
||||
var needsUpgrade = function(responseVersion) {
|
||||
if (version === false) {
|
||||
version = responseVersion;
|
||||
return false;
|
||||
@@ -65,8 +66,7 @@ var Unsee = (function(params) {
|
||||
return version != responseVersion;
|
||||
};
|
||||
|
||||
|
||||
renderError = function(template, context) {
|
||||
var renderError = function(template, context) {
|
||||
Counter.Error();
|
||||
Grid.Clear();
|
||||
Grid.Hide();
|
||||
@@ -78,13 +78,12 @@ var Unsee = (function(params) {
|
||||
updateCompleted();
|
||||
};
|
||||
|
||||
|
||||
handleError = function(err) {
|
||||
var handleError = function(err) {
|
||||
Raven.captureException(err);
|
||||
if (window.console) {
|
||||
console.error(err.stack);
|
||||
}
|
||||
renderError('internalError', {
|
||||
renderError("internalError", {
|
||||
name: err.name,
|
||||
message: err.message,
|
||||
raw: err
|
||||
@@ -94,27 +93,25 @@ var Unsee = (function(params) {
|
||||
}, 500);
|
||||
};
|
||||
|
||||
|
||||
upgrade = function() {
|
||||
renderError('reloadNeeded', {});
|
||||
var upgrade = function() {
|
||||
renderError("reloadNeeded", {});
|
||||
setTimeout(function() {
|
||||
location.reload();
|
||||
}, 3000);
|
||||
};
|
||||
|
||||
|
||||
triggerReload = function() {
|
||||
var triggerReload = function() {
|
||||
updateIsReady();
|
||||
$.ajax({
|
||||
url: 'alerts.json?q=' + Filters.GetFilters().join(','),
|
||||
url: "alerts.json?q=" + Filters.GetFilters().join(","),
|
||||
success: function(resp) {
|
||||
Counter.Success();
|
||||
if (needsUpgrade(resp.version)) {
|
||||
upgrade();
|
||||
} else if (resp.error) {
|
||||
Counter.Unknown();
|
||||
renderError('updateError', {
|
||||
error: 'Backend error',
|
||||
renderError("updateError", {
|
||||
error: "Backend error",
|
||||
message: resp.error,
|
||||
last_ts: Watchdog.GetLastUpdate()
|
||||
});
|
||||
@@ -133,8 +130,8 @@ var Unsee = (function(params) {
|
||||
Watchdog.Pong(moment(resp.timestamp));
|
||||
Unsee.WaitForNextReload();
|
||||
if (!Watchdog.IsFatal()) {
|
||||
$(selectors.errors).html('');
|
||||
$(selectors.errors).hide('');
|
||||
$(selectors.errors).html("");
|
||||
$(selectors.errors).hide("");
|
||||
}
|
||||
} catch (err) {
|
||||
Counter.Unknown();
|
||||
@@ -144,14 +141,14 @@ var Unsee = (function(params) {
|
||||
}, 50);
|
||||
}
|
||||
},
|
||||
error: function(jqXHR, textStatus) {
|
||||
error: function() {
|
||||
Counter.Unknown();
|
||||
// if fatal error was already triggered we have error message
|
||||
// so don't add new one
|
||||
if (!Watchdog.IsFatal()) {
|
||||
renderError('updateError', {
|
||||
error: 'Backend error',
|
||||
message: 'AJAX request failed',
|
||||
renderError("updateError", {
|
||||
error: "Backend error",
|
||||
message: "AJAX request failed",
|
||||
last_ts: Watchdog.GetLastUpdate()
|
||||
});
|
||||
}
|
||||
@@ -160,25 +157,22 @@ var Unsee = (function(params) {
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
updateIsReady = function() {
|
||||
var updateIsReady = function() {
|
||||
Progress.Complete();
|
||||
$(selectors.refreshButton).prop('disabled', true);
|
||||
$(selectors.refreshButton).prop("disabled", true);
|
||||
Counter.Hide();
|
||||
};
|
||||
|
||||
|
||||
updateCompleted = function() {
|
||||
var updateCompleted = function() {
|
||||
Counter.Show();
|
||||
Filters.UpdateCompleted();
|
||||
Progress.Complete();
|
||||
$(selectors.refreshButton).prop('disabled', false);
|
||||
$(selectors.refreshButton).prop("disabled", false);
|
||||
// hack for fixing padding since input can grow and change height
|
||||
$('body').css('padding-top', $('.navbar').height());
|
||||
$("body").css("padding-top", $(".navbar").height());
|
||||
};
|
||||
|
||||
|
||||
pause = function() {
|
||||
var pause = function() {
|
||||
Progress.Pause();
|
||||
Filters.Pause();
|
||||
if (timer !== false) {
|
||||
@@ -187,9 +181,8 @@ var Unsee = (function(params) {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
resume = function() {
|
||||
if (Config.GetOption('autorefresh').Get()) {
|
||||
var resume = function() {
|
||||
if (Config.GetOption("autorefresh").Get()) {
|
||||
Filters.UpdateCompleted();
|
||||
} else {
|
||||
Filters.Pause();
|
||||
@@ -202,19 +195,17 @@ var Unsee = (function(params) {
|
||||
timer = setTimeout(Unsee.Reload, Unsee.GetRefreshRate() * 1000);
|
||||
};
|
||||
|
||||
|
||||
flash = function() {
|
||||
var bg = $('#flash').css('background-color');
|
||||
$('#flash').css('display', 'block').animate({
|
||||
backgroundColor: '#fff'
|
||||
var flash = function() {
|
||||
var bg = $("#flash").css("background-color");
|
||||
$("#flash").css("display", "block").animate({
|
||||
backgroundColor: "#fff"
|
||||
}, 300, function() {
|
||||
$(this).animate({
|
||||
backgroundColor: bg
|
||||
}, 100).css('display', 'none');
|
||||
}, 100).css("display", "none");
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
Init: init,
|
||||
Pause: pause,
|
||||
@@ -227,17 +218,16 @@ var Unsee = (function(params) {
|
||||
|
||||
})();
|
||||
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
// wrap all inits so we can handle errors
|
||||
try {
|
||||
// init all elements using bootstrapSwitch
|
||||
$('.toggle').bootstrapSwitch();
|
||||
$(".toggle").bootstrapSwitch();
|
||||
|
||||
// enable tooltips, #settings is a dropdown so it already uses different data-toggle
|
||||
$('[data-toggle="tooltip"], #settings').tooltip({
|
||||
trigger: 'hover'
|
||||
$("[data-toggle='tooltip'], #settings").tooltip({
|
||||
trigger: "hover"
|
||||
});
|
||||
|
||||
Templates.Init();
|
||||
@@ -251,17 +241,17 @@ $(document).ready(function() {
|
||||
} catch (error) {
|
||||
Raven.captureException(error);
|
||||
if (window.console) {
|
||||
console.error('Error: ' + error.stack);
|
||||
console.error("Error: " + error.stack);
|
||||
}
|
||||
// templates might not be loaded yet, make some html manually
|
||||
$("#errors").html(
|
||||
'<div class="jumbotron">' +
|
||||
'<h1 class="text-center">' +
|
||||
'Internal error <i class="fa fa-exclamation-circle text-danger"/>' +
|
||||
'</h1>' +
|
||||
'<div class="text-center"><p>' +
|
||||
"<div class='jumbotron'>" +
|
||||
"<h1 class='text-center'>" +
|
||||
"Internal error <i class='fa fa-exclamation-circle text-danger'/>" +
|
||||
"</h1>" +
|
||||
"<div class='text-center'><p>" +
|
||||
error.message +
|
||||
'</p></div></div>'
|
||||
"</p></div></div>"
|
||||
).show();
|
||||
}
|
||||
|
||||
|
||||
+13
-15
@@ -1,29 +1,31 @@
|
||||
/* globals moment */ // moment.js
|
||||
|
||||
/* globals Config, Counter, Templates */
|
||||
|
||||
/* exported Watchdog */
|
||||
var Watchdog = (function() {
|
||||
|
||||
|
||||
var selectors = {
|
||||
countdown: '#reload-counter'
|
||||
countdown: "#reload-counter"
|
||||
};
|
||||
|
||||
var lastTs = 0;
|
||||
var maxLag;
|
||||
var timer = false;
|
||||
|
||||
var inCountdown = false;
|
||||
var fatalCountdown = 60;
|
||||
var fatalReloadTimer = false;
|
||||
var fatalCounterTimer = false;
|
||||
|
||||
|
||||
timerTick = function() {
|
||||
var timerTick = function() {
|
||||
if (lastTs === 0) return;
|
||||
|
||||
// don't raise an error if autorefresh is disabled
|
||||
if (!Config.GetOption('autorefresh').Get()) return;
|
||||
if (!Config.GetOption("autorefresh").Get()) return;
|
||||
|
||||
var now = moment().utc().unix();
|
||||
if (now - lastTs > maxLag) {
|
||||
$('#errors').html(Templates.Render('fatalError', {
|
||||
$("#errors").html(Templates.Render("fatalError", {
|
||||
last_ts: lastTs,
|
||||
seconds_left: fatalCountdown
|
||||
})).show();
|
||||
@@ -45,27 +47,23 @@ var Watchdog = (function() {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
init = function(interval, tolerance) {
|
||||
var init = function(interval, tolerance) {
|
||||
maxLag = tolerance;
|
||||
setInterval(timerTick, interval * 1000);
|
||||
};
|
||||
|
||||
|
||||
updateTs = function(ts) {
|
||||
var updateTs = function(ts) {
|
||||
lastTs = ts.utc().unix();
|
||||
};
|
||||
|
||||
|
||||
getTs = function() {
|
||||
var getTs = function() {
|
||||
return lastTs;
|
||||
};
|
||||
|
||||
getFatal = function() {
|
||||
var getFatal = function() {
|
||||
return inCountdown;
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
Init: init,
|
||||
Pong: updateTs,
|
||||
|
||||
+15
-15
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user