Skip to content

Commit

Permalink
[IMPROVEMENT] Move silence form to a separate component #377
Browse files Browse the repository at this point in the history
* Extract silence form into a new `<silence-form>` component
  * Template is now included as a X-Template. Without transpilation, we don't have access to single file components, and this way we don't have to keep it as a string
* Extract shared state into a simple state store
  * This allowed to simplify silence label update functions
* Cleanup `silence_form.html`
  * CSRF tokens are no longer needed, since we pass them with cookies
  * `.lazy` modifier is no longer necessary after #372 
* Use arrow functions to avoid `this` reassignment
  • Loading branch information
kfdm authored Jan 12, 2022
2 parents 01be464 + 089f7db commit 4cc80e6
Show file tree
Hide file tree
Showing 17 changed files with 114 additions and 167 deletions.
148 changes: 82 additions & 66 deletions promgen/static/js/promgen.vue.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,37 @@

Vue.config.devtools = true

const globalStore = {
state: {
messages: []
},
setMessages(messages) {
this.state.messages = [...messages];
}
};

const dataStore = {
global: globalStore.state,
components: {},
selectedHosts: [],
newSilence: { 'labels': {} },
globalSilences: [],
globalAlerts: [],
globalMessages: []
globalAlerts: []
};

const silenceStore = {
state: {
show: false,
labels: {}
},
showForm() {
this.state.show = true;
},
setLabels(labels) {
Vue.set(this.state, 'labels', { ...labels });
},
addLabel(label, value) {
Vue.set(this.state.labels, label, value);
}
};

const app = new Vue({
Expand All @@ -27,72 +51,31 @@ const app = new Vue({
let tgt = document.getElementById(target);
tgt.classList.toggle('collapse');
},
silenceExpire: function (id) {
fetch('/proxy/v1/silences/' + id, { method: 'DELETE' }).then(function (response) {
location.reload();
})
},
silenceChangeEvent: function (event) {
this.newSilence[event.target.name] = event.target.value;
expireSilence(id) {
fetch(`/proxy/v1/silences/${id}`, { method: 'DELETE' })
.then(() => location.reload());
},
silenceSubmit: function (event) {
let this_ = this;
fetch('/proxy/v1/silences', { method: 'POST', body: JSON.stringify(this.newSilence) })
.then(function (response) {
if (response.ok) {
location.reload();
} else {
return response.json()
}
})
.then(function (result) {
this_.globalMessages = [];
for (key in result.messages) {
this_.$set(this_.globalMessages, key, result.messages[key]);
}
})
setSilenceLabels(labels) {
silenceStore.setLabels(labels);
silenceStore.showForm();
scroll(0, 0);
},
silenceRemoveLabel: function (label) {
console.debug('silenceRemoveLabel', label)
this.$delete(this.newSilence.labels, label)
setSilenceDataset(event) {
this.setSilenceLabels(event.target.dataset);
},
showSilenceForm: function (event) {
this.$set(this.components, 'silence-form', true);
addSilenceLabel(label, value) {
silenceStore.addLabel(label, value);
silenceStore.showForm();
scroll(0, 0);
},
silenceAppendLabel: function (event) {
console.debug('silenceAppendLabel', event.target.dataset);
this.$set(this.newSilence.labels, event.target.dataset.label, event.target.dataset.value);
this.showSilenceForm(event);
},
silenceSelectedHosts: function (event) {
this.$set(this.newSilence, 'labels', {});
this.$set(this.newSilence.labels, "instance", this.selectedHosts.join("|"));
for (key in event.target.dataset) {
this.$set(this.newSilence.labels, key, event.target.dataset[key]);
}
this.showSilenceForm(event);
},
silenceSetLabels: function (event) {
console.debug('silenceSetLabels', event.target.dataset);
this.$set(this.newSilence, 'labels', {});
for (key in event.target.dataset) {
this.$set(this.newSilence.labels, key, event.target.dataset[key]);
}
this.showSilenceForm(event);
},
silenceAlert: function (alert) {
this.$set(this.newSilence, 'labels', {});
for (key in alert.labels) {
this.$set(this.newSilence.labels, key, alert.labels[key]);
}
this.showSilenceForm(event);
silenceSelectedHosts(event) {
this.setSilenceLabels(event.target.dataset);
this.addSilenceLabel('instance', this.selectedHosts.join('|'));
},
fetchSilences: function () {
let this_ = this;
fetch('/proxy/v1/silences')
.then(response => response.json())
.then(function (response) {
.then(response => {
let silences = response.data.sort(silence => silence.startsAt);

// Pull out the matchers and do a simpler label map
Expand All @@ -104,15 +87,14 @@ const app = new Vue({
}
}

this_.globalSilences = silences;
this.globalSilences = silences;
});
},
fetchAlerts: function () {
let this_ = this;
fetch('/proxy/v1/alerts')
.then(response => response.json())
.then(function (response) {
this_.globalAlerts = response.data.sort(alert => alert.startsAt);
.then(response => {
this.globalAlerts = response.data.sort(alert => alert.startsAt);
});

},
Expand Down Expand Up @@ -143,10 +125,10 @@ const app = new Vue({
return groupByLabel(this.activeSilences, 'project');
},
activeAlerts: function () {
return this.globalAlerts.filter(alert => alert.status.state == 'active');
return this.globalAlerts.filter(alert => alert.status.state === 'active');
},
activeSilences: function () {
return this.globalSilences.filter(silence => silence.status.state != 'expired');
return this.globalSilences.filter(silence => silence.status.state !== 'expired');
}
},
mounted: function () {
Expand All @@ -155,6 +137,40 @@ const app = new Vue({
},
});

Vue.component('silence-form', {
template: '#silence-form-template',
delimiters: ['[[', ']]'],
data: () => ({
state: silenceStore.state,
form: {}
}),
methods: {
removeLabel(label) {
this.$delete(this.state.labels, label);
},
submit() {
const body = JSON.stringify({
labels: this.state.labels,
...this.form
});

fetch('/proxy/v1/silences', { method: 'POST', body })
.then(response => {
if (response.ok) {
location.reload();
} else {
return response.json();
}
})
.then(result => {
if (result) {
globalStore.setMessages(result.messages);
}
});
},
}
});

Vue.filter("localize", function (number) {
return number.toLocaleString();
});
Expand Down
5 changes: 4 additions & 1 deletion promgen/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
{% endblock %}
<div class="container">
{% include 'promgen/global_messages.html' %}
{% include 'promgen/silence_form.html' %}
<silence-form></silence-form>
{% include 'promgen/global_alerts.html' %}
{% include 'promgen/global_silences.html' %}
{% block content %}{% endblock %}
Expand All @@ -35,6 +35,9 @@
<script src="{% static 'js/linkify.min.js' %}"></script>
<script src="{% static 'js/linkify-string.min.js' %}"></script>
<script src="{% static 'js/vue.min.js' %}"></script>
<script type="text/x-template" id="silence-form-template">
{% include 'promgen/silence_form.html' %}
</script>
<script src="{% static 'js/promgen.js' %}"></script>
<script src="{% static 'js/promgen.vue.js' %}"></script>
{% block javascript %}{% endblock %}
Expand Down
61 changes: 0 additions & 61 deletions promgen/templates/promgen/ajax_silence.html

This file was deleted.

5 changes: 0 additions & 5 deletions promgen/templates/promgen/ajax_silence_button.html

This file was deleted.

4 changes: 2 additions & 2 deletions promgen/templates/promgen/alert_row.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<dd>
<ul class="list-inline">
<li v-for="(value, label) in alert.labels">
<a @click.prevent="silenceAppendLabel" class="label label-danger" :data-label="label" :data-value="value">[[label]]:[[value]]</a>
<a @click="addSilenceLabel(label, value)" class="label label-danger">[[label]]:[[value]]</a>
</li>
</ul>
</dd>
Expand All @@ -20,5 +20,5 @@
</dl>
</td>
<td>
<a @click.prevent="silenceAlert(alert)" class="btn btn-warning btn-xs">{% trans "Silence" %}</a>
<a @click="setSilenceLabels(alert.labels)" class="btn btn-warning btn-xs">{% trans "Silence" %}</a>
</td>
2 changes: 1 addition & 1 deletion promgen/templates/promgen/global_messages.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
</div>
{% endfor %}

<div :class="m.class" role="alert" v-cloak v-for="m in globalMessages">
<div :class="m.class" role="alert" v-cloak v-for="m in global.messages">
<button type="button" class="close" data-dismiss="alert">
<span aria-hidden="true">&times;</span>
</button>
Expand Down
2 changes: 1 addition & 1 deletion promgen/templates/promgen/global_silences.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<th>Ends</th>
<th>Matchers</th>
<th>Comment</th>
<th>CreatedBy</th>
<th>Created by</th>
<th>&nbsp;</th>
</tr>
<tr v-for="silence in activeSilences">
Expand Down
3 changes: 1 addition & 2 deletions promgen/templates/promgen/host_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@ <h1>Host: {{ slug }}</h1>
<div class="panel panel-primary">
<div class="panel-body">
<a
@click.prevent="silenceSetLabels"
@click="setSilenceDataset"
class="btn btn-warning"
data-instance="{{slug}}:[0-9]*"
href="#"
style="display: inline-block;"
>{% trans "Silence" %}</a>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
</div>

<a href="{% url 'project-update' project.id %}" class="btn btn-warning btn-sm">{% trans "Update Project" %}</a>
<a @click.prevent="silenceSetLabels" class="btn btn-warning btn-sm" data-project="{{project.name}}" data-service="{{project.service.name}}">{% trans "Silence" %}</a>
<a @click="setSilenceDataset" class="btn btn-warning btn-sm" data-project="{{project.name}}" data-service="{{project.service.name}}">{% trans "Silence" %}</a>

<div class="btn-group btn-group-sm" role="group" aria-label="...">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Expand Down
3 changes: 1 addition & 2 deletions promgen/templates/promgen/project_detail_exporters.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,11 @@
</td>
<td>
<a
@click.prevent="silenceSetLabels"
@click="setSilenceDataset"
class="btn btn-warning btn-xs"
data-job="{{exporter.job}}"
data-project="{{project.name}}"
data-service="{{project.service.name}}"
href="#"
style="display: inline-block;"
>{% trans "Silence" %}</a>
</td>
Expand Down
6 changes: 2 additions & 4 deletions promgen/templates/promgen/project_detail_hosts.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,11 @@
<td><a href="{% url 'host-detail' host.name %}">{{ host.name }}</a></td>
<td>
<a
@click.prevent="silenceSetLabels"
@click="setSilenceDataset"
class="btn btn-warning btn-xs"
data-instance="{{host.name}}:[0-9]*"
data-project="{{project.name}}"
data-service="{{project.service.name}}"
href="#"
style="display: inline-block;"
>{% trans "Silence" %}</a>
</td>
Expand All @@ -39,11 +38,10 @@

<div class="panel-footer">
<a
@click.prevent="silenceSelectedHosts"
@click="silenceSelectedHosts"
class="btn btn-warning"
data-project="{{project.name}}"
data-service="{{project.service.name}}"
href="#"
style="display: inline-block;"
v-if="selectedHosts.length"
>{% trans "Silence selected hosts" %}</a>
Expand Down
2 changes: 1 addition & 1 deletion promgen/templates/promgen/project_detail_urls.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<td>{{ url.url }}</td>
<td title="{{ url.probe.description }}">{{ url.probe.module }}</td>
<td>
<a @click.prevent="silenceSetLabels"
<a @click="setSilenceDataset"
class="btn btn-warning btn-xs"
data-job="{{url.probe.module}}"
data-instance="{{url.url}}">{% trans "Silence" %}</a>
Expand Down
Loading

0 comments on commit 4cc80e6

Please sign in to comment.