mirror of
https://github.com/prymitive/karma
synced 2026-05-27 05:03:09 +00:00
Merge pull request #77 from cloudflare/fix-silence-label
Polish silence form UI
This commit is contained in:
@@ -450,13 +450,19 @@ table.silence-duration-table > tbody > tr > td.silence-duration-label {
|
||||
line-height: 2em;
|
||||
}
|
||||
|
||||
.no-margin-top {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
a[aria-expanded=true] .fa-chevron-right {
|
||||
display: none;
|
||||
}
|
||||
a[aria-expanded=false] .fa-chevron-down {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* adjust size and padding to look like bootstrap button but without all background tweaks */
|
||||
.icon-as-button {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
padding: 10px 15px;
|
||||
font-size: 15px;
|
||||
line-height: 1.42857143;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
@@ -36,6 +36,10 @@ var Summary = (function() {
|
||||
summary = {};
|
||||
$('.navbar-header').popover({
|
||||
trigger: 'hover',
|
||||
delay: {
|
||||
"show": 500,
|
||||
"hide": 100
|
||||
},
|
||||
container: 'body',
|
||||
html: true,
|
||||
placement: 'bottom',
|
||||
|
||||
@@ -34,7 +34,7 @@ var UI = (function(params) {
|
||||
modal.find(".modal-body").children().remove();
|
||||
Unsee.WaitForNextReload();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// each alert group have a link generated for it, but we hide it until
|
||||
@@ -50,7 +50,7 @@ var UI = (function(params) {
|
||||
opacity: 0
|
||||
}, 200);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// find all elements inside alert group panel that will use tooltips
|
||||
@@ -67,19 +67,19 @@ var UI = (function(params) {
|
||||
trigger: "hover"
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
setupAlertGroupUI = function(elem) {
|
||||
setupGroupLinkHover(elem);
|
||||
setupGroupTooltips(elem);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
init = function() {
|
||||
setupModal();
|
||||
setupSilenceForm();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
silenceFormData = function() {
|
||||
@@ -116,7 +116,7 @@ var UI = (function(params) {
|
||||
} else {
|
||||
pval = values[0];
|
||||
}
|
||||
payload["matchers"].push({
|
||||
payload.matchers.push({
|
||||
name: label_key,
|
||||
value: pval,
|
||||
isRegex: isRegex
|
||||
@@ -124,7 +124,7 @@ var UI = (function(params) {
|
||||
}
|
||||
});
|
||||
return payload;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
silenceFormCalculateDuration = function() {
|
||||
@@ -150,36 +150,62 @@ var UI = (function(params) {
|
||||
endsAtDesc = endsAtDesc.replace("in a few seconds", "now");
|
||||
endsAtDesc = endsAtDesc.replace("a few seconds ago", "now");
|
||||
$("#silence-end-description").html(endsAtDesc);
|
||||
|
||||
// fix endsAt min date, it cannot be < startsAt
|
||||
$("#endsAt").data('DateTimePicker').minDate(startsAt);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
silenceFormJSONRender = function() {
|
||||
var d = "curl " + $("#silenceModal").data("silence-api")
|
||||
+ "\n -X POST --data "
|
||||
+ JSON.stringify(silenceFormData(), undefined, 2);
|
||||
var d = "curl " + $("#silenceModal").data("silence-api") +
|
||||
"\n -X POST --data " +
|
||||
JSON.stringify(silenceFormData(), undefined, 2);
|
||||
$("#silenceJSONBlob").html(d);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
silenceFormUpdateDuration = function(event) {
|
||||
// skip if datetimepicker isn't ready yet
|
||||
if (!$("#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 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) {
|
||||
case "hours":
|
||||
totalValue = totalValue % 24;
|
||||
break;
|
||||
case "minutes":
|
||||
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;
|
||||
}
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// modal form for creating new silences
|
||||
@@ -209,16 +235,16 @@ var UI = (function(params) {
|
||||
$.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) {
|
||||
if (labels[label_key] === undefined) {
|
||||
labels[label_key] = {};
|
||||
}
|
||||
if (labels[label_key][label_val] == undefined) {
|
||||
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
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -237,8 +263,8 @@ var UI = (function(params) {
|
||||
multipleSeparator: ' ',
|
||||
selectedTextFormat: 'count > 1',
|
||||
countSelectedText: function (numSelected, numTotal) {
|
||||
return '<span class="label label-list label-warning">'
|
||||
+ $(elem).data('label-key') + ": " + numSelected + " values selected</span>";
|
||||
return '<span class="label label-list label-warning">' +
|
||||
$(elem).data('label-key') + ": " + numSelected + " values selected</span>";
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -264,14 +290,25 @@ var UI = (function(params) {
|
||||
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 time to +1hour
|
||||
// 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
|
||||
modal.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);
|
||||
});
|
||||
modal.on("click", "a.silence-duration-btn", silenceFormUpdateDuration);
|
||||
modal.on("mousedown", "a.silence-duration-btn", false);
|
||||
silenceFormCalculateDuration();
|
||||
@@ -293,7 +330,7 @@ var UI = (function(params) {
|
||||
});
|
||||
modal.submit(function(event) {
|
||||
payload = silenceFormData();
|
||||
if (payload["matchers"].length == 0) {
|
||||
if (payload.matchers.length === 0) {
|
||||
var errContent = Templates.Render("silenceFormError", {error: "Select at least on label"});
|
||||
$("#newSilenceAlert").html(errContent).removeClass("hidden");
|
||||
return false;
|
||||
@@ -312,10 +349,10 @@ var UI = (function(params) {
|
||||
// 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"];
|
||||
if (j.error !== undefined) {
|
||||
err = j.error;
|
||||
}
|
||||
} catch (err) {
|
||||
} catch (error) {
|
||||
// can't parse json, do nothing
|
||||
}
|
||||
}
|
||||
@@ -324,10 +361,10 @@ var UI = (function(params) {
|
||||
$("#newSilenceAlert").html(errContent).removeClass("hidden");
|
||||
},
|
||||
success: function(data, textStatus, xhr) {
|
||||
if (data["status"] == "success") {
|
||||
if (data.status == "success") {
|
||||
$("#newSilenceAlert").addClass("hidden");
|
||||
$('#newSilenceForm').html(Templates.Render("silenceFormSuccess", {
|
||||
silenceID: data["data"]["silenceId"]
|
||||
silenceID: data.data.silenceId
|
||||
}));
|
||||
} else {
|
||||
var err = "Invalid response from Alertmanager API: " + JSON.stringify(data);
|
||||
@@ -340,12 +377,12 @@ var UI = (function(params) {
|
||||
|
||||
event.preventDefault();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
Init: init,
|
||||
SetupAlertGroupUI: setupAlertGroupUI
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
@@ -30,8 +30,6 @@
|
||||
<% }) %>
|
||||
</table>
|
||||
|
||||
<hr class="separator">
|
||||
|
||||
<div>
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li role="presentation">
|
||||
@@ -132,8 +130,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="separator no-margin-top">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">
|
||||
@@ -164,18 +160,24 @@
|
||||
|
||||
<hr class="separator">
|
||||
|
||||
<a class="text-muted" data-toggle="collapse" href="#silenceJSON" aria-expanded="false" aria-controls="silenceJSON">
|
||||
<i class="fa fa-chevron-right"></i>
|
||||
<i class="fa fa-chevron-down"></i>
|
||||
</a>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<a class="text-muted icon-as-button" data-toggle="collapse" href="#silenceJSON" aria-expanded="false" aria-controls="silenceJSON">
|
||||
<i class="fa fa-chevron-right"></i>
|
||||
<i class="fa fa-chevron-down"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-sm-6 text-right">
|
||||
<button id="silenceSubmit" type="submit" class="btn btn-success">
|
||||
<i class="fa fa-floppy-o"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="collapse" id="silenceJSON">
|
||||
<p class="text-muted">
|
||||
</p>
|
||||
<pre id="silenceJSONBlob"></pre>
|
||||
</div>
|
||||
|
||||
<div class="text-center">
|
||||
<button id="silenceSubmit" type="submit" class="btn btn-success">Create</button>
|
||||
</div>
|
||||
</form>
|
||||
</script>
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user