mirror of
https://github.com/jpros/tacticalrmm-web.git
synced 2026-05-05 05:46:12 +00:00
more alerts work
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<q-dialog ref="dialog" @hide="onHide">
|
||||
<div style="width: 900px; max-width: 90vw">
|
||||
<div class="q-dialog-plugin" style="width: 900px; max-width: 90vw">
|
||||
<q-card>
|
||||
<q-bar>
|
||||
<q-btn ref="refresh" @click="refresh" class="q-mr-sm" dense flat push icon="refresh" />Alerts Manager
|
||||
@@ -9,7 +9,7 @@
|
||||
<q-tooltip content-class="bg-white text-primary">Close</q-tooltip>
|
||||
</q-btn>
|
||||
</q-bar>
|
||||
<div class="q-pa-md">
|
||||
<div class="q-pa-md" style="min-height: 65vh; max-height: 65vh">
|
||||
<div class="q-gutter-sm">
|
||||
<q-btn ref="new" label="New" dense flat push unelevated no-caps icon="add" @click="showAddTemplateModal" />
|
||||
<q-btn
|
||||
@@ -47,28 +47,30 @@
|
||||
row-key="id"
|
||||
binary-state-sort
|
||||
hide-pagination
|
||||
:hide-bottom="!!selected"
|
||||
no-data-label="No Alert Templates"
|
||||
>
|
||||
<!-- header slots -->
|
||||
<template v-slot:header="props">
|
||||
<q-tr :props="props">
|
||||
<template v-for="col in props.cols">
|
||||
<q-th v-if="col.name === 'active'" auto-width :key="col.name">
|
||||
<q-th v-if="col.name === 'is_active'" auto-width :key="col.name">
|
||||
<q-icon name="power_settings_new" size="1.5em">
|
||||
<q-tooltip>Enable Template</q-tooltip>
|
||||
</q-icon>
|
||||
</q-th>
|
||||
|
||||
<q-th
|
||||
v-else-if="col.name === 'email_severity' || col.name === 'text_severity'"
|
||||
auto-width
|
||||
:key="col.name"
|
||||
>
|
||||
{{ col.label }}
|
||||
</q-th>
|
||||
|
||||
<q-th v-else :key="col.name" :props="props">{{ col.label }}</q-th>
|
||||
</template>
|
||||
</q-tr>
|
||||
</template>
|
||||
<!-- No data Slot -->
|
||||
<template v-slot:no-data>
|
||||
<div class="full-width row flex-center q-gutter-sm">
|
||||
<span v-if="templates.length === 0">No Templates</span>
|
||||
</div>
|
||||
</template>
|
||||
<!-- body slots -->
|
||||
<template v-slot:body="props">
|
||||
<q-tr
|
||||
@@ -76,11 +78,11 @@
|
||||
class="cursor-pointer"
|
||||
:class="rowSelectedClass(props.row.id, selected)"
|
||||
@click="
|
||||
editTemplateId = props.row.id;
|
||||
editTemplate = props.row;
|
||||
props.selected = true;
|
||||
"
|
||||
@contextmenu="
|
||||
editTemplateId = props.row.id;
|
||||
editTemplate = props.row;
|
||||
props.selected = true;
|
||||
"
|
||||
>
|
||||
@@ -102,22 +104,6 @@
|
||||
|
||||
<q-separator></q-separator>
|
||||
|
||||
<q-item clickable v-close-popup @click="ResetPassword(props.row)" id="context-reset">
|
||||
<q-item-section side>
|
||||
<q-icon name="autorenew" />
|
||||
</q-item-section>
|
||||
<q-item-section>Reset Password</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item clickable v-close-popup @click="reset2FA(props.row)" id="context-reset">
|
||||
<q-item-section side>
|
||||
<q-icon name="autorenew" />
|
||||
</q-item-section>
|
||||
<q-item-section>Reset Two-Factor Auth</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-separator></q-separator>
|
||||
|
||||
<q-item clickable v-close-popup>
|
||||
<q-item-section>Close</q-item-section>
|
||||
</q-item>
|
||||
@@ -127,7 +113,56 @@
|
||||
<q-td>
|
||||
<q-checkbox dense @input="toggleEnabled(props.row)" v-model="props.row.is_active" />
|
||||
</q-td>
|
||||
<!-- name -->
|
||||
<q-td>{{ props.row.name }}</q-td>
|
||||
<!-- email severity -->
|
||||
<q-td>
|
||||
<q-icon v-if="props.row.email_alert_severity.includes('info')" color="primary" name="info" size="sm">
|
||||
<q-tooltip>Sends email alert on informational severity</q-tooltip>
|
||||
</q-icon>
|
||||
<q-icon
|
||||
v-if="props.row.email_alert_severity.includes('warning')"
|
||||
color="warning"
|
||||
name="warning"
|
||||
size="sm"
|
||||
>
|
||||
<q-tooltip>Sends email alert on warning severity</q-tooltip>
|
||||
</q-icon>
|
||||
<q-icon
|
||||
v-if="props.row.email_alert_severity.includes('error')"
|
||||
color="negative"
|
||||
name="error"
|
||||
size="sm"
|
||||
>
|
||||
<q-tooltip>Sends email alert on error severity</q-tooltip>
|
||||
</q-icon>
|
||||
</q-td>
|
||||
<!-- text severity -->
|
||||
<q-td>
|
||||
<q-icon v-if="props.row.email_alert_severity.includes('info')" color="primary" name="info" size="sm">
|
||||
<q-tooltip>Sends text alert on informational severity</q-tooltip>
|
||||
</q-icon>
|
||||
<q-icon
|
||||
v-if="props.row.text_alert_severity.includes('warning')"
|
||||
color="warning"
|
||||
name="warning"
|
||||
size="sm"
|
||||
>
|
||||
<q-tooltip>Sends text alert on warning severity</q-tooltip>
|
||||
</q-icon>
|
||||
<q-icon
|
||||
v-if="props.row.text_alert_severity.includes('error')"
|
||||
color="negative"
|
||||
name="error"
|
||||
size="sm"
|
||||
>
|
||||
<q-tooltip>Sends text alert on error severity</q-tooltip>
|
||||
</q-icon>
|
||||
</q-td>
|
||||
<!-- applied to -->
|
||||
<q-td>Applied To Placeholder</q-td>
|
||||
<!-- actions -->
|
||||
<q-td>{{ props.row.actions.length }} actions</q-td>
|
||||
</q-tr>
|
||||
</template>
|
||||
</q-table>
|
||||
@@ -138,7 +173,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mixins, { notifySuccessConfig, notifyErrorConfig } from "@/mixins/mixins";
|
||||
import mixins from "@/mixins/mixins";
|
||||
import AlertTemplateForm from "@/components/modals/alerts/AlertTemplateForm";
|
||||
|
||||
export default {
|
||||
@@ -155,18 +190,24 @@ export default {
|
||||
name: "email_severity",
|
||||
label: "Email Severity",
|
||||
field: "email_severity",
|
||||
align: "left",
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
name: "text_severity",
|
||||
label: "Text Severity",
|
||||
field: "text_severity",
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
name: "applied_to",
|
||||
label: "Applied To",
|
||||
field: "applied_to",
|
||||
align: "left",
|
||||
},
|
||||
{
|
||||
name: "last_login",
|
||||
label: "Last Login",
|
||||
field: "last_login",
|
||||
name: "actions",
|
||||
label: "Actions",
|
||||
field: "actions",
|
||||
align: "left",
|
||||
},
|
||||
],
|
||||
@@ -196,37 +237,49 @@ export default {
|
||||
this.getTemplates();
|
||||
this.clearRow();
|
||||
},
|
||||
deleteTemplate(data) {
|
||||
deleteTemplate(template) {
|
||||
this.$q
|
||||
.dialog({
|
||||
title: `Delete template ${data.name}?`,
|
||||
title: `Delete alert template ${template.name}?`,
|
||||
cancel: true,
|
||||
ok: { label: "Delete", color: "negative" },
|
||||
})
|
||||
.onOk(() => {
|
||||
this.$store
|
||||
.dispatch("admin/deleteTemplate", data.id)
|
||||
.then(response => {
|
||||
this.$q.notify(notifySuccessConfig(`Template ${data.name} was deleted!`));
|
||||
this.$q.loading.show();
|
||||
this.$axios
|
||||
.delete(`alerts/alerttemplates/${template.id}/`)
|
||||
.then(r => {
|
||||
this.getTemplates();
|
||||
this.$q.loading.hide();
|
||||
this.notifySuccess(`Alert template ${template.name} was deleted!`);
|
||||
})
|
||||
.catch(error => {
|
||||
this.$q.notify(notifyErrorConfig(`An Error occured while deleting template ${data.name}`));
|
||||
this.$q.loading.hide();
|
||||
this.notifyError(`An Error occured while deleting alert template: ${template.name}`);
|
||||
});
|
||||
});
|
||||
},
|
||||
showEditTemplateModal(data) {
|
||||
this.$q.dialog({
|
||||
component: AlertTemplateForm,
|
||||
parent: this,
|
||||
alertTemplate: data,
|
||||
});
|
||||
showEditTemplateModal(template) {
|
||||
this.$q
|
||||
.dialog({
|
||||
component: AlertTemplateForm,
|
||||
parent: this,
|
||||
alertTemplate: template,
|
||||
})
|
||||
.onOk(() => {
|
||||
this.refresh();
|
||||
});
|
||||
},
|
||||
showAddTemplateModal() {
|
||||
this.clearRow();
|
||||
this.$q.dialog({
|
||||
component: AlertTemplateForm,
|
||||
parent: this,
|
||||
});
|
||||
this.$q
|
||||
.dialog({
|
||||
component: AlertTemplateForm,
|
||||
parent: this,
|
||||
})
|
||||
.onOk(() => {
|
||||
this.refresh();
|
||||
});
|
||||
},
|
||||
toggleEnabled(template) {
|
||||
let text = template.is_active ? "Template enabled successfully" : "Template disabled successfully";
|
||||
@@ -237,12 +290,12 @@ export default {
|
||||
};
|
||||
|
||||
this.$axios
|
||||
.put("alerts/alerttemplates", data)
|
||||
.put(`alerts/alerttemplates/${template.id}/`, data)
|
||||
.then(r => {
|
||||
this.$q.notifySuccess(text);
|
||||
this.notifySuccess(text);
|
||||
})
|
||||
.catch(error => {
|
||||
this.$q.notifyError("An Error occured while editing the template");
|
||||
this.notifyError("An Error occured while editing the template");
|
||||
});
|
||||
},
|
||||
rowSelectedClass(id, selected) {
|
||||
@@ -259,7 +312,7 @@ export default {
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.refresh();
|
||||
this.getTemplates();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -416,16 +416,12 @@ export default {
|
||||
this.selectedScript = {};
|
||||
},
|
||||
viewCode(script) {
|
||||
this.$q
|
||||
.dialog({
|
||||
component: ScriptFormModal,
|
||||
parent: this,
|
||||
script: script,
|
||||
readonly: true,
|
||||
})
|
||||
.onDismiss(() => {
|
||||
this.getScripts();
|
||||
});
|
||||
this.$q.dialog({
|
||||
component: ScriptFormModal,
|
||||
parent: this,
|
||||
script: script,
|
||||
readonly: true,
|
||||
});
|
||||
},
|
||||
favoriteScript(script) {
|
||||
this.$q.loading.show();
|
||||
@@ -495,7 +491,7 @@ export default {
|
||||
categories: this.categories,
|
||||
readonly: false,
|
||||
})
|
||||
.onDismiss(() => {
|
||||
.onOk(() => {
|
||||
this.getScripts();
|
||||
});
|
||||
},
|
||||
@@ -508,7 +504,7 @@ export default {
|
||||
categories: this.categories,
|
||||
readonly: false,
|
||||
})
|
||||
.onDismiss(() => {
|
||||
.onOk(() => {
|
||||
this.getScripts();
|
||||
});
|
||||
},
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
row-key="id"
|
||||
binary-state-sort
|
||||
hide-pagination
|
||||
:hide-bottom="!!selected"
|
||||
no-data-label="No Policies"
|
||||
>
|
||||
<!-- header slots -->
|
||||
<template v-slot:header="props">
|
||||
@@ -81,12 +81,6 @@
|
||||
</template>
|
||||
</q-tr>
|
||||
</template>
|
||||
<!-- No data Slot -->
|
||||
<template v-slot:no-data>
|
||||
<div class="full-width row flex-center q-gutter-sm">
|
||||
<span v-if="policies.length === 0">No Policies</span>
|
||||
</div>
|
||||
</template>
|
||||
<!-- body slots -->
|
||||
<template v-slot:body="props">
|
||||
<q-tr :props="props" class="cursor-pointer" @click="props.selected = true">
|
||||
@@ -130,6 +124,13 @@
|
||||
<q-item-section>{{ patchPolicyText(props.row) }}</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item clickable v-close-popup @click="showAlertTemplateAdd(props.row)">
|
||||
<q-item-section side>
|
||||
<q-icon name="warning" />
|
||||
</q-item-section>
|
||||
<q-item-section>{{ alertTemplateText(props.row) }}</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-separator></q-separator>
|
||||
|
||||
<q-item clickable v-close-popup>
|
||||
@@ -171,6 +172,14 @@
|
||||
>{{ patchPolicyText(props.row) }}</span
|
||||
>
|
||||
</q-td>
|
||||
<q-td>
|
||||
<span
|
||||
style="cursor: pointer; text-decoration: underline"
|
||||
class="text-primary"
|
||||
@click="showAlertTemplateAdd(props.row)"
|
||||
>{{ alertTemplateText(props.row) }}</span
|
||||
>
|
||||
</q-td>
|
||||
<q-td>
|
||||
<q-icon name="content_copy" size="1.5em" @click="showCopyPolicyModal(props.row)">
|
||||
<q-tooltip>Create a copy of this policy</q-tooltip>
|
||||
@@ -270,6 +279,12 @@ export default {
|
||||
field: "winupdatepolicy",
|
||||
align: "left",
|
||||
},
|
||||
{
|
||||
name: "alert_template",
|
||||
label: "Alert Template",
|
||||
field: "alert_template",
|
||||
align: "left",
|
||||
},
|
||||
{
|
||||
name: "actions",
|
||||
label: "Actions",
|
||||
@@ -391,6 +406,9 @@ export default {
|
||||
return this.policy.winupdatepolicy.length === 1 ? "Edit Patch Policy" : "Add Patch Policy";
|
||||
}
|
||||
},
|
||||
alertTemplateText(policy) {
|
||||
return this.policy.alert_template ? "Modify Alert Template" : "Assign Alert Template";
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
|
||||
126
src/components/modals/alerts/AlertTemplateAdd.vue
Normal file
126
src/components/modals/alerts/AlertTemplateAdd.vue
Normal file
@@ -0,0 +1,126 @@
|
||||
<template>
|
||||
<q-dialog ref="dialog" @hide="onHide">
|
||||
<q-card class="q-dialog-plugin" style="width: 60vw">
|
||||
<q-bar>
|
||||
Edit Alert Template assigned to {{ type }}
|
||||
<q-space />
|
||||
<q-btn dense flat icon="close" v-close-popup>
|
||||
<q-tooltip content-class="bg-white text-primary">Close</q-tooltip>
|
||||
</q-btn>
|
||||
</q-bar>
|
||||
<q-form @submit.prevent="submit" ref="form">
|
||||
<q-card-section v-if="options.length > 0">
|
||||
<q-select
|
||||
v-model="selectedTemplate"
|
||||
:options="options"
|
||||
outlined
|
||||
dense
|
||||
clearable
|
||||
emit-value
|
||||
map-options
|
||||
:label="capitalize(type) + ' Alert Template'"
|
||||
>
|
||||
</q-select>
|
||||
</q-card-section>
|
||||
<q-card-section v-else> No Alert Templates have been setup. Go to Settings > Alerts Manager </q-card-section>
|
||||
<q-card-actions align="right">
|
||||
<q-btn dense flat label="Cancel" v-close-popup />
|
||||
<q-btn v-if="options.length > 0" flat label="Submit" color="primary" type="submit" />
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mixins from "@/mixins/mixins";
|
||||
|
||||
export default {
|
||||
name: "AlertTemplateAdd",
|
||||
props: {
|
||||
object: !Object,
|
||||
type: {
|
||||
required: true,
|
||||
type: String,
|
||||
validator: function (value) {
|
||||
// The value must match one of these strings
|
||||
return ["site", "client", "policy"].includes(value);
|
||||
},
|
||||
},
|
||||
},
|
||||
mixins: [mixins],
|
||||
data() {
|
||||
return {
|
||||
selectedTemplate: null,
|
||||
options: [],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
submit() {
|
||||
// close because nothing was edited
|
||||
if (this.object.alertTemplate === this.selectedTemplate) {
|
||||
this.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
this.$q.loading.show();
|
||||
|
||||
const data = {
|
||||
id: this.object.id,
|
||||
alert_template: this.selectedTemplate,
|
||||
};
|
||||
|
||||
let url = "";
|
||||
if (this.type === "client") url = `/clients/${this.object.id}/client/`;
|
||||
else if (this.type === "site") url = `/clients/${this.object.id}/site/`;
|
||||
else if (this.type === "policy") url = `/automation/${this.object.id}/policy/`;
|
||||
|
||||
const text = this.selectedTemplate ? "assigned" : "removed";
|
||||
this.$axios
|
||||
.put(url, data)
|
||||
.then(r => {
|
||||
this.$q.loading.hide();
|
||||
this.onOk();
|
||||
this.notifySuccess(`Alert Template ${text} successfully!`);
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError("Something went wrong!");
|
||||
});
|
||||
},
|
||||
getAlertTemplates() {
|
||||
this.$q.loading.show();
|
||||
this.$axios
|
||||
.get("/alerts/alerttemplates")
|
||||
.then(r => {
|
||||
this.options = r.data.map(template => ({
|
||||
label: template.name,
|
||||
value: template.id,
|
||||
}));
|
||||
this.$q.loading.hide();
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError("Add error occured while loading alert templates");
|
||||
});
|
||||
},
|
||||
show() {
|
||||
this.$refs.dialog.show();
|
||||
},
|
||||
hide() {
|
||||
this.$refs.dialog.hide();
|
||||
},
|
||||
onHide() {
|
||||
this.$emit("hide");
|
||||
},
|
||||
onOk() {
|
||||
this.$emit("ok");
|
||||
this.hide();
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.getAlertTemplates();
|
||||
this.selectedTemplate = this.object.alertTemplate;
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -1,75 +1,178 @@
|
||||
<template>
|
||||
<q-card style="width: 70vw">
|
||||
<q-bar>
|
||||
{{ title }}
|
||||
<q-space />
|
||||
<q-btn dense flat icon="close" v-close-popup>
|
||||
<q-tooltip content-class="bg-white text-primary">Close</q-tooltip>
|
||||
</q-btn>
|
||||
</q-bar>
|
||||
<q-form ref="form" @submit="onSubmit">
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">Name:</div>
|
||||
<div class="col-10">
|
||||
<q-input outlined dense v-model="name" :rules="[val => !!val || '*Required']" class="q-pa-none" />
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="row" v-if="!this.pk">
|
||||
<div class="col-2">Password:</div>
|
||||
<div class="col-10">
|
||||
<q-input
|
||||
outlined
|
||||
dense
|
||||
v-model="password"
|
||||
:type="isPwd ? 'password' : 'text'"
|
||||
:rules="[val => !!val || '*Required']"
|
||||
class="q-pa-none"
|
||||
>
|
||||
<template v-slot:append>
|
||||
<q-icon :name="isPwd ? 'visibility_off' : 'visibility'" class="cursor-pointer" @click="isPwd = !isPwd" />
|
||||
</template>
|
||||
</q-input>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">Email:</div>
|
||||
<div class="col-10">
|
||||
<q-input
|
||||
outlined
|
||||
dense
|
||||
v-model="email"
|
||||
:rules="[val => isValidEmail(val) || 'Invalid email']"
|
||||
class="q-pa-none"
|
||||
/>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">First Name:</div>
|
||||
<div class="col-10">
|
||||
<q-input outlined dense v-model="first_name" />
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">Last Name:</div>
|
||||
<div class="col-10">
|
||||
<q-input outlined dense v-model="last_name" />
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">Active:</div>
|
||||
<div class="col-10">
|
||||
<q-toggle v-model="is_active" color="green" :disable="username === logged_in_user" />
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="row items-center">
|
||||
<q-btn :label="title" color="primary" type="submit" />
|
||||
</q-card-section>
|
||||
</q-form>
|
||||
</q-card>
|
||||
<q-dialog ref="dialog" @hide="onHide">
|
||||
<q-card style="min-width: 70vw">
|
||||
<q-bar>
|
||||
{{ title }}
|
||||
<q-space />
|
||||
<q-btn dense flat icon="close" v-close-popup>
|
||||
<q-tooltip content-class="bg-white text-primary">Close</q-tooltip>
|
||||
</q-btn>
|
||||
</q-bar>
|
||||
<q-form ref="form" @submit.prevent="onSubmit">
|
||||
<q-scroll-area :thumb-style="thumbStyle" style="height: 60vh">
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">Name:</div>
|
||||
<div class="col-10">
|
||||
<q-input outlined dense v-model="template.name" :rules="[val => !!val || '*Required']" />
|
||||
</div>
|
||||
<div class="col-2">Active:</div>
|
||||
<div class="col-10">
|
||||
<q-toggle v-model="template.is_active" color="green" />
|
||||
</div>
|
||||
<div class="col-2">Action:</div>
|
||||
<div class="col-10">
|
||||
<q-select
|
||||
hint="optionally run a set of scripts which an alert is triggered"
|
||||
dense
|
||||
options-dense
|
||||
outlined
|
||||
multiple
|
||||
v-model="template.actions"
|
||||
:options="scriptOptions"
|
||||
use-chips
|
||||
map-options
|
||||
emit-value
|
||||
/>
|
||||
</div>
|
||||
</q-card-section>
|
||||
|
||||
<div class="q-pl-md text-subtitle1">Email Settings</div>
|
||||
<q-separator class="q-mb-sm" />
|
||||
|
||||
<q-card-section class="row">
|
||||
<div class="col-2 q-mb-sm">Email recipients:</div>
|
||||
<div class="col-4 q-mb-sm">
|
||||
<q-list dense v-if="template.email_recipients.length !== 0">
|
||||
<q-item v-for="email in template.email_recipients" :key="email" dense>
|
||||
<q-item-section>
|
||||
<q-item-label>{{ email }}</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side>
|
||||
<q-icon class="cursor-pointer" name="delete" color="red" @click="removeEmail(email)" />
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
<q-list v-else>
|
||||
<q-item-section>
|
||||
<q-item-label>No recipients</q-item-label>
|
||||
</q-item-section>
|
||||
</q-list>
|
||||
</div>
|
||||
<div class="col-3 q-mb-sm"></div>
|
||||
<div class="col-3 q-mb-sm">
|
||||
<q-btn size="sm" icon="fas fa-plus" color="secondary" label="Add email" @click="toggleAddEmail" />
|
||||
</div>
|
||||
|
||||
<div class="col-2">Email From address:</div>
|
||||
<div class="col-10">
|
||||
<q-input
|
||||
hint="Will override the global settings From: address"
|
||||
class="q-mb-sm"
|
||||
outlined
|
||||
dense
|
||||
v-model="template.email_from"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="col-2">Email on severity:</div>
|
||||
<div class="col-10">
|
||||
<q-select
|
||||
v-model="template.email_alert_severity"
|
||||
outlined
|
||||
dense
|
||||
multiple
|
||||
use-chips
|
||||
emit-value
|
||||
map-options
|
||||
:options="severityOptions"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="col-2">Email on resolved:</div>
|
||||
<div class="col-4">
|
||||
<q-toggle v-model="template.email_on_resolved" color="green" />
|
||||
</div>
|
||||
</q-card-section>
|
||||
|
||||
<div class="q-pl-md text-subtitle1">SMS Settings</div>
|
||||
<q-separator class="q-mb-sm" />
|
||||
|
||||
<q-card-section class="row">
|
||||
<div class="col-2 q-mb-sm">SMS recipients:</div>
|
||||
<div class="col-4 q-mb-md">
|
||||
<q-list dense v-if="template.text_recipients.length !== 0">
|
||||
<q-item v-for="num in template.text_recipients" :key="num" dense>
|
||||
<q-item-section>
|
||||
<q-item-label>{{ num }}</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side>
|
||||
<q-icon class="cursor-pointer" name="delete" color="red" @click="removeSMSNumber(num)" />
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
<q-list v-else>
|
||||
<q-item-section>
|
||||
<q-item-label>No recipients</q-item-label>
|
||||
</q-item-section>
|
||||
</q-list>
|
||||
</div>
|
||||
<div class="col-3 q-mb-sm"></div>
|
||||
<div class="col-3 q-mb-sm">
|
||||
<q-btn
|
||||
class="cursor-pointer"
|
||||
size="sm"
|
||||
icon="fas fa-plus"
|
||||
color="secondary"
|
||||
label="Add sms number"
|
||||
@click="toggleAddSMSNumber"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="col-2">SMS on severity:</div>
|
||||
<div class="col-10">
|
||||
<q-select
|
||||
v-model="template.text_alert_severity"
|
||||
outlined
|
||||
dense
|
||||
multiple
|
||||
use-chips
|
||||
emit-value
|
||||
map-options
|
||||
:options="severityOptions"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="col-2">SMS on resolved:</div>
|
||||
<div class="col-4">
|
||||
<q-toggle v-model="template.text_on_resolved" color="green" />
|
||||
</div>
|
||||
</q-card-section>
|
||||
|
||||
<div class="q-pl-md text-subtitle1">Override agent alert settings</div>
|
||||
<q-separator class="q-mb-sm" />
|
||||
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">Always email:</div>
|
||||
<div class="col-4">
|
||||
<q-toggle v-model="template.always_email" color="green" />
|
||||
</div>
|
||||
<div class="col-2">Always sms:</div>
|
||||
<div class="col-4">
|
||||
<q-toggle v-model="template.always_text" color="green" />
|
||||
</div>
|
||||
</q-card-section>
|
||||
</q-scroll-area>
|
||||
|
||||
<q-card-actions align="right">
|
||||
<q-btn dense flat label="Cancel" v-close-popup />
|
||||
<q-btn dense flat label="Save" color="primary" type="submit" />
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from "vuex";
|
||||
import mixins from "@/mixins/mixins";
|
||||
|
||||
export default {
|
||||
@@ -77,62 +180,143 @@ export default {
|
||||
mixins: [mixins],
|
||||
props: { alertTemplate: Object },
|
||||
data() {
|
||||
return {};
|
||||
return {
|
||||
template: {
|
||||
actions: [],
|
||||
name: "",
|
||||
is_active: true,
|
||||
always_email: false,
|
||||
always_text: false,
|
||||
email_recipients: [],
|
||||
email_from: "",
|
||||
email_alert_severity: [],
|
||||
text_alert_severity: [],
|
||||
text_recipients: [],
|
||||
email_on_resolved: false,
|
||||
text_on_resolved: false,
|
||||
},
|
||||
scriptOptions: [],
|
||||
severityOptions: [
|
||||
{ label: "Error", value: "error" },
|
||||
{ label: "Warning", value: "warning" },
|
||||
{ label: "Informational", value: "info" },
|
||||
],
|
||||
thumbStyle: {
|
||||
right: "2px",
|
||||
borderRadius: "5px",
|
||||
backgroundColor: "#027be3",
|
||||
width: "5px",
|
||||
opacity: 0.75,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
title() {
|
||||
return this.editing ? "Edit User" : "Add User";
|
||||
return this.editing ? "Edit Alert Template" : "Add Alert Template";
|
||||
},
|
||||
editing() {
|
||||
return !!this.alertTemplate;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
toggleAddEmail() {
|
||||
this.$q
|
||||
.dialog({
|
||||
title: "Add email",
|
||||
prompt: {
|
||||
model: "",
|
||||
isValid: val => this.isValidEmail(val),
|
||||
type: "email",
|
||||
},
|
||||
cancel: true,
|
||||
ok: { label: "Add", color: "primary" },
|
||||
persistent: false,
|
||||
})
|
||||
.onOk(data => {
|
||||
this.template.email_recipients.push(data);
|
||||
});
|
||||
},
|
||||
toggleAddSMSNumber() {
|
||||
this.$q
|
||||
.dialog({
|
||||
title: "Add number",
|
||||
message:
|
||||
"Use E.164 format: must have the <b>+</b> symbol and <span class='text-red'>country code</span>, followed by the <span class='text-green'>phone number</span> e.g. <b>+<span class='text-red'>1</span><span class='text-green'>2131231234</span></b>",
|
||||
prompt: {
|
||||
model: "",
|
||||
},
|
||||
html: true,
|
||||
cancel: true,
|
||||
ok: { label: "Add", color: "primary" },
|
||||
persistent: false,
|
||||
})
|
||||
.onOk(data => {
|
||||
this.template.text_recipients.push(data);
|
||||
});
|
||||
},
|
||||
removeEmail(email) {
|
||||
const removed = this.template.email_recipients.filter(k => k !== email);
|
||||
this.template.email_recipients = removed;
|
||||
},
|
||||
removeSMSNumber(num) {
|
||||
const removed = this.template.text_recipients.filter(k => k !== num);
|
||||
this.template.text_recipients = removed;
|
||||
},
|
||||
onSubmit() {
|
||||
this.$q.loading.show();
|
||||
|
||||
let formData = {
|
||||
id: this.pk,
|
||||
username: this.username,
|
||||
email: this.email,
|
||||
is_active: this.is_active,
|
||||
first_name: this.first_name,
|
||||
last_name: this.last_name,
|
||||
};
|
||||
|
||||
if (this.editing) {
|
||||
// dont allow updating is_active if username is same as logged in user
|
||||
if (formData.username === this.logged_in_user) {
|
||||
delete formData.is_active;
|
||||
}
|
||||
|
||||
this.$store
|
||||
.dispatch("admin/editUser", formData)
|
||||
this.$axios
|
||||
.put(`alerts/alerttemplates/${this.template.id}/`, this.template)
|
||||
.then(r => {
|
||||
this.$q.loading.hide();
|
||||
this.$emit("close");
|
||||
this.$q.notify(notifySuccessConfig("User edited!"));
|
||||
this.onOK();
|
||||
this.notifySuccess("Alert Template edited!");
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
this.$q.notify(notifyErrorConfig(e.response.data));
|
||||
this.notifyError(e.response.data);
|
||||
});
|
||||
} else {
|
||||
formData.password = this.password;
|
||||
|
||||
this.$store
|
||||
.dispatch("admin/addUser", formData)
|
||||
this.$axios
|
||||
.post("alerts/alerttemplates/", this.template)
|
||||
.then(r => {
|
||||
this.$q.loading.hide();
|
||||
this.$emit("close");
|
||||
this.$q.notify(notifySuccessConfig(`User ${r.data} was added!`));
|
||||
this.onOK();
|
||||
this.notifySuccess(`Alert Template was added!`);
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
this.$q.notify(notifyErrorConfig(e.response.data));
|
||||
this.notifyError(e);
|
||||
});
|
||||
}
|
||||
},
|
||||
getScripts() {
|
||||
this.$axios.get("/scripts/scripts/").then(r => {
|
||||
this.scriptOptions = r.data
|
||||
.map(script => ({ label: script.name, value: script.id }))
|
||||
.sort((a, b) => a.label.localeCompare(b.label));
|
||||
});
|
||||
},
|
||||
show() {
|
||||
this.$refs.dialog.show();
|
||||
},
|
||||
hide() {
|
||||
this.$refs.dialog.hide();
|
||||
},
|
||||
onHide() {
|
||||
this.$emit("hide");
|
||||
},
|
||||
onOK() {
|
||||
this.$emit("ok");
|
||||
this.hide();
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
// Copy alertTemplate prop locally
|
||||
if (this.editing) Object.assign(this.template, this.alertTemplate);
|
||||
|
||||
this.getScripts();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -51,8 +51,8 @@
|
||||
<q-input
|
||||
outlined
|
||||
dense
|
||||
v-model.number="scriptcheck.timeout"
|
||||
label="Timeout (seconds)"
|
||||
v-model.number="scriptcheck.info_return_codes"
|
||||
label="Informational alert return codes"
|
||||
:rules="[
|
||||
val => !!val || '*Required',
|
||||
val => val >= 10 || 'Minimum is 10 seconds',
|
||||
@@ -61,16 +61,10 @@
|
||||
/>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<q-select
|
||||
outlined
|
||||
dense
|
||||
options-dense
|
||||
map-options
|
||||
emit-value
|
||||
v-model="scriptcheck.alert_severity"
|
||||
:options="severityOptions"
|
||||
label="Alert Severity"
|
||||
/>
|
||||
<q-input outlined dense v-model.number="scriptcheck.warning_return_codes" label="Warning alert return codes" />
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<q-input outlined dense v-model.number="scriptcheck.timeout" label="Timeout (seconds)" />
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<q-select
|
||||
@@ -110,13 +104,9 @@ export default {
|
||||
script_args: [],
|
||||
timeout: 120,
|
||||
fails_b4_alert: 1,
|
||||
alert_severity: "warning",
|
||||
info_return_codes: "",
|
||||
warning_return_codes: "",
|
||||
},
|
||||
severityOptions: [
|
||||
{ label: "Informational", value: "info" },
|
||||
{ label: "Warning", value: "warning" },
|
||||
{ label: "Error", value: "error" },
|
||||
],
|
||||
scriptOptions: [],
|
||||
failOptions: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
|
||||
};
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
dense
|
||||
options-dense
|
||||
v-model="settings.alert_template"
|
||||
:options="templates"
|
||||
:options="alertTemplateOptions"
|
||||
class="col-6"
|
||||
/>
|
||||
</q-card-section>
|
||||
@@ -339,6 +339,7 @@ export default {
|
||||
width: "5px",
|
||||
opacity: 0.75,
|
||||
},
|
||||
alertTemplateOptions: [],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
@@ -354,6 +355,11 @@ export default {
|
||||
this.notifyError(e.response.data);
|
||||
});
|
||||
},
|
||||
getAlertTemplates() {
|
||||
this.$axios.get("alerts/alerttemplates").then(r => {
|
||||
this.alertTemplateOptions = r.data.map(template => ({ label: template.name, value: template.id }));
|
||||
});
|
||||
},
|
||||
toggleAddEmail() {
|
||||
this.$q
|
||||
.dialog({
|
||||
@@ -441,6 +447,7 @@ export default {
|
||||
created() {
|
||||
this.getCoreSettings();
|
||||
this.getPolicies();
|
||||
this.getAlertTemplates();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -77,8 +77,7 @@
|
||||
:style="heightVar"
|
||||
lineNumbers
|
||||
></prism-editor>
|
||||
<q-card-actions v-if="!readonly">
|
||||
<q-space />
|
||||
<q-card-actions v-if="!readonly" align="right">
|
||||
<q-btn dense flat label="Cancel" v-close-popup />
|
||||
<q-btn dense flat label="Save" color="primary" type="submit" />
|
||||
</q-card-actions>
|
||||
@@ -138,7 +137,7 @@ export default {
|
||||
.put(`/scripts/${this.script.id}/script/`, this.localScript)
|
||||
.then(r => {
|
||||
this.$q.loading.hide();
|
||||
this.$emit("hide");
|
||||
this.onOk();
|
||||
this.notifySuccess(r.data);
|
||||
})
|
||||
.catch(e => {
|
||||
@@ -150,7 +149,7 @@ export default {
|
||||
.post(`/scripts/scripts/`, this.localScript)
|
||||
.then(r => {
|
||||
this.$q.loading.hide();
|
||||
this.$emit("hide");
|
||||
this.onOk();
|
||||
this.notifySuccess(r.data);
|
||||
})
|
||||
.catch(e => {
|
||||
@@ -185,6 +184,13 @@ export default {
|
||||
onHide() {
|
||||
this.$emit("hide");
|
||||
},
|
||||
onOk() {
|
||||
this.$emit("ok");
|
||||
this.hide();
|
||||
},
|
||||
onCancel() {
|
||||
this.hide();
|
||||
},
|
||||
filterFn(val, update) {
|
||||
update(() => {
|
||||
if (val === "") {
|
||||
|
||||
@@ -229,6 +229,8 @@ export default function () {
|
||||
this.$router.push({ name: "InitialSetup" });
|
||||
}
|
||||
|
||||
console.log(r.data)
|
||||
|
||||
let output = [];
|
||||
for (let client of r.data) {
|
||||
|
||||
@@ -241,6 +243,9 @@ export default function () {
|
||||
raw: `Site|${site.id}`,
|
||||
header: "generic",
|
||||
icon: "apartment",
|
||||
serverPolicy: site.server_policy,
|
||||
workstationPolicy: site.workstation_policy,
|
||||
alertTemplate: site.alert_template
|
||||
}
|
||||
|
||||
if (site.maintenance_mode) { siteNode["color"] = "warning" }
|
||||
@@ -255,6 +260,9 @@ export default function () {
|
||||
raw: `Client|${client.id}`,
|
||||
header: "root",
|
||||
icon: "business",
|
||||
serverPolicy: client.server_policy,
|
||||
workstationPolicy: client.workstation_policy,
|
||||
alertTemplate: client.alert_template,
|
||||
children: childSites
|
||||
}
|
||||
|
||||
|
||||
@@ -157,7 +157,14 @@
|
||||
<q-item-section side>
|
||||
<q-icon name="policy" />
|
||||
</q-item-section>
|
||||
<q-item-section>Edit Policies</q-item-section>
|
||||
<q-item-section>Assign Automation Policy</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item clickable v-close-popup @click="showAlertTemplateAdd(props.node)">
|
||||
<q-item-section side>
|
||||
<q-icon name="error" />
|
||||
</q-item-section>
|
||||
<q-item-section>Assign Alert Template</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-separator></q-separator>
|
||||
@@ -378,6 +385,7 @@ import ClientsForm from "@/components/modals/clients/ClientsForm";
|
||||
import SitesForm from "@/components/modals/clients/SitesForm";
|
||||
import InstallAgent from "@/components/modals/agents/InstallAgent";
|
||||
import UserPreferences from "@/components/modals/coresettings/UserPreferences";
|
||||
import AlertTemplateAdd from "@/components/modals/alerts/AlertTemplateAdd";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -654,6 +662,18 @@ export default {
|
||||
this.showInstallAgentModal = false;
|
||||
this.sitePk = null;
|
||||
},
|
||||
showAlertTemplateAdd(node) {
|
||||
this.$q
|
||||
.dialog({
|
||||
component: AlertTemplateAdd,
|
||||
parent: this,
|
||||
type: node.children ? "client" : "site",
|
||||
object: node,
|
||||
})
|
||||
.onOk(() => {
|
||||
this.getTree();
|
||||
});
|
||||
},
|
||||
reload() {
|
||||
this.$store.dispatch("reload");
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user