mirror of
https://github.com/prymitive/karma
synced 2026-08-23 11:56:20 +00:00
@@ -0,0 +1,2 @@
|
||||
assets/static/lru.js
|
||||
assets/static/jquery.typing-0.2.0.js
|
||||
@@ -0,0 +1,27 @@
|
||||
env:
|
||||
browser: true
|
||||
jquery: true
|
||||
extends:
|
||||
- eslint:recommended
|
||||
rules:
|
||||
indent:
|
||||
- error
|
||||
- 4
|
||||
linebreak-style:
|
||||
- error
|
||||
- unix
|
||||
quotes:
|
||||
- error
|
||||
- double
|
||||
array-bracket-spacing:
|
||||
- warn
|
||||
- always
|
||||
block-spacing:
|
||||
- warn
|
||||
- always
|
||||
brace-style:
|
||||
- warn
|
||||
- 1tbs
|
||||
camelcase: warn
|
||||
no-console: off
|
||||
no-use-before-define: error
|
||||
+3
-7
@@ -6,15 +6,11 @@ go:
|
||||
|
||||
go_import_path: github.com/cloudflare/unsee
|
||||
|
||||
# nodejs is needed so that we can install jshint
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- nodejs
|
||||
|
||||
# install jshint, it's used for linting js files (needs nodejs)
|
||||
# install jshint & eslint, it's used for linting js files (needs nodejs)
|
||||
before_script:
|
||||
- nvm install 6
|
||||
- npm install jshint
|
||||
- npm install eslint
|
||||
|
||||
script:
|
||||
- make test
|
||||
|
||||
@@ -19,8 +19,9 @@ ifdef DEBUG
|
||||
DOCKER_ARGS = -v $(CURDIR)/assets:$(CURDIR)/assets:ro
|
||||
endif
|
||||
|
||||
# detect if jshint is installed
|
||||
# detect if jshint and/or eslint is installed
|
||||
JSHINT := $(shell which jshint)
|
||||
ESLINT := $(shell which eslint)
|
||||
|
||||
.DEFAULT_GOAL := $(NAME)
|
||||
|
||||
@@ -81,6 +82,9 @@ lint: .build/deps.ok
|
||||
ifneq ($(JSHINT),)
|
||||
@$(JSHINT) assets/static/*.js
|
||||
endif
|
||||
ifneq ($(ESLINT),)
|
||||
@$(ESLINT) --quiet assets/static/*.js
|
||||
endif
|
||||
|
||||
.PHONY: test
|
||||
test: lint bindata_assetfs.go
|
||||
|
||||
@@ -17,8 +17,7 @@ var Alerts = (function() {
|
||||
return Templates.Render("alertGroup", {
|
||||
group: this,
|
||||
silences: silences,
|
||||
static_color_label: Colors.GetStaticLabels(),
|
||||
alert_limit: 5
|
||||
alertLimit: 5
|
||||
});
|
||||
};
|
||||
|
||||
@@ -90,8 +89,8 @@ var Alerts = (function() {
|
||||
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");
|
||||
if (ts_age < 3) {
|
||||
var tsAge = now.diff(ts, "minutes");
|
||||
if (tsAge < 3) {
|
||||
$(elem).addClass("recent-alert").find(".incident-indicator").removeClass("hidden");
|
||||
} else {
|
||||
$(elem).removeClass("recent-alert").find(".incident-indicator").addClass("hidden");
|
||||
@@ -110,9 +109,9 @@ var Alerts = (function() {
|
||||
silences = apiResponse.silences;
|
||||
|
||||
var summaryData = {};
|
||||
$.each(apiResponse.counters, function(label_key, counters){
|
||||
$.each(counters, function(label_val, hits){
|
||||
summaryData[label_key + ": " + label_val] = hits;
|
||||
$.each(apiResponse.counters, function(labelKey, counters){
|
||||
$.each(counters, function(labelVal, hits){
|
||||
summaryData[labelKey + ": " + labelVal] = hits;
|
||||
});
|
||||
});
|
||||
Summary.Update(summaryData);
|
||||
|
||||
@@ -28,39 +28,39 @@ var Autocomplete = (function() {
|
||||
};
|
||||
|
||||
// this is used to generate quick filters for label modal
|
||||
var generateHints = function(label_key, label_val) {
|
||||
var hints = [];
|
||||
if (label_key == "@state") {
|
||||
// static list of hints for @silenced label
|
||||
hints.push("@state=active");
|
||||
hints.push("@state=suppressed");
|
||||
hints.push("@state=unprocessed");
|
||||
hints.push("@state!=active");
|
||||
hints.push("@state!=suppressed");
|
||||
hints.push("@state!=unprocessed");
|
||||
} else {
|
||||
// equal and non-equal hints for everything else
|
||||
hints.push(label_key + "=" + label_val);
|
||||
hints.push(label_key + "!=" + label_val);
|
||||
var generateHints = function(labelKey, labelVal) {
|
||||
var hints = [];
|
||||
if (labelKey == "@state") {
|
||||
// static list of hints for @silenced label
|
||||
hints.push("@state=active");
|
||||
hints.push("@state=suppressed");
|
||||
hints.push("@state=unprocessed");
|
||||
hints.push("@state!=active");
|
||||
hints.push("@state!=suppressed");
|
||||
hints.push("@state!=unprocessed");
|
||||
} else {
|
||||
// equal and non-equal hints for everything else
|
||||
hints.push(labelKey + "=" + labelVal);
|
||||
hints.push(labelKey + "!=" + labelVal);
|
||||
|
||||
// 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 there's space in the label generate regexp hints for partials
|
||||
if (labelVal.toString().indexOf(" ") >= 0) {
|
||||
$.each(labelVal.toString().split(" "), function(l, labelPart){
|
||||
hints.push(labelKey + "=~" + labelPart);
|
||||
hints.push(labelKey + "!~" + labelPart);
|
||||
});
|
||||
}
|
||||
|
||||
// if value is an int generate less / more hints
|
||||
if ($.isNumeric(label_val)) {
|
||||
var valAsNumber = parseInt(label_val);
|
||||
if (!isNaN(valAsNumber)) {
|
||||
hints.push(label_key + ">" + label_val);
|
||||
hints.push(label_key + "<" + label_val);
|
||||
}
|
||||
// if value is an int generate less / more hints
|
||||
if ($.isNumeric(labelVal)) {
|
||||
var valAsNumber = parseInt(labelVal);
|
||||
if (!isNaN(valAsNumber)) {
|
||||
hints.push(labelKey + ">" + labelVal);
|
||||
hints.push(labelKey + "<" + labelVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return hints;
|
||||
return hints;
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
/* exported Colors */
|
||||
var Colors = (function() {
|
||||
|
||||
var colors,
|
||||
staticColorLabels;
|
||||
var colors;
|
||||
|
||||
var specialLabels = {
|
||||
"@state: unprocessed": "label-default",
|
||||
@@ -32,8 +31,8 @@ var Colors = (function() {
|
||||
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;
|
||||
};
|
||||
@@ -46,12 +45,7 @@ var Colors = (function() {
|
||||
return ($.inArray(key, Colors.GetStaticLabels()) >= 0);
|
||||
};
|
||||
|
||||
var init = function(staticColors) {
|
||||
staticColorLabels = staticColors;
|
||||
};
|
||||
|
||||
return {
|
||||
Init: init,
|
||||
Update: update,
|
||||
Get: getStyle,
|
||||
GetClass: getClass,
|
||||
|
||||
@@ -84,8 +84,8 @@ var Config = (function() {
|
||||
// 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());
|
||||
});
|
||||
|
||||
+12
-12
@@ -30,21 +30,21 @@ var Filters = (function() {
|
||||
};
|
||||
|
||||
var init = function() {
|
||||
var initial_filter;
|
||||
var initialFilter;
|
||||
|
||||
if ($(selectors.filter).data("default-used") == "false" || $(selectors.filter).data("default-used") === false) {
|
||||
// user passed ?q=filter string
|
||||
initial_filter = $(selectors.filter).val();
|
||||
initialFilter = $(selectors.filter).val();
|
||||
} else {
|
||||
// no ?q=filter string, check if we have default filter cookie
|
||||
initial_filter = Cookies.get("defaultFilter.v2");
|
||||
if (initial_filter === undefined) {
|
||||
initialFilter = Cookies.get("defaultFilter.v2");
|
||||
if (initialFilter === undefined) {
|
||||
// no cookie, use global default
|
||||
initial_filter = $(selectors.filter).data("default-filter");
|
||||
initialFilter = $(selectors.filter).data("default-filter");
|
||||
}
|
||||
}
|
||||
|
||||
var initial_filter_arr = initial_filter.split(",");
|
||||
var initialFilterArr = initialFilter.split(",");
|
||||
$(selectors.filter).val("");
|
||||
$(".filterbar :input").tagsinput({
|
||||
typeaheadjs: {
|
||||
@@ -55,7 +55,7 @@ var Filters = (function() {
|
||||
source: Autocomplete.Autocomplete()
|
||||
}
|
||||
});
|
||||
$.each(initial_filter_arr, function(i, filter) {
|
||||
$.each(initialFilterArr, function(i, filter) {
|
||||
$(selectors.filter).tagsinput("add", filter);
|
||||
addBadge(filter);
|
||||
});
|
||||
@@ -90,8 +90,8 @@ var Filters = (function() {
|
||||
});
|
||||
|
||||
$(".filterbar").on("resize", function(){
|
||||
// hack for fixing padding since input can grow and change height
|
||||
$("body").css("padding-top", $(".navbar").height());
|
||||
// hack for fixing padding since input can grow and change height
|
||||
$("body").css("padding-top", $(".navbar").height());
|
||||
});
|
||||
|
||||
};
|
||||
@@ -120,8 +120,8 @@ var Filters = (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");
|
||||
// visual hint that alerts are reloaded due to filter change
|
||||
$(selectors.icon).removeClass("fa-search fa-pause").addClass("fa-circle-o-notch fa-spin");
|
||||
};
|
||||
|
||||
var updateDone = function() {
|
||||
@@ -129,7 +129,7 @@ var Filters = (function() {
|
||||
};
|
||||
|
||||
var setPause = function() {
|
||||
$(selectors.icon).removeClass("fa-circle-o-notch fa-spin fa-search").addClass("fa-pause");
|
||||
$(selectors.icon).removeClass("fa-circle-o-notch fa-spin fa-search").addClass("fa-pause");
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
@@ -33,13 +33,13 @@ var Progress = (function() {
|
||||
};
|
||||
|
||||
var start = function() {
|
||||
var step_ms = 250; // animation step in ms
|
||||
var steps = (Unsee.GetRefreshRate() * 1000) / step_ms; // how many steps we have
|
||||
var stepMs = 250; // animation step in ms
|
||||
var steps = (Unsee.GetRefreshRate() * 1000) / stepMs; // how many steps we have
|
||||
NProgress.set(0.0);
|
||||
Progress.ResetTimer();
|
||||
timer = setInterval(function() {
|
||||
NProgress.inc(1.0 / steps);
|
||||
}, step_ms);
|
||||
}, stepMs);
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
@@ -17,7 +17,7 @@ var QueryString = (function() {
|
||||
|
||||
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;
|
||||
@@ -37,7 +37,7 @@ var QueryString = (function() {
|
||||
};
|
||||
|
||||
var remove = function(key) {
|
||||
var baseUrl = [location.protocol, "//", location.host, location.pathname].join(""),
|
||||
var baseUrl = [ location.protocol, "//", location.host, location.pathname ].join(""),
|
||||
q = QueryString.Parse();
|
||||
if (q[key] !== undefined) {
|
||||
delete q[key];
|
||||
|
||||
+13
-13
@@ -2,18 +2,18 @@
|
||||
|
||||
(function() {
|
||||
|
||||
// init sentry client if sentry dsn is set
|
||||
if ($("body").data("raven-dsn")) {
|
||||
var dsn = $("body").data("raven-dsn").replace("\/", "/");
|
||||
// raven itself can fail if invalid DSN is passed
|
||||
try {
|
||||
Raven.config(dsn, {
|
||||
release: $("body").data("unsee-version")
|
||||
}).install();
|
||||
} catch (error) {
|
||||
var msg = "Sentry error: " + error.message;
|
||||
$("#raven-error").text(msg).removeClass("hidden");
|
||||
}
|
||||
}
|
||||
// init sentry client if sentry dsn is set
|
||||
if ($("body").data("raven-dsn")) {
|
||||
var dsn = $("body").data("raven-dsn").replace("\/", "/");
|
||||
// raven itself can fail if invalid DSN is passed
|
||||
try {
|
||||
Raven.config(dsn, {
|
||||
release: $("body").data("unsee-version")
|
||||
}).install();
|
||||
} catch (error) {
|
||||
var msg = "Sentry error: " + error.message;
|
||||
$("#raven-error").text(msg).removeClass("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
+227
-227
@@ -8,123 +8,123 @@ var Silence = (function() {
|
||||
var silenceFormData = function() {
|
||||
var values = $("#newSilenceForm").serializeArray();
|
||||
var payload = {
|
||||
matchers: [],
|
||||
startsAt: "",
|
||||
endsAt: "",
|
||||
createdBy: "",
|
||||
comment: ""
|
||||
matchers: [],
|
||||
startsAt: "",
|
||||
endsAt: "",
|
||||
createdBy: "",
|
||||
comment: ""
|
||||
};
|
||||
$.each(values, function(i, elem){
|
||||
switch (elem.name) {
|
||||
case "comment": case "createdBy":
|
||||
payload[elem.name] = elem.value;
|
||||
break;
|
||||
}
|
||||
switch (elem.name) {
|
||||
case "comment": case "createdBy":
|
||||
payload[elem.name] = elem.value;
|
||||
break;
|
||||
}
|
||||
});
|
||||
if ($("#startsAt").data("DateTimePicker")) {
|
||||
payload.startsAt = $("#startsAt").data("DateTimePicker").date();
|
||||
payload.startsAt = $("#startsAt").data("DateTimePicker").date();
|
||||
}
|
||||
if ($("#endsAt").data("DateTimePicker")) {
|
||||
payload.endsAt = $("#endsAt").data("DateTimePicker").date();
|
||||
payload.endsAt = $("#endsAt").data("DateTimePicker").date();
|
||||
}
|
||||
$.each($("#newSilenceForm .selectpicker"), function(i, elem) {
|
||||
var label_key = $(elem).data("label-key");
|
||||
var labelKey = $(elem).data("label-key");
|
||||
var values = $(elem).selectpicker("val");
|
||||
if (values && values.length > 0) {
|
||||
var pval;
|
||||
var isRegex = false;
|
||||
if (values.length > 1) {
|
||||
pval = "^(?:" + values.join("|") + ")$";
|
||||
isRegex = true;
|
||||
} else {
|
||||
pval = values[0];
|
||||
}
|
||||
payload.matchers.push({
|
||||
name: label_key,
|
||||
value: pval,
|
||||
isRegex: isRegex
|
||||
});
|
||||
var pval;
|
||||
var isRegex = false;
|
||||
if (values.length > 1) {
|
||||
pval = "^(?:" + values.join("|") + ")$";
|
||||
isRegex = true;
|
||||
} else {
|
||||
pval = values[0];
|
||||
}
|
||||
payload.matchers.push({
|
||||
name: labelKey,
|
||||
value: pval,
|
||||
isRegex: isRegex
|
||||
});
|
||||
}
|
||||
});
|
||||
return payload;
|
||||
};
|
||||
|
||||
var silenceFormCalculateDuration = function() {
|
||||
// skip if datetimepicker isn't ready yet
|
||||
if (!$("#startsAt").data("DateTimePicker") || !$("#endsAt").data("DateTimePicker")) return false;
|
||||
// skip if datetimepicker isn't ready yet
|
||||
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;
|
||||
$("#silence-duration-days").html(totalDays);
|
||||
$("#silence-duration-hours").html(totalHours);
|
||||
$("#silence-duration-minutes").html(totalMinutes);
|
||||
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);
|
||||
|
||||
var startsAtDesc = moment().to(startsAt);
|
||||
startsAtDesc = startsAtDesc.replace("in a few seconds", "now");
|
||||
startsAtDesc = startsAtDesc.replace("a few seconds ago", "now");
|
||||
$("#silence-start-description").html(startsAtDesc);
|
||||
var startsAtDesc = moment().to(startsAt);
|
||||
startsAtDesc = startsAtDesc.replace("in a few seconds", "now");
|
||||
startsAtDesc = startsAtDesc.replace("a few seconds ago", "now");
|
||||
$("#silence-start-description").html(startsAtDesc);
|
||||
|
||||
var endsAtDesc = moment().to(endsAt);
|
||||
endsAtDesc = endsAtDesc.replace("in a few seconds", "now");
|
||||
endsAtDesc = endsAtDesc.replace("a few seconds ago", "now");
|
||||
$("#silence-end-description").html(endsAtDesc);
|
||||
var endsAtDesc = moment().to(endsAt);
|
||||
endsAtDesc = endsAtDesc.replace("in a few seconds", "now");
|
||||
endsAtDesc = endsAtDesc.replace("a few seconds ago", "now");
|
||||
$("#silence-end-description").html(endsAtDesc);
|
||||
};
|
||||
|
||||
var silenceFormJSONRender = function() {
|
||||
var d = "curl " + $("#silenceModal").data("silence-api") +
|
||||
"\n -X POST --data " +
|
||||
JSON.stringify(silenceFormData(), undefined, 2);
|
||||
$("#silenceJSONBlob").html(d);
|
||||
var d = "curl " + $("#silenceModal").data("silence-api") +
|
||||
"\n -X POST --data " +
|
||||
JSON.stringify(silenceFormData(), undefined, 2);
|
||||
$("#silenceJSONBlob").html(d);
|
||||
};
|
||||
|
||||
var silenceFormUpdateDuration = function(event) {
|
||||
// skip if datetimepicker isn't ready yet
|
||||
if (!$("#startsAt").data("DateTimePicker") || !$("#endsAt").data("DateTimePicker")) return false;
|
||||
// skip if datetimepicker isn't ready yet
|
||||
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 action = $(event.target).data("duration-action");
|
||||
var unit = $(event.target).data("duration-unit");
|
||||
var step = parseInt($(event.target).data("duration-step"));
|
||||
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"));
|
||||
|
||||
// re-calculate step for low values
|
||||
// if we have 5 minute step and current duration is 1 minute than clicking
|
||||
// on the increment should give us 5 minute, not 6 minute duration
|
||||
var totalValue = (endsAt.diff(startsAt, unit));
|
||||
switch (unit) {
|
||||
// re-calculate step for low values
|
||||
// if we have 5 minute step and current duration is 1 minute than clicking
|
||||
// on the increment should give us 5 minute, not 6 minute duration
|
||||
var totalValue = (endsAt.diff(startsAt, unit));
|
||||
switch (unit) {
|
||||
case "hours":
|
||||
totalValue = totalValue % 24;
|
||||
break;
|
||||
totalValue = totalValue % 24;
|
||||
break;
|
||||
case "minutes":
|
||||
totalValue = totalValue % 60;
|
||||
break;
|
||||
}
|
||||
totalValue = totalValue % 60;
|
||||
break;
|
||||
}
|
||||
|
||||
if (action == "increment") {
|
||||
// if step is 5 minute and current value is 3 than set 5 minutes, not 8
|
||||
if (step > 1 && totalValue < step) {
|
||||
step = step - totalValue;
|
||||
if (action == "increment") {
|
||||
// if step is 5 minute and current value is 3 than set 5 minutes, not 8
|
||||
if (step > 1 && totalValue < step) {
|
||||
step = step - totalValue;
|
||||
}
|
||||
endsAt.add(step, unit);
|
||||
} else {
|
||||
// if step is 5 minute and current value is 3 than set 0 minutes
|
||||
if (totalValue > 0 && step > 1 && totalValue < step) {
|
||||
step = totalValue;
|
||||
}
|
||||
endsAt.subtract(step, unit);
|
||||
if (endsAt < endsAtMinDate) {
|
||||
// if decrement would result in a timestamp lower than allowed minimum
|
||||
// then just reset it to the minimum
|
||||
endsAt = endsAtMinDate;
|
||||
}
|
||||
}
|
||||
endsAt.add(step, unit);
|
||||
} else {
|
||||
// if step is 5 minute and current value is 3 than set 0 minutes
|
||||
if (totalValue > 0 && step > 1 && totalValue < step) {
|
||||
step = totalValue;
|
||||
}
|
||||
endsAt.subtract(step, unit);
|
||||
if (endsAt < endsAtMinDate) {
|
||||
// if decrement would result in a timestamp lower than allowed minimum
|
||||
// then just reset it to the minimum
|
||||
endsAt = endsAtMinDate;
|
||||
}
|
||||
}
|
||||
$("#endsAt").data("DateTimePicker").date(endsAt);
|
||||
silenceFormCalculateDuration();
|
||||
$("#endsAt").data("DateTimePicker").date(endsAt);
|
||||
silenceFormCalculateDuration();
|
||||
};
|
||||
|
||||
// modal form for creating new silences
|
||||
@@ -141,152 +141,152 @@ var Silence = (function() {
|
||||
elemLabels[l.split("=")[0]] = l.split("=")[1];
|
||||
});
|
||||
$.ajax({
|
||||
url: "alerts.json?q=alertname=" + elem.data("alertname"),
|
||||
error: function(xhr, textStatus, errorThrown) {
|
||||
var err = xhr.responseText || errorThrown || textStatus;
|
||||
modal.find(".modal-body").html(
|
||||
Templates.Render("silenceFormFatal", {error: err})
|
||||
);
|
||||
},
|
||||
success: function(data) {
|
||||
var modal = $("#silenceModal");
|
||||
var labels = {};
|
||||
$.each(data.groups, function(i, group) {
|
||||
$.each(group.alerts, function(j, alert) {
|
||||
$.each(alert.labels, function(label_key, label_val) {
|
||||
if (labels[label_key] === undefined) {
|
||||
labels[label_key] = {};
|
||||
}
|
||||
if (labels[label_key][label_val] === undefined) {
|
||||
labels[label_key][label_val] = {
|
||||
key: label_key,
|
||||
value: label_val,
|
||||
attrs: Alerts.GetLabelAttrs(label_key, label_val),
|
||||
selected: elemLabels[label_key] == label_val
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
modal.find(".modal-body").html(
|
||||
Templates.Render("silenceForm", {labels: labels})
|
||||
);
|
||||
$.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) {
|
||||
return "<span class='label label-list label-warning'>" +
|
||||
$(elem).data("label-key") + ": " + numSelected + " values selected</span>";
|
||||
url: "alerts.json?q=alertname=" + elem.data("alertname"),
|
||||
error: function(xhr, textStatus, errorThrown) {
|
||||
var err = xhr.responseText || errorThrown || textStatus;
|
||||
modal.find(".modal-body").html(
|
||||
Templates.Render("silenceFormFatal", {error: err})
|
||||
);
|
||||
},
|
||||
success: function(data) {
|
||||
var modal = $("#silenceModal");
|
||||
var labels = {};
|
||||
$.each(data.groups, function(i, group) {
|
||||
$.each(group.alerts, function(j, alert) {
|
||||
$.each(alert.labels, function(labelKey, labelVal) {
|
||||
if (labels[labelKey] === undefined) {
|
||||
labels[labelKey] = {};
|
||||
}
|
||||
if (labels[labelKey][labelVal] === undefined) {
|
||||
labels[labelKey][labelVal] = {
|
||||
key: labelKey,
|
||||
value: labelVal,
|
||||
attrs: Alerts.GetLabelAttrs(labelKey, labelVal),
|
||||
selected: elemLabels[labelKey] == labelVal
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
modal.find(".modal-body").html(
|
||||
Templates.Render("silenceForm", {labels: labels})
|
||||
);
|
||||
$.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) {
|
||||
return "<span class='label label-list label-warning'>" +
|
||||
$(elem).data("label-key") + ": " + numSelected + " values selected</span>";
|
||||
}
|
||||
});
|
||||
});
|
||||
$(".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"
|
||||
},
|
||||
minDate: moment(),
|
||||
sideBySide: true,
|
||||
inline: true
|
||||
});
|
||||
UI.SetupTooltips($("#newSilenceForm"));
|
||||
$(".select-label-badge").on("click", function() {
|
||||
var select = $(this).parent().parent().find("select");
|
||||
if (select.selectpicker("val").length) {
|
||||
// if there's anything selected deselect all
|
||||
select.selectpicker("deselectAll");
|
||||
} else {
|
||||
// else select all
|
||||
select.selectpicker("selectAll");
|
||||
}
|
||||
});
|
||||
});
|
||||
$(".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"
|
||||
},
|
||||
minDate: moment(),
|
||||
sideBySide: true,
|
||||
inline: true
|
||||
});
|
||||
UI.SetupTooltips($("#newSilenceForm"));
|
||||
$(".select-label-badge").on("click", function() {
|
||||
var select = $(this).parent().parent().find("select");
|
||||
if (select.selectpicker("val").length) {
|
||||
// if there's anything selected deselect all
|
||||
select.selectpicker("deselectAll");
|
||||
} else {
|
||||
// else select all
|
||||
select.selectpicker("selectAll");
|
||||
}
|
||||
});
|
||||
// set endsAt minDate to now + 1 minute
|
||||
$("#endsAt").data("DateTimePicker").minDate(moment().add(1, "minute"));
|
||||
// set endsAt time to +1 hour
|
||||
$("#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();
|
||||
// endsAt needs to be at least 1 minute after startsAt
|
||||
startsAt.add(1, "minute");
|
||||
$("#endsAt").data("DateTimePicker").minDate(startsAt);
|
||||
});
|
||||
$("#newSilenceForm").on("click", "a.silence-duration-btn", silenceFormUpdateDuration);
|
||||
$("#newSilenceForm").on("show.bs.collapse, dp.change", function () {
|
||||
silenceFormJSONRender();
|
||||
silenceFormCalculateDuration();
|
||||
});
|
||||
$("#newSilenceForm").on("change", function () {
|
||||
silenceFormJSONRender();
|
||||
});
|
||||
$("#newSilenceForm").submit(function(event) {
|
||||
var payload = silenceFormData();
|
||||
if (payload.matchers.length === 0) {
|
||||
var errContent = Templates.Render("silenceFormError", {error: "Select at least on label"});
|
||||
$("#newSilenceAlert").html(errContent).removeClass("hidden");
|
||||
return false;
|
||||
}
|
||||
|
||||
var url = modal.data("silence-api");
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: url,
|
||||
data: JSON.stringify(payload),
|
||||
error: function(xhr, textStatus, errorThrown) {
|
||||
// default to whatever error text we can get
|
||||
var err = xhr.responseText || errorThrown || textStatus;
|
||||
if (xhr.responseText) {
|
||||
// if we have a reponse text try to decode it as JSON
|
||||
// it should be error from Alertmanager (it we were able to connect)
|
||||
try {
|
||||
var j = JSON.parse(xhr.responseText);
|
||||
if (j.error !== undefined) {
|
||||
err = j.error;
|
||||
}
|
||||
} catch (error) {
|
||||
// can't parse json, do nothing
|
||||
}
|
||||
}
|
||||
|
||||
var errContent = Templates.Render("silenceFormError", {error: err});
|
||||
// set endsAt minDate to now + 1 minute
|
||||
$("#endsAt").data("DateTimePicker").minDate(moment().add(1, "minute"));
|
||||
// set endsAt time to +1 hour
|
||||
$("#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();
|
||||
// endsAt needs to be at least 1 minute after startsAt
|
||||
startsAt.add(1, "minute");
|
||||
$("#endsAt").data("DateTimePicker").minDate(startsAt);
|
||||
});
|
||||
$("#newSilenceForm").on("click", "a.silence-duration-btn", silenceFormUpdateDuration);
|
||||
$("#newSilenceForm").on("show.bs.collapse, dp.change", function () {
|
||||
silenceFormJSONRender();
|
||||
silenceFormCalculateDuration();
|
||||
});
|
||||
$("#newSilenceForm").on("change", function () {
|
||||
silenceFormJSONRender();
|
||||
});
|
||||
$("#newSilenceForm").submit(function(event) {
|
||||
var payload = silenceFormData();
|
||||
if (payload.matchers.length === 0) {
|
||||
var errContent = Templates.Render("silenceFormError", {error: "Select at least on label"});
|
||||
$("#newSilenceAlert").html(errContent).removeClass("hidden");
|
||||
},
|
||||
success: function(data) {
|
||||
if (data.status == "success") {
|
||||
$("#newSilenceAlert").addClass("hidden");
|
||||
$("#newSilenceForm").html(Templates.Render("silenceFormSuccess", {
|
||||
silenceID: data.data.silenceId
|
||||
}));
|
||||
} else {
|
||||
var err = "Invalid response from Alertmanager API: " + JSON.stringify(data);
|
||||
var errContent = Templates.Render("silenceFormError", {error: err});
|
||||
$("#newSilenceAlert").html(errContent).removeClass("hidden");
|
||||
}
|
||||
},
|
||||
dataType: "json"
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
});
|
||||
silenceFormCalculateDuration();
|
||||
silenceFormJSONRender();
|
||||
var url = modal.data("silence-api");
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: url,
|
||||
data: JSON.stringify(payload),
|
||||
error: function(xhr, textStatus, errorThrown) {
|
||||
// default to whatever error text we can get
|
||||
var err = xhr.responseText || errorThrown || textStatus;
|
||||
if (xhr.responseText) {
|
||||
// if we have a reponse text try to decode it as JSON
|
||||
// it should be error from Alertmanager (it we were able to connect)
|
||||
try {
|
||||
var j = JSON.parse(xhr.responseText);
|
||||
if (j.error !== undefined) {
|
||||
err = j.error;
|
||||
}
|
||||
} catch (error) {
|
||||
// can't parse json, do nothing
|
||||
}
|
||||
}
|
||||
|
||||
var errContent = Templates.Render("silenceFormError", {error: err});
|
||||
$("#newSilenceAlert").html(errContent).removeClass("hidden");
|
||||
},
|
||||
success: function(data) {
|
||||
if (data.status == "success") {
|
||||
$("#newSilenceAlert").addClass("hidden");
|
||||
$("#newSilenceForm").html(Templates.Render("silenceFormSuccess", {
|
||||
silenceID: data.data.silenceId
|
||||
}));
|
||||
} else {
|
||||
var err = "Invalid response from Alertmanager API: " + JSON.stringify(data);
|
||||
var errContent = Templates.Render("silenceFormError", {error: err});
|
||||
$("#newSilenceAlert").html(errContent).removeClass("hidden");
|
||||
}
|
||||
},
|
||||
dataType: "json"
|
||||
});
|
||||
|
||||
event.preventDefault();
|
||||
});
|
||||
silenceFormCalculateDuration();
|
||||
silenceFormJSONRender();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
+10
-10
@@ -6,14 +6,14 @@ var Summary = (function() {
|
||||
var summary;
|
||||
|
||||
var render = function() {
|
||||
var top_tags = [];
|
||||
var topTags = [];
|
||||
$.each(summary, function(k, v) {
|
||||
top_tags.push({
|
||||
topTags.push({
|
||||
name: k,
|
||||
val: v
|
||||
});
|
||||
});
|
||||
top_tags.sort(function(a, b) {
|
||||
topTags.sort(function(a, b) {
|
||||
if (a.val > b.val) return 1;
|
||||
if (a.val < b.val) return -1;
|
||||
if (a.name > b.name) return -1;
|
||||
@@ -22,11 +22,11 @@ var Summary = (function() {
|
||||
}).reverse();
|
||||
|
||||
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];
|
||||
tag.style = Colors.Get(label_key, label_val);
|
||||
tag.cls = Colors.GetClass(label_key, label_val);
|
||||
$.each(topTags.slice(0, 10), function(i, tag) {
|
||||
var labelKey = tag.name.split(": ")[0];
|
||||
var labelVal = tag.name.split(": ")[1];
|
||||
tag.style = Colors.Get(labelKey, labelVal);
|
||||
tag.cls = Colors.GetClass(labelKey, labelVal);
|
||||
tags.push(tag);
|
||||
});
|
||||
|
||||
@@ -38,8 +38,8 @@ var Summary = (function() {
|
||||
$(".navbar-header").popover({
|
||||
trigger: "hover",
|
||||
delay: {
|
||||
"show": 500,
|
||||
"hide": 100
|
||||
"show": 500,
|
||||
"hide": 100
|
||||
},
|
||||
container: "body",
|
||||
html: true,
|
||||
|
||||
+30
-30
@@ -5,40 +5,40 @@ var Templates = (function() {
|
||||
|
||||
var templates = {},
|
||||
config = {
|
||||
// popover with the list of most common labels
|
||||
breakdown: "#breakdown",
|
||||
breakdownContent: "#breakdown-content",
|
||||
// popover with the list of most common labels
|
||||
breakdown: "#breakdown",
|
||||
breakdownContent: "#breakdown-content",
|
||||
|
||||
// reload message if backend version bump is detected
|
||||
reloadNeeded: "#reload-needed",
|
||||
// reload message if backend version bump is detected
|
||||
reloadNeeded: "#reload-needed",
|
||||
|
||||
// errors
|
||||
fatalError: "#fatal-error",
|
||||
internalError: "#internal-error",
|
||||
updateError: "#update-error",
|
||||
// errors
|
||||
fatalError: "#fatal-error",
|
||||
internalError: "#internal-error",
|
||||
updateError: "#update-error",
|
||||
|
||||
// modal popup with label filters
|
||||
modalTitle: "#modal-title",
|
||||
modalBody: "#modal-body",
|
||||
// modal popup with label filters
|
||||
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",
|
||||
// modal popup with silence form
|
||||
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",
|
||||
// label button
|
||||
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"
|
||||
// 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"
|
||||
};
|
||||
|
||||
var init = function() {
|
||||
@@ -59,9 +59,9 @@ var Templates = (function() {
|
||||
return "<div class='jumbotron'><h1>Internal error: unknown template " + name + "</h1></div>";
|
||||
}
|
||||
try {
|
||||
return t(context);
|
||||
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>";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+7
-7
@@ -10,17 +10,17 @@ var UI = (function() {
|
||||
Unsee.Pause();
|
||||
var modal = $(this);
|
||||
var label = $(event.relatedTarget);
|
||||
var label_key = label.data("label-key");
|
||||
var label_val = label.data("label-val");
|
||||
var attrs = Alerts.GetLabelAttrs(label_key, label_val);
|
||||
var counter = Summary.Get(label_key, label_val);
|
||||
var labelKey = label.data("label-key");
|
||||
var labelVal = label.data("label-val");
|
||||
var attrs = Alerts.GetLabelAttrs(labelKey, labelVal);
|
||||
var counter = Summary.Get(labelKey, labelVal);
|
||||
modal.find(".modal-title").html(
|
||||
Templates.Render("modalTitle", {
|
||||
attrs: attrs,
|
||||
counter: counter
|
||||
attrs: attrs,
|
||||
counter: counter
|
||||
})
|
||||
);
|
||||
var hints = Autocomplete.GenerateHints(label_key, label_val);
|
||||
var hints = Autocomplete.GenerateHints(labelKey, labelVal);
|
||||
modal.find(".modal-body").html(
|
||||
Templates.Render("modalBody", {hints: hints})
|
||||
);
|
||||
|
||||
+50
-50
@@ -66,6 +66,21 @@ var Unsee = (function() {
|
||||
return version != responseVersion;
|
||||
};
|
||||
|
||||
var updateIsReady = function() {
|
||||
Progress.Complete();
|
||||
$(selectors.refreshButton).prop("disabled", true);
|
||||
Counter.Hide();
|
||||
};
|
||||
|
||||
var updateCompleted = function() {
|
||||
Counter.Show();
|
||||
Filters.UpdateCompleted();
|
||||
Progress.Complete();
|
||||
$(selectors.refreshButton).prop("disabled", false);
|
||||
// hack for fixing padding since input can grow and change height
|
||||
$("body").css("padding-top", $(".navbar").height());
|
||||
};
|
||||
|
||||
var renderError = function(template, context) {
|
||||
Counter.Error();
|
||||
Grid.Clear();
|
||||
@@ -113,7 +128,7 @@ var Unsee = (function() {
|
||||
renderError("updateError", {
|
||||
error: "Backend error",
|
||||
message: resp.error,
|
||||
last_ts: Watchdog.GetLastUpdate()
|
||||
lastTs: Watchdog.GetLastUpdate()
|
||||
});
|
||||
Unsee.WaitForNextReload();
|
||||
} else {
|
||||
@@ -130,8 +145,8 @@ var Unsee = (function() {
|
||||
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();
|
||||
@@ -149,7 +164,7 @@ var Unsee = (function() {
|
||||
renderError("updateError", {
|
||||
error: "Backend error",
|
||||
message: "AJAX request failed",
|
||||
last_ts: Watchdog.GetLastUpdate()
|
||||
lastTs: Watchdog.GetLastUpdate()
|
||||
});
|
||||
}
|
||||
Unsee.WaitForNextReload();
|
||||
@@ -157,21 +172,6 @@ var Unsee = (function() {
|
||||
});
|
||||
};
|
||||
|
||||
var updateIsReady = function() {
|
||||
Progress.Complete();
|
||||
$(selectors.refreshButton).prop("disabled", true);
|
||||
Counter.Hide();
|
||||
};
|
||||
|
||||
var updateCompleted = function() {
|
||||
Counter.Show();
|
||||
Filters.UpdateCompleted();
|
||||
Progress.Complete();
|
||||
$(selectors.refreshButton).prop("disabled", false);
|
||||
// hack for fixing padding since input can grow and change height
|
||||
$("body").css("padding-top", $(".navbar").height());
|
||||
};
|
||||
|
||||
var pause = function() {
|
||||
Progress.Pause();
|
||||
Filters.Pause();
|
||||
@@ -220,40 +220,40 @@ var Unsee = (function() {
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
// wrap all inits so we can handle errors
|
||||
try {
|
||||
// init all elements using bootstrapSwitch
|
||||
$(".toggle").bootstrapSwitch();
|
||||
// wrap all inits so we can handle errors
|
||||
try {
|
||||
// init all elements using bootstrapSwitch
|
||||
$(".toggle").bootstrapSwitch();
|
||||
|
||||
// enable tooltips, #settings is a dropdown so it already uses different data-toggle
|
||||
$("[data-toggle='tooltip'], #settings").tooltip({
|
||||
trigger: "hover"
|
||||
});
|
||||
// enable tooltips, #settings is a dropdown so it already uses different data-toggle
|
||||
$("[data-toggle='tooltip'], #settings").tooltip({
|
||||
trigger: "hover"
|
||||
});
|
||||
|
||||
Templates.Init();
|
||||
UI.Init();
|
||||
Silence.Init();
|
||||
Unsee.Init();
|
||||
Templates.Init();
|
||||
UI.Init();
|
||||
Silence.Init();
|
||||
Unsee.Init();
|
||||
|
||||
// delay initial alert load to allow browser finish rendering
|
||||
setTimeout(function() {
|
||||
Filters.SetFilters();
|
||||
}, 100);
|
||||
} catch (error) {
|
||||
Raven.captureException(error);
|
||||
if (window.console) {
|
||||
console.error("Error: " + error.stack);
|
||||
// delay initial alert load to allow browser finish rendering
|
||||
setTimeout(function() {
|
||||
Filters.SetFilters();
|
||||
}, 100);
|
||||
} catch (error) {
|
||||
Raven.captureException(error);
|
||||
if (window.console) {
|
||||
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>" +
|
||||
error.message +
|
||||
"</p></div></div>"
|
||||
).show();
|
||||
}
|
||||
// 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>" +
|
||||
error.message +
|
||||
"</p></div></div>"
|
||||
).show();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@@ -26,8 +26,8 @@ var Watchdog = (function() {
|
||||
var now = moment().utc().unix();
|
||||
if (now - lastTs > maxLag) {
|
||||
$("#errors").html(Templates.Render("fatalError", {
|
||||
last_ts: lastTs,
|
||||
seconds_left: fatalCountdown
|
||||
lastTs: lastTs,
|
||||
secondsLeft: fatalCountdown
|
||||
})).show();
|
||||
Counter.Unknown();
|
||||
if (!inCountdown) {
|
||||
|
||||
@@ -209,7 +209,7 @@
|
||||
<% var labelMap = {} %>
|
||||
<% var skipped = 0 %>
|
||||
<% _.each(group.alerts, function(alert, i) { %>
|
||||
<% if (i > alert_limit - 1) { %>
|
||||
<% if (i > alertLimit - 1) { %>
|
||||
<% skipped++ %>
|
||||
<% _.each(alert.labels, function(label_val, label_key) { %>
|
||||
<% var text = label_key + ': ' + label_val %>
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
</p>
|
||||
</div>
|
||||
<% } %>
|
||||
<% if (last_ts > 0) { %>
|
||||
<% if (lastTs > 0) { %>
|
||||
<div class="text-center">
|
||||
<p>
|
||||
Last successful update was <%= moment.unix(last_ts).fromNow() %>
|
||||
Last successful update was <%= moment.unix(lastTs).fromNow() %>
|
||||
</p>
|
||||
</div>
|
||||
<% } %>
|
||||
@@ -39,12 +39,12 @@
|
||||
</h1>
|
||||
<div class="text-center">
|
||||
<p>
|
||||
Auto refresh is enabled but last update was <%= moment.unix(last_ts).fromNow() %>
|
||||
Auto refresh is enabled but last update was <%= moment.unix(lastTs).fromNow() %>
|
||||
</p>
|
||||
<p>
|
||||
This page will auto reload in
|
||||
<span id='reload-counter'>
|
||||
<%- seconds_left %> seconds
|
||||
<%- secondsLeft %> seconds
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
+16
-16
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user