Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement "Create Silence" Feature as a Modal #523

Merged
merged 1 commit into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions promgen/static/css/promgen.css
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,66 @@ a[rel]:after {
word-break: break-word;
font-family: monospace;
}

/* silence-modal */
.promgen-labels-list {
padding: 10px 5px;
min-height: 116px;
border-radius: 8px 0px 0px 0px;
margin-left: 0px;
background: #F9F9F9;
}

.promgen-label-target {
height: 32px;
border-radius: 4px;
color: #000000;
border: 0.5px solid #3269BC;
background: #F1F6FF;
padding: 0px 10px;
margin-bottom: 10px;
}

.promgen-label-target:hover {
text-decoration: none !important;
color: #000000;
}

.promgen-label-close {
font-size: 20px;
margin-left: 10px;
color: #aaaaaa;
bai1024 marked this conversation as resolved.
Show resolved Hide resolved
cursor: pointer;
}

/* Margin Top */
.mt-0 { margin-top: 0 !important; }
.mt-1 { margin-top: 0.25rem !important; }
.mt-2 { margin-top: 0.5rem !important; }
.mt-3 { margin-top: 1rem !important; }
.mt-4 { margin-top: 1.5rem !important; }
.mt-5 { margin-top: 3rem !important; }

/* Margin Bottom */
.mb-0 { margin-bottom: 0 !important; }
.mb-1 { margin-bottom: 0.25rem !important; }
.mb-2 { margin-bottom: 0.5rem !important; }
.mb-3 { margin-bottom: 1rem !important; }
.mb-4 { margin-bottom: 1.5rem !important; }
.mb-5 { margin-bottom: 3rem !important; }

/* Margin Left (Bootstrap 4) */
.ml-0 { margin-left: 0 !important; }
.ml-1 { margin-left: 0.25rem !important; }
.ml-2 { margin-left: 0.5rem !important; }
.ml-3 { margin-left: 1rem !important; }
.ml-4 { margin-left: 1.5rem !important; }
.ml-5 { margin-left: 3rem !important; }

/* Margin Right (Bootstrap 4) */
.mr-0 { margin-right: 0 !important; }
.mr-1 { margin-right: 0.25rem !important; }
.mr-2 { margin-right: 0.5rem !important; }
.mr-3 { margin-right: 1rem !important; }
.mr-4 { margin-right: 1.5rem !important; }
.mr-5 { margin-right: 3rem !important; }
75 changes: 62 additions & 13 deletions promgen/static/js/promgen.vue.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,18 @@ const silenceStore = Vue.reactive({
show: false,
labels: {}
},
showForm() {
this.state.show = true;
},
setLabels(labels) {
this.state.labels = { ...labels };
},
addLabel(label, value) {
this.state.labels[label] = value;
}
},
showModal() {
this.state.show = true;
},
hideModal() {
this.state.show = false;
},
});

const exporterTestResultStore = Vue.reactive({
Expand Down Expand Up @@ -67,16 +70,14 @@ const app = Vue.createApp({
},
setSilenceLabels(labels) {
silenceStore.setLabels(labels);
silenceStore.showForm();
scroll(0, 0);
silenceStore.showModal();
},
setSilenceDataset(event) {
this.setSilenceLabels(event.target.dataset);
},
addSilenceLabel(label, value) {
silenceStore.addLabel(label, value);
silenceStore.showForm();
scroll(0, 0);
silenceStore.showModal();
},
silenceSelectedHosts(event) {
this.setSilenceLabels(event.target.dataset);
Expand Down Expand Up @@ -116,7 +117,7 @@ const app = Vue.createApp({
// and set the target list
let tgt = document.getElementById(target);
tgt.setAttribute('list', dst + '.' + src);
}
},
},
computed: {
activeServiceAlerts: function () {
Expand Down Expand Up @@ -149,21 +150,37 @@ const app = Vue.createApp({

app.config.compilerOptions.whitespace = "preserve";

app.component('silence-form', {
template: '#silence-form-template',
app.component('silence-modal', {
template: '#silence-modal-template',
delimiters: ['[[', ']]'],
data: () => ({
state: silenceStore.state,
form: {}
}),
computed: {
globalMessages() {
return globalStore.state.messages;
},
},
methods: {
addLabel() {
if (this.form.label && this.form.value) {
silenceStore.addLabel(this.form.label, this.form.value);
this.form.label = '';
this.form.value = '';
}
},
removeLabel(label) {
delete this.state.labels[label];
},
submit() {
const body = JSON.stringify({
labels: this.state.labels,
...this.form
startsAt: this.form.startsAt,
endsAt: this.form.endsAt,
duration: this.form.duration,
createdBy: this.form.createdBy,
comment: this.form.comment
});

fetch('/proxy/v1/silences', { method: 'POST', body })
Expand All @@ -180,7 +197,39 @@ app.component('silence-form', {
}
});
},
}
hideModal() {
const modal = $('#silenceModal');
if (modal.length) {
globalStore.setMessages([]);
this.form = {};
this.state = silenceStore.state;
modal.modal('hide');
}
},
vincent-olivert-riera marked this conversation as resolved.
Show resolved Hide resolved
showModal() {
const modal = $('#silenceModal');
if (modal.length) {
// Detect when the modal is closed, and update the state accordingly. This is
// necessary in case the user closes the modal by clicking outside of it, instead of
// using the close button.
//
// https://getbootstrap.com/docs/3.3/javascript/#modals-events
modal.on('hidden.bs.modal', function (e) {
silenceStore.hideModal();
});
modal.modal('show');
}
},
},
watch: {
"state.show"(val) {
if (val) {
this.showModal();
} else {
this.hideModal();
}
},
},
vincent-olivert-riera marked this conversation as resolved.
Show resolved Hide resolved
});

app.component("promql-query", {
Expand Down
6 changes: 3 additions & 3 deletions promgen/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
{% endblock %}
<div class="container">
{% include 'promgen/global_messages.html' %}
<silence-form></silence-form>
<silence-modal></silence-modal>
{% include 'promgen/global_alerts.html' %}
{% include 'promgen/global_silences.html' %}
{% block content %}{% endblock %}
Expand Down Expand Up @@ -52,8 +52,8 @@
<script type="text/x-template" id="promql-query-template">
{% include 'promgen/vue/promql_query.html' %}
</script>
<script type="text/x-template" id="silence-form-template">
{% include 'promgen/vue/silence_form.html' %}
<script type="text/x-template" id="silence-modal-template">
{% include 'promgen/vue/silence_modal.html' %}
</script>
<script src="{% static 'js/promgen.js' %}"></script>
<script src="{% static 'js/mixins.vue.js' %}"></script>
Expand Down
42 changes: 0 additions & 42 deletions promgen/templates/promgen/vue/silence_form.html

This file was deleted.

108 changes: 108 additions & 0 deletions promgen/templates/promgen/vue/silence_modal.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<div id="silenceModal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="silenceModalLabel">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" @click="state.show = false" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="silenceModalLabel">New Silence</h4>
</div>
<div class="modal-body" style="padding:10px 30px;">

<div>
<div v-for="message in globalMessages" :key="message.id">
<div :class="message.class" >
[[ message.message ]]
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
</div>

</div>
</div>

<form @submit.prevent="submit()">

<div class="row mb-4">
<div class="col-md-4">
<h5>
Start from
</h5>
<div>
<input v-model="form.startsAt" placeholder="2006-10-25 14:30" type='datetime-local' class="form-control" />
</div>
</div>
<div class="col-md-4">
<h5>
End
</h5>
<div>
<input v-model="form.endsAt" placeholder="2006-10-25 14:30" type='datetime-local' class="form-control" />
</div>
</div>
<div class="col-md-4">
<h5>
Duration
</h5>
<div>
<input v-model="form.duration" placeholder="1m/1h/etc" class="form-control" />
</div>
</div>
</div>

<div class="row mb-4">
<div class="col-md-12">
<h5>
Target
</h5>
<div class="labels">
<ul class="list-inline promgen-labels-list">
<li v-for="(value, label) in state.labels">
<div class="promgen-label-target">
<span>[[label]]=~[[value]]</span>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is somewhat incorrect. We are not always using =~ matches for everything. I think only the instance field is a =~ while others should generally be a regular = match 🤔

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A little buried but

kwargs["matchers"] = [
{
"name": name,
"value": value,
"isEqual": True, # Right now we only support =~
"isRegex": True if value.endswith("*") else False,
}
for name, value in labels.items()

The only time it is a =~ is when our matcher ends with * and in Promgen that is generally only for our quick silence for instance/host

<span @click="removeLabel(label)" aria-hidden="true" class="promgen-label-close">&times;</span>
</div>
</li>
</ul>
</div>
</div>
</div>

<div class="row mb-4">
<div class="col-md-12">
<h5>Matcher</h5>
<div style="display: flex;align-items: center;">
<input type="text" placeholder="Label" v-model="form.label" class="form-control">
<input type="text" placeholder="=~" style="max-width: 50px; text-align: center;" class="form-control ml-2 mr-2" disabled>
<input type="text" placeholder="Value" v-model="form.value" class="form-control">
<button type="button" class="btn btn-primary ml-2" @click="addLabel">&plus;</button>
</div>
</div>
</div>

<div class="row mb-4">
<div class="col-md-6">
<h5>
Created By
</h5>
<div>
<input v-model="form.createdBy" class="form-control" />
</div>
</div>
</div>

<div class="row mb-4">
<div class="col-md-12">
<h5>
Comment
</h5>
<div>
<textarea v-model="form.comment" class="form-control" rows="3"></textarea>
</div>
</div>
</div>

</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" @click="submit()">Create</button>
</div>
</div>
</div>
</div>