mirror of
https://github.com/jpros/tacticalrmm-web.git
synced 2026-02-27 23:00:57 +00:00
Policy Overview Add/Edit
This commit is contained in:
@@ -75,15 +75,18 @@
|
||||
>
|
||||
<q-td>{{ props.row.name }}</q-td>
|
||||
<q-td>{{ props.row.desc }}</q-td>
|
||||
<q-td>{{ props.row.applied_to }}</q-td>
|
||||
<q-td>{{ props.row.actions }}</q-td>
|
||||
<q-td>{{ props.row.active }}</q-td>
|
||||
<q-td>{{ props.row.clients.length }}</q-td>
|
||||
<q-td>{{ props.row.sites.length }}</q-td>
|
||||
<q-td>{{ props.row.agents.length }}</q-td>
|
||||
</q-tr>
|
||||
</template>
|
||||
</q-table>
|
||||
</div>
|
||||
<q-card-section></q-card-section>
|
||||
<q-separator />
|
||||
<q-card-section></q-card-section>
|
||||
<q-card-section>
|
||||
<PolicySubTableTabs />
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
<q-dialog v-model="showAddPolicyModal">
|
||||
@@ -105,14 +108,14 @@ import { mapState } from "vuex";
|
||||
import AddPolicy from "@/components/modals/automation/AddPolicy";
|
||||
import EditPolicy from "@/components/modals/automation/EditPolicy";
|
||||
import PolicyOverview from "@/components/modals/automation/PolicyOverview";
|
||||
import PolicySubTableTabs from "@/components/PolicySubTableTabs"
|
||||
|
||||
export default {
|
||||
name: "AutomationManager",
|
||||
components: { AddPolicy, EditPolicy, PolicyOverview },
|
||||
components: { AddPolicy, EditPolicy, PolicyOverview, PolicySubTableTabs },
|
||||
mixins: [mixins],
|
||||
data() {
|
||||
return {
|
||||
selectedRow: null,
|
||||
showAddPolicyModal: false,
|
||||
showEditPolicyModal: false,
|
||||
showPolicyOverviewModal: false,
|
||||
@@ -145,14 +148,28 @@ export default {
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
name: "applied_to",
|
||||
label: "Applied To",
|
||||
field: "applied_to",
|
||||
name: "clients",
|
||||
label: "Clients",
|
||||
field: "clients",
|
||||
align: "left",
|
||||
sortable: false
|
||||
},
|
||||
{
|
||||
name: "sites",
|
||||
label: "Sites",
|
||||
field: "sites",
|
||||
align: "left",
|
||||
sortable: false
|
||||
},
|
||||
{
|
||||
name: "agents",
|
||||
label: "Agents",
|
||||
field: "agents",
|
||||
align: "left",
|
||||
sortable: false
|
||||
}
|
||||
],
|
||||
visibleColumns: ["name", "desc", "active", "applied_to"]
|
||||
visibleColumns: ["name", "desc", "active", "clients", "sites", "agents"]
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
@@ -164,10 +181,12 @@ export default {
|
||||
this.$store.commit("TOGGLE_AUTOMATION_MANAGER", false);
|
||||
},
|
||||
policyRowSelected(pk) {
|
||||
this.selectedRow = pk;
|
||||
this.$store.commit("setSelectedPolicy", pk);
|
||||
this.$store.dispatch("loadPolicyChecks", pk);
|
||||
},
|
||||
clearRow() {
|
||||
this.selectedRow = null;
|
||||
this.$store.commit("setSelectedPolicy", null);
|
||||
this.$store.commit("setPolicyChecks", {});
|
||||
},
|
||||
deletePolicy() {
|
||||
this.$q
|
||||
@@ -179,16 +198,17 @@ export default {
|
||||
.onOk(() => {
|
||||
axios.delete(`/automation/policies/${this.selectedRow}`).then(r => {
|
||||
this.getPolicies();
|
||||
this.notifySuccess(`Policy ${r.data} was deleted!`);
|
||||
this.notifySuccess(`Policy was deleted!`);
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
toggleAutomationManager: state => state.toggleAutomationManager,
|
||||
policies: state => state.policies
|
||||
})
|
||||
policies: state => state.policies,
|
||||
selectedRow: state => state.selectedPolicy
|
||||
}),
|
||||
},
|
||||
mounted() {
|
||||
this.getPolicies();
|
||||
|
||||
429
src/components/PolicyChecksTab.vue
Normal file
429
src/components/PolicyChecksTab.vue
Normal file
@@ -0,0 +1,429 @@
|
||||
<template>
|
||||
<div v-if="Object.keys(checks).length === 0">No policy selected</div>
|
||||
<div class="row" v-else>
|
||||
<div class="col-12">
|
||||
<q-btn size="sm" color="grey-5" icon="fas fa-plus" label="Add Check" text-color="black">
|
||||
<q-menu>
|
||||
<q-list dense style="min-width: 200px">
|
||||
<q-item clickable v-close-popup @click="showAddDiskSpaceCheck = true">
|
||||
<q-item-section side>
|
||||
<q-icon size="xs" name="far fa-hdd" />
|
||||
</q-item-section>
|
||||
<q-item-section>Disk Space Check</q-item-section>
|
||||
</q-item>
|
||||
<q-item clickable v-close-popup @click="showAddPingCheck = true">
|
||||
<q-item-section side>
|
||||
<q-icon size="xs" name="fas fa-network-wired" />
|
||||
</q-item-section>
|
||||
<q-item-section>Ping Check</q-item-section>
|
||||
</q-item>
|
||||
<q-item clickable v-close-popup @click="showAddCpuLoadCheck = true">
|
||||
<q-item-section side>
|
||||
<q-icon size="xs" name="fas fa-microchip" />
|
||||
</q-item-section>
|
||||
<q-item-section>CPU Load Check</q-item-section>
|
||||
</q-item>
|
||||
<q-item clickable v-close-popup @click="showAddMemCheck = true">
|
||||
<q-item-section side>
|
||||
<q-icon size="xs" name="fas fa-memory" />
|
||||
</q-item-section>
|
||||
<q-item-section>Memory Check</q-item-section>
|
||||
</q-item>
|
||||
<q-item clickable v-close-popup @click="showAddWinSvcCheck = true">
|
||||
<q-item-section side>
|
||||
<q-icon size="xs" name="fas fa-cogs" />
|
||||
</q-item-section>
|
||||
<q-item-section>Windows Service Check</q-item-section>
|
||||
</q-item>
|
||||
<q-item clickable v-close-popup @click="showAddScriptCheck = true">
|
||||
<q-item-section side>
|
||||
<q-icon size="xs" name="fas fa-terminal" />
|
||||
</q-item-section>
|
||||
<q-item-section>Script Check</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
</q-btn>
|
||||
<q-btn dense flat push @click="onRefresh(checks.id)" icon="refresh" />
|
||||
<template v-if="allChecks === undefined || allChecks.length === 0">
|
||||
<p>No Checks</p>
|
||||
</template>
|
||||
<template v-else>
|
||||
<q-table
|
||||
dense
|
||||
class="checks-tbl-sticky"
|
||||
:data="allChecks"
|
||||
:columns="columns"
|
||||
:row-key="row => row.id + row.check_type"
|
||||
binary-state-sort
|
||||
:pagination.sync="pagination"
|
||||
hide-bottom
|
||||
>
|
||||
<!-- header slots -->
|
||||
<template v-slot:header-cell-smsalert="props">
|
||||
<q-th auto-width :props="props">
|
||||
<q-icon name="phone_android" size="1.5em">
|
||||
<q-tooltip>SMS Alert</q-tooltip>
|
||||
</q-icon>
|
||||
</q-th>
|
||||
</template>
|
||||
<template v-slot:header-cell-emailalert="props">
|
||||
<q-th auto-width :props="props">
|
||||
<q-icon name="email" size="1.5em">
|
||||
<q-tooltip>Email Alert</q-tooltip>
|
||||
</q-icon>
|
||||
</q-th>
|
||||
</template>
|
||||
<template v-slot:header-cell-statusicon="props">
|
||||
<q-th auto-width :props="props"></q-th>
|
||||
</template>
|
||||
<!-- body slots -->
|
||||
<template slot="body" slot-scope="props" :props="props">
|
||||
<q-tr @contextmenu="editCheckPK = props.row.id">
|
||||
<!-- context menu -->
|
||||
<q-menu context-menu>
|
||||
<q-list dense style="min-width: 200px">
|
||||
<q-item clickable v-close-popup @click="editCheck(props.row.check_type)">
|
||||
<q-item-section side>
|
||||
<q-icon name="edit" />
|
||||
</q-item-section>
|
||||
<q-item-section>Edit</q-item-section>
|
||||
</q-item>
|
||||
<q-item
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="deleteCheck(props.row.id, props.row.check_type)"
|
||||
>
|
||||
<q-item-section side>
|
||||
<q-icon name="delete" />
|
||||
</q-item-section>
|
||||
<q-item-section>Delete</q-item-section>
|
||||
</q-item>
|
||||
<q-separator></q-separator>
|
||||
<q-item clickable v-close-popup>
|
||||
<q-item-section>Close</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
<!-- tds -->
|
||||
<q-td>
|
||||
<q-checkbox
|
||||
dense
|
||||
@input="checkAlertAction(props.row.id, props.row.check_type, 'text', props.row.text_alert)"
|
||||
v-model="props.row.text_alert"
|
||||
/>
|
||||
</q-td>
|
||||
<q-td>
|
||||
<q-checkbox
|
||||
dense
|
||||
@input="checkAlertAction(props.row.id, props.row.check_type, 'email', props.row.email_alert)"
|
||||
v-model="props.row.email_alert"
|
||||
/>
|
||||
</q-td>
|
||||
<q-td v-if="props.row.status === 'pending'"></q-td>
|
||||
<q-td v-else-if="props.row.status === 'passing'">
|
||||
<q-icon style="font-size: 1.3rem;" color="positive" name="check_circle" />
|
||||
</q-td>
|
||||
<q-td v-else-if="props.row.status === 'failing'">
|
||||
<q-icon style="font-size: 1.3rem;" color="negative" name="error" />
|
||||
</q-td>
|
||||
<q-td
|
||||
v-if="props.row.check_type === 'diskspace'"
|
||||
>Disk Space Drive {{ props.row.disk }} > {{props.row.threshold }}%</q-td>
|
||||
<q-td
|
||||
v-else-if="props.row.check_type === 'cpuload'"
|
||||
>Avg CPU Load > {{ props.row.cpuload }}%</q-td>
|
||||
<q-td
|
||||
v-else-if="props.row.check_type === 'script'"
|
||||
>Script check: {{ props.row.script.name }}</q-td>
|
||||
<q-td
|
||||
v-else-if="props.row.check_type === 'ping'"
|
||||
>Ping {{ props.row.name }} ({{ props.row.ip }})</q-td>
|
||||
<q-td
|
||||
v-else-if="props.row.check_type === 'memory'"
|
||||
>Avg memory usage > {{ props.row.threshold }}%</q-td>
|
||||
<q-td
|
||||
v-else-if="props.row.check_type === 'winsvc'"
|
||||
>Service Check - {{ props.row.svc_display_name }}</q-td>
|
||||
<q-td v-if="props.row.status === 'pending'">Awaiting First Synchronization</q-td>
|
||||
<q-td v-else-if="props.row.status === 'passing'">
|
||||
<q-badge color="positive">Passing</q-badge>
|
||||
</q-td>
|
||||
<q-td v-else-if="props.row.status === 'failing'">
|
||||
<q-badge color="negative">Failing</q-badge>
|
||||
</q-td>
|
||||
<q-td v-if="props.row.check_type === 'ping'">
|
||||
<span
|
||||
style="cursor:pointer;color:blue;text-decoration:underline"
|
||||
@click="moreInfo('Ping', props.row.more_info)"
|
||||
>output</span>
|
||||
</q-td>
|
||||
<q-td v-else-if="props.row.check_type === 'script'">
|
||||
<span
|
||||
style="cursor:pointer;color:blue;text-decoration:underline"
|
||||
@click="scriptMoreInfo(props.row)"
|
||||
>output</span>
|
||||
</q-td>
|
||||
<q-td v-else>{{ props.row.more_info }}</q-td>
|
||||
<q-td>{{ props.row.last_run }}</q-td>
|
||||
</q-tr>
|
||||
</template>
|
||||
</q-table>
|
||||
</template>
|
||||
</div>
|
||||
<!-- modals -->
|
||||
<q-dialog v-model="showAddDiskSpaceCheck">
|
||||
<AddDiskSpaceCheck @close="showAddDiskSpaceCheck = false" :policypk="checks.id" />
|
||||
</q-dialog>
|
||||
<q-dialog v-model="showEditDiskSpaceCheck">
|
||||
<EditDiskSpaceCheck
|
||||
@close="showEditDiskSpaceCheck = false"
|
||||
:editCheckPK="editCheckPK"
|
||||
:policypk="checks.id"
|
||||
/>
|
||||
</q-dialog>
|
||||
<q-dialog v-model="showAddPingCheck">
|
||||
<AddPingCheck @close="showAddPingCheck = false" :policypk="checks.id" />
|
||||
</q-dialog>
|
||||
<q-dialog v-model="showEditPingCheck">
|
||||
<EditPingCheck
|
||||
@close="showEditPingCheck = false"
|
||||
:editCheckPK="editCheckPK"
|
||||
:policypk="checks.id"
|
||||
/>
|
||||
</q-dialog>
|
||||
<q-dialog v-model="showAddCpuLoadCheck">
|
||||
<AddCpuLoadCheck @close="showAddCpuLoadCheck = false" :policypk="checks.id" />
|
||||
</q-dialog>
|
||||
<q-dialog v-model="showEditCpuLoadCheck">
|
||||
<EditCpuLoadCheck
|
||||
@close="showEditCpuLoadCheck = false"
|
||||
:editCheckPK="editCheckPK"
|
||||
:policypk="checks.id"
|
||||
/>
|
||||
</q-dialog>
|
||||
|
||||
<q-dialog v-model="showAddMemCheck">
|
||||
<AddMemCheck @close="showAddMemCheck = false" :policypk="checks.id" />
|
||||
</q-dialog>
|
||||
<q-dialog v-model="showEditMemCheck">
|
||||
<EditMemCheck
|
||||
@close="showEditMemCheck = false"
|
||||
:editCheckPK="editCheckPK"
|
||||
:policypk="checks.id"
|
||||
/>
|
||||
</q-dialog>
|
||||
|
||||
<q-dialog v-model="showAddWinSvcCheck">
|
||||
<AddWinSvcCheck @close="showAddWinSvcCheck = false" :policypk="checks.id" />
|
||||
</q-dialog>
|
||||
<q-dialog v-model="showEditWinSvcCheck">
|
||||
<EditWinSvcCheck
|
||||
@close="showEditWinSvcCheck = false"
|
||||
:editCheckPK="editCheckPK"
|
||||
:policypk="checks.id"
|
||||
/>
|
||||
</q-dialog>
|
||||
<!-- script check -->
|
||||
<q-dialog v-model="showAddScriptCheck">
|
||||
<AddScriptCheck @close="showAddScriptCheck = false" :policypk="checks.id" />
|
||||
</q-dialog>
|
||||
<q-dialog v-model="showEditScriptCheck">
|
||||
<EditScriptCheck
|
||||
@close="showEditScriptCheck = false"
|
||||
:editCheckPK="editCheckPK"
|
||||
:policypk="checks.id"
|
||||
/>
|
||||
</q-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from "axios";
|
||||
import { mapState } from "vuex";
|
||||
import mixins from "@/mixins/mixins";
|
||||
import AddDiskSpaceCheck from "@/components/modals/checks/AddDiskSpaceCheck";
|
||||
import EditDiskSpaceCheck from "@/components/modals/checks/EditDiskSpaceCheck";
|
||||
import AddPingCheck from "@/components/modals/checks/AddPingCheck";
|
||||
import EditPingCheck from "@/components/modals/checks/EditPingCheck";
|
||||
import AddCpuLoadCheck from "@/components/modals/checks/AddCpuLoadCheck";
|
||||
import EditCpuLoadCheck from "@/components/modals/checks/EditCpuLoadCheck";
|
||||
import AddMemCheck from "@/components/modals/checks/AddMemCheck";
|
||||
import EditMemCheck from "@/components/modals/checks/EditMemCheck";
|
||||
import AddWinSvcCheck from "@/components/modals/checks/AddWinSvcCheck";
|
||||
import EditWinSvcCheck from "@/components/modals/checks/EditWinSvcCheck";
|
||||
import AddScriptCheck from "@/components/modals/checks/AddScriptCheck";
|
||||
import EditScriptCheck from "@/components/modals/checks/EditScriptCheck";
|
||||
|
||||
export default {
|
||||
name: "PolicyChecksTab",
|
||||
components: {
|
||||
AddDiskSpaceCheck,
|
||||
EditDiskSpaceCheck,
|
||||
AddPingCheck,
|
||||
EditPingCheck,
|
||||
AddCpuLoadCheck,
|
||||
EditCpuLoadCheck,
|
||||
AddMemCheck,
|
||||
EditMemCheck,
|
||||
AddWinSvcCheck,
|
||||
EditWinSvcCheck,
|
||||
AddScriptCheck,
|
||||
EditScriptCheck
|
||||
},
|
||||
mixins: [mixins],
|
||||
data() {
|
||||
return {
|
||||
showAddDiskSpaceCheck: false,
|
||||
showEditDiskSpaceCheck: false,
|
||||
showAddPingCheck: false,
|
||||
showEditPingCheck: false,
|
||||
showAddCpuLoadCheck: false,
|
||||
showEditCpuLoadCheck: false,
|
||||
showAddMemCheck: false,
|
||||
showEditMemCheck: false,
|
||||
showAddWinSvcCheck: false,
|
||||
showEditWinSvcCheck: false,
|
||||
showAddScriptCheck: false,
|
||||
showEditScriptCheck: false,
|
||||
editCheckPK: null,
|
||||
scriptInfo: {},
|
||||
columns: [
|
||||
{ name: "smsalert", field: "text_alert", align: "left" },
|
||||
{ name: "emailalert", field: "email_alert", align: "left" },
|
||||
{ name: "statusicon", align: "left" },
|
||||
{ name: "desc", label: "Description", align: "left" },
|
||||
{ name: "status", label: "Status", field: "status", align: "left" },
|
||||
{
|
||||
name: "moreinfo",
|
||||
label: "More Info",
|
||||
field: "more_info",
|
||||
align: "left"
|
||||
},
|
||||
{
|
||||
name: "datetime",
|
||||
label: "Date / Time",
|
||||
field: "last_run",
|
||||
align: "left"
|
||||
}
|
||||
],
|
||||
pagination: {
|
||||
rowsPerPage: 9999
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
checkAlertAction(pk, category, alert_type, alert_action) {
|
||||
const action = alert_action ? "enabled" : "disabled";
|
||||
const data = {
|
||||
alertType: alert_type,
|
||||
checkid: pk,
|
||||
category: category,
|
||||
action: action
|
||||
};
|
||||
const alertColor = alert_action ? "positive" : "warning";
|
||||
axios.patch("/checks/checkalert/", data).then(r => {
|
||||
this.$q.notify({
|
||||
color: alertColor,
|
||||
icon: "fas fa-check-circle",
|
||||
message: `${alert_type} alerts ${action}`
|
||||
});
|
||||
});
|
||||
},
|
||||
onRefresh(id) {
|
||||
this.$store.dispatch("loadPolicyChecks", id);
|
||||
},
|
||||
moreInfo(name, output) {
|
||||
this.$q.dialog({
|
||||
title: `${name} output`,
|
||||
style: "width: 35vw; max-width: 50vw",
|
||||
message: `<pre>${output}</pre>`,
|
||||
html: true,
|
||||
dark: true
|
||||
});
|
||||
},
|
||||
scriptMoreInfo(props) {
|
||||
this.scriptInfo = props;
|
||||
this.showScriptOutput = true;
|
||||
},
|
||||
editCheck(category) {
|
||||
switch (category) {
|
||||
case "diskspace":
|
||||
this.showEditDiskSpaceCheck = true;
|
||||
break;
|
||||
case "ping":
|
||||
this.showEditPingCheck = true;
|
||||
break;
|
||||
case "cpuload":
|
||||
this.showEditCpuLoadCheck = true;
|
||||
break;
|
||||
case "memory":
|
||||
this.showEditMemCheck = true;
|
||||
break;
|
||||
case "winsvc":
|
||||
this.showEditWinSvcCheck = true;
|
||||
break;
|
||||
case "script":
|
||||
this.showEditScriptCheck = true;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
},
|
||||
deleteCheck(pk, check_type) {
|
||||
this.$q
|
||||
.dialog({
|
||||
title: "Are you sure?",
|
||||
message: `Delete ${check_type} check`,
|
||||
cancel: true,
|
||||
persistent: true
|
||||
})
|
||||
.onOk(() => {
|
||||
const data = { pk: pk, checktype: check_type };
|
||||
axios
|
||||
.delete("checks/deletestandardcheck/", { data: data })
|
||||
.then(r => {
|
||||
this.$store.dispatch("loadPolicyChecks", this.checks.pk);
|
||||
this.notifySuccess("Check was deleted!");
|
||||
})
|
||||
.catch(e => this.notifyError(e.response.data.error));
|
||||
});
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
checks: state => state.policyChecks
|
||||
}),
|
||||
allChecks() {
|
||||
return [
|
||||
...this.checks.diskchecks,
|
||||
...this.checks.cpuloadchecks,
|
||||
...this.checks.memchecks,
|
||||
...this.checks.scriptchecks,
|
||||
...this.checks.winservicechecks,
|
||||
...this.checks.pingchecks
|
||||
];
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="stylus">
|
||||
.checks-tbl-sticky {
|
||||
.q-table__middle {
|
||||
max-height: 25vh;
|
||||
}
|
||||
|
||||
.q-table__top, .q-table__bottom, thead tr:first-child th {
|
||||
background-color: #f5f4f2;
|
||||
}
|
||||
|
||||
thead tr:first-child th {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
opacity: 1;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
40
src/components/PolicySubTableTabs.vue
Normal file
40
src/components/PolicySubTableTabs.vue
Normal file
@@ -0,0 +1,40 @@
|
||||
<template>
|
||||
<div class="q-pa-md">
|
||||
<q-tabs
|
||||
v-model="subtab"
|
||||
dense
|
||||
inline-label
|
||||
class="text-grey"
|
||||
active-color="primary"
|
||||
indicator-color="primary"
|
||||
align="left"
|
||||
narrow-indicator
|
||||
no-caps
|
||||
>
|
||||
<q-tab name="checks" icon="fas fa-check-double" label="Checks" />
|
||||
</q-tabs>
|
||||
<q-separator />
|
||||
<q-tab-panels v-model="subtab" :animated="false">
|
||||
<q-tab-panel name="checks">
|
||||
<PolicyChecksTab />
|
||||
</q-tab-panel>
|
||||
</q-tab-panels>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PolicyChecksTab from '@/components/PolicyChecksTab';
|
||||
|
||||
export default {
|
||||
name: "PolicySubTableTabs",
|
||||
components: {
|
||||
PolicyChecksTab,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
subtab: 'checks'
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<q-card style="width: 40vw">
|
||||
<q-card style="width: 60vw">
|
||||
<q-form @submit.prevent="addPolicy">
|
||||
<q-card-section class="row items-center">
|
||||
<div class="text-h6">Add Policy</div>
|
||||
@@ -15,7 +15,73 @@
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">Description:</div>
|
||||
<div class="col-10">
|
||||
<q-input outlined dense v-model="desc" type="textarea" />
|
||||
<q-input outlined dense v-model="desc" />
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">Active:</div>
|
||||
<div class="col-10">
|
||||
<q-toggle v-model="active" color="green" />
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">Clients:</div>
|
||||
<div class="col-10">
|
||||
<q-select
|
||||
v-model="selectedClients"
|
||||
:options="clientOptions"
|
||||
filled
|
||||
multiple
|
||||
use-chips
|
||||
>
|
||||
<template v-slot:no-option>
|
||||
<q-item>
|
||||
<q-item-section class="text-grey">
|
||||
No Results
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
</q-select>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">Sites:</div>
|
||||
<div class="col-10">
|
||||
<q-select
|
||||
v-model="selectedSites"
|
||||
:options="siteOptions"
|
||||
filled
|
||||
multiple
|
||||
use-chips
|
||||
>
|
||||
<template v-slot:no-option>
|
||||
<q-item>
|
||||
<q-item-section class="text-grey">
|
||||
No Results
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
</q-select>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">Agents:</div>
|
||||
<div class="col-10">
|
||||
<q-select
|
||||
v-model="selectedAgents"
|
||||
:options="agentOptions"
|
||||
filled
|
||||
multiple
|
||||
use-chips
|
||||
>
|
||||
<template v-slot:no-option>
|
||||
<q-item>
|
||||
<q-item-section class="text-grey">
|
||||
No Results
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
</q-select>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="row items-center">
|
||||
@@ -34,7 +100,14 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
name: "",
|
||||
desc: ""
|
||||
desc: "",
|
||||
active: false,
|
||||
selectedAgents: [],
|
||||
selectedSites: [],
|
||||
selectedClients: [],
|
||||
clientOptions: [],
|
||||
siteOptions: [],
|
||||
agentOptions: [],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
@@ -45,22 +118,78 @@ export default {
|
||||
}
|
||||
|
||||
this.$q.loading.show();
|
||||
let formData = new FormData();
|
||||
formData.append("name", this.name);
|
||||
formData.append("desc", this.desc);
|
||||
axios
|
||||
.post("/automation/policies/", formData)
|
||||
|
||||
let formData = {
|
||||
name: this.name,
|
||||
desc: this.desc,
|
||||
active: this.active,
|
||||
agents: this.selectedAgents.map(agent => agent.value),
|
||||
sites: this.selectedSites.map(site => site.value),
|
||||
clients: this.selectedClients.map(client => client.value)
|
||||
};
|
||||
|
||||
axios.post("/automation/policies/", formData)
|
||||
.then(r => {
|
||||
this.$q.loading.hide();
|
||||
this.$emit("close");
|
||||
this.$emit("added");
|
||||
this.notifySuccess("Policy added! Edit the policy to add Checks!");
|
||||
this.notifySuccess("Policy added! Now you can add Tasks and Checks!");
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError(e.response.data);
|
||||
});
|
||||
}
|
||||
},
|
||||
getClients() {
|
||||
|
||||
axios.get(`/clients/listclients/`).then(r => {
|
||||
this.clientOptions = r.data.map(client => {
|
||||
return {
|
||||
label: client.client,
|
||||
value: client.id
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError(e.response.data);
|
||||
});
|
||||
},
|
||||
getSites() {
|
||||
|
||||
axios.get(`/clients/listsites/`).then(r => {
|
||||
this.siteOptions = r.data.map(site => {
|
||||
return {
|
||||
label: `${site.client_name}\\${site.site}`,
|
||||
value: site.id
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError(e.response.data);
|
||||
});
|
||||
},
|
||||
getAgents() {
|
||||
|
||||
axios.get(`/agents/listagents/`).then(r => {
|
||||
this.agentOptions = r.data.map(agent => {
|
||||
return {
|
||||
label: `${agent.client}\\${agent.site}\\${agent.hostname}`,
|
||||
value: agent.pk
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError(e.response.data);
|
||||
});
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.getClients();
|
||||
this.getSites();
|
||||
this.getAgents();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<q-card style="width: 40vw">
|
||||
<q-card style="width: 60vw">
|
||||
<q-form @submit.prevent="editPolicy">
|
||||
<q-card-section class="row items-center">
|
||||
<div class="text-h6">Edit Policy</div>
|
||||
@@ -15,7 +15,73 @@
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">Description:</div>
|
||||
<div class="col-10">
|
||||
<q-input outlined dense v-model="desc" type="textarea" />
|
||||
<q-input outlined dense v-model="desc" />
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">Active:</div>
|
||||
<div class="col-10">
|
||||
<q-toggle v-model="active" color="green" />
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">Clients:</div>
|
||||
<div class="col-10">
|
||||
<q-select
|
||||
v-model="selectedClients"
|
||||
:options="clientOptions"
|
||||
filled
|
||||
multiple
|
||||
use-chips
|
||||
>
|
||||
<template v-slot:no-option>
|
||||
<q-item>
|
||||
<q-item-section class="text-grey">
|
||||
No Results
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
</q-select>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">Sites:</div>
|
||||
<div class="col-10">
|
||||
<q-select
|
||||
v-model="selectedSites"
|
||||
:options="siteOptions"
|
||||
filled
|
||||
multiple
|
||||
use-chips
|
||||
>
|
||||
<template v-slot:no-option>
|
||||
<q-item>
|
||||
<q-item-section class="text-grey">
|
||||
No Results
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
</q-select>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">Agents:</div>
|
||||
<div class="col-10">
|
||||
<q-select
|
||||
v-model="selectedAgents"
|
||||
:options="agentOptions"
|
||||
filled
|
||||
multiple
|
||||
use-chips
|
||||
>
|
||||
<template v-slot:no-option>
|
||||
<q-item>
|
||||
<q-item-section class="text-grey">
|
||||
No Results
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
</q-select>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="row items-center">
|
||||
@@ -37,15 +103,41 @@ export default {
|
||||
return {
|
||||
name: "",
|
||||
desc: "",
|
||||
associations: []
|
||||
active: false,
|
||||
selectedAgents: [],
|
||||
selectedSites: [],
|
||||
selectedClients: [],
|
||||
clientOptions: [],
|
||||
siteOptions: [],
|
||||
agentOptions: [],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getPolicy() {
|
||||
axios.get(`/automation/policies/${this.pk}/`).then(r => {
|
||||
|
||||
this.name = r.data.name;
|
||||
this.desc = r.data.desc;
|
||||
})
|
||||
this.active = r.data.active;
|
||||
this.selectedAgents = r.data.agents.map(agent => {
|
||||
return {
|
||||
label: agent.hostname,
|
||||
value: agent.pk
|
||||
}
|
||||
});
|
||||
this.selectedSites = r.data.sites.map(site => {
|
||||
return {
|
||||
label: site.site,
|
||||
value: site.id
|
||||
}
|
||||
});
|
||||
this.selectedClients = r.data.clients.map(client => {
|
||||
return {
|
||||
label: client.client,
|
||||
value: client.id
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
editPolicy() {
|
||||
if (!this.name) {
|
||||
@@ -54,10 +146,15 @@ export default {
|
||||
}
|
||||
|
||||
this.$q.loading.show();
|
||||
let formData = new FormData();
|
||||
|
||||
formData.append("name", this.name);
|
||||
formData.append("desc", this.desc);
|
||||
let formData = {
|
||||
name: this.name,
|
||||
desc: this.desc,
|
||||
active: this.active,
|
||||
agents: this.selectedAgents.map(agent => agent.value),
|
||||
sites: this.selectedSites.map(site => site.value),
|
||||
clients: this.selectedClients.map(client => client.value)
|
||||
}
|
||||
|
||||
axios.put(`/automation/policies/${this.pk}/`, formData)
|
||||
.then(r => {
|
||||
@@ -70,10 +167,58 @@ export default {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError(e.response.data);
|
||||
});
|
||||
}
|
||||
},
|
||||
getClients() {
|
||||
|
||||
axios.get(`/clients/listclients/`).then(r => {
|
||||
this.clientOptions = r.data.map(client => {
|
||||
return {
|
||||
label: client.client,
|
||||
value: client.id
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError(e.response.data);
|
||||
});
|
||||
},
|
||||
getSites() {
|
||||
|
||||
axios.get(`/clients/listsites/`).then(r => {
|
||||
this.siteOptions = r.data.map(site => {
|
||||
return {
|
||||
label: `${site.client_name}\\${site.site}`,
|
||||
value: site.id
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError(e.response.data);
|
||||
});
|
||||
},
|
||||
getAgents() {
|
||||
|
||||
axios.get(`/agents/listagents/`).then(r => {
|
||||
this.agentOptions = r.data.map(agent => {
|
||||
return {
|
||||
label: `${agent.client}\\${agent.site}\\${agent.hostname}`,
|
||||
value: agent.pk
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError(e.response.data);
|
||||
});
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.getPolicy();
|
||||
this.getClients();
|
||||
this.getSites();
|
||||
this.getAgents();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,7 +1,166 @@
|
||||
<template>
|
||||
<div>Policy Overview</div>
|
||||
<q-card style="width: 600px; max-width: 60vw">
|
||||
<q-bar>
|
||||
<q-btn @click="getPolicyTree" class="q-mr-sm" dense flat push icon="refresh" />Policy Overview
|
||||
<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-splitter
|
||||
v-model="splitterModel"
|
||||
style="height: 400px"
|
||||
>
|
||||
<template v-slot:before>
|
||||
<div class="q-pa-md">
|
||||
<q-tree
|
||||
ref="Tree"
|
||||
:nodes="clientSiteTree"
|
||||
node-key="label"
|
||||
:selected.sync="selected"
|
||||
selected-color="primary"
|
||||
@update:selected="loadPolicyDetails"
|
||||
default-expand-all
|
||||
>
|
||||
|
||||
</q-tree>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-slot:after>
|
||||
<q-tab-panels
|
||||
v-model="selectedTab"
|
||||
animated
|
||||
transition-prev="jump-up"
|
||||
transition-next="jump-up"
|
||||
>
|
||||
<q-tab-panel name="Checks">
|
||||
<p>List Checks</p>
|
||||
</q-tab-panel>
|
||||
<q-tab-panel name="Tasks">
|
||||
<p>List Tasks</p>
|
||||
</q-tab-panel>
|
||||
</q-tab-panels>
|
||||
</template>
|
||||
</q-splitter>
|
||||
</q-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from "axios";
|
||||
import mixins from "@/mixins/mixins";
|
||||
|
||||
export default {
|
||||
name: "PolicyOverview",
|
||||
mixins: [mixins],
|
||||
data () {
|
||||
return {
|
||||
splitterModel: 50,
|
||||
selected: "",
|
||||
selectedPolicy: {},
|
||||
selectedTab: "Checks",
|
||||
clientSiteTree: [],
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getPolicyTree();
|
||||
},
|
||||
methods: {
|
||||
getPolicyTree() {
|
||||
axios.get(`/automation/policies/overview/`).then(r => {
|
||||
this.processTreeDataFromApi(r.data);
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError(e.response.data);
|
||||
});
|
||||
|
||||
},
|
||||
loadPolicyDetails(key) {
|
||||
|
||||
if (key === undefined) {return}
|
||||
|
||||
let node = this.$refs.Tree.getNodeByKey(key);
|
||||
|
||||
axios.get(`/automation/policies/${node.id}/`).then(r => {
|
||||
this.selectedPolicy = r.data
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError(e.response.data);
|
||||
});
|
||||
},
|
||||
processTreeDataFromApi(data) {
|
||||
/* Structure
|
||||
* [{
|
||||
* "client_name_1": {
|
||||
* "policies": [
|
||||
* {
|
||||
* id: 1
|
||||
* name: "Policy Name 1"
|
||||
* }
|
||||
* ]
|
||||
* "site_name_1": {
|
||||
* "policies": []
|
||||
* }
|
||||
* }
|
||||
* }]
|
||||
*/
|
||||
|
||||
var result = [];
|
||||
|
||||
for (let client in data) {
|
||||
|
||||
var client_temp = {};
|
||||
|
||||
client_temp["label"] = client;
|
||||
client_temp["icon"] = "business";
|
||||
client_temp["selectable"] = false;
|
||||
client_temp["children"] = [];
|
||||
|
||||
// Add any policies assigned to client
|
||||
if (data[client].policies.length > 0) {
|
||||
for (let policy in data[client].policies)
|
||||
client_temp["children"].push({
|
||||
label: data[client].policies[policy].name,
|
||||
icon: 'policy',
|
||||
id: data[client].policies[policy].id
|
||||
});
|
||||
}
|
||||
|
||||
// Iterate through Sites
|
||||
for (let site in data[client].sites) {
|
||||
var site_temp = {}
|
||||
site_temp["label"] = site;
|
||||
site_temp["icon"] = "apartment";
|
||||
site_temp["selectable"] = false;
|
||||
|
||||
// Add any policies assigned to site
|
||||
if (data[client].sites[site].policies.length > 0) {
|
||||
|
||||
site_temp["children"] = [];
|
||||
|
||||
for (let policy in data[client].sites[site].policies) {
|
||||
site_temp["children"].push({
|
||||
label: data[client].sites[site].policies[policy].name,
|
||||
icon: 'policy',
|
||||
id: data[client].sites[site].policies[policy].id
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Add Site to Client children array
|
||||
client_temp.children.push(site_temp);
|
||||
|
||||
}
|
||||
|
||||
// Add Client and it's Sites to result array
|
||||
result.push(client_temp);
|
||||
|
||||
}
|
||||
|
||||
this.clientSiteTree = result;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -42,7 +42,7 @@ import { mapState } from "vuex";
|
||||
import mixins from "@/mixins/mixins";
|
||||
export default {
|
||||
name: "AddCpuLoadCheck",
|
||||
props: ["agentpk"],
|
||||
props: ["agentpk", "policypk"],
|
||||
mixins: [mixins],
|
||||
data() {
|
||||
return {
|
||||
@@ -53,8 +53,10 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
addCheck() {
|
||||
pk = (this.policypk) ? {policy: policypk} : {pk: agentpk}
|
||||
|
||||
const data = {
|
||||
pk: this.agentpk,
|
||||
pk,
|
||||
check_type: "cpuload",
|
||||
threshold: this.threshold,
|
||||
failure: this.failure
|
||||
@@ -63,7 +65,13 @@ export default {
|
||||
.post("/checks/addstandardcheck/", data)
|
||||
.then(r => {
|
||||
this.$emit("close");
|
||||
this.$store.dispatch("loadChecks", this.agentpk);
|
||||
|
||||
if (this.policypk) {
|
||||
this.$store.dispatch("loadPolicyChecks", this.policypk);
|
||||
} else {
|
||||
this.$store.dispatch("loadChecks", this.agentpk);
|
||||
}
|
||||
|
||||
this.notifySuccess("CPU load check was added!");
|
||||
})
|
||||
.catch(e => this.notifyError(e.response.data.error));
|
||||
|
||||
@@ -45,7 +45,7 @@ import { mapState } from "vuex";
|
||||
import mixins from "@/mixins/mixins";
|
||||
export default {
|
||||
name: "AddPingCheck",
|
||||
props: ["agentpk"],
|
||||
props: ["agentpk", "policypk"],
|
||||
mixins: [mixins],
|
||||
data() {
|
||||
return {
|
||||
@@ -57,21 +57,32 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
addCheck() {
|
||||
let pk = (this.policypk) ? {policy: this.policypk} : {pk: this.agentpk}
|
||||
|
||||
const data = {
|
||||
pk: this.agentpk,
|
||||
...pk,
|
||||
check_type: "ping",
|
||||
failures: this.failure,
|
||||
name: this.pingname,
|
||||
ip: this.pingip,
|
||||
};
|
||||
axios
|
||||
.post("/checks/addstandardcheck/", data)
|
||||
|
||||
axios.post("/checks/addstandardcheck/", data)
|
||||
.then(r => {
|
||||
this.$emit("close");
|
||||
this.$store.dispatch("loadChecks", this.agentpk);
|
||||
|
||||
if (this.policypk) {
|
||||
this.$store.dispatch("loadPolicyChecks", this.policypk);
|
||||
} else {
|
||||
this.$store.dispatch("loadChecks", this.agentpk);
|
||||
}
|
||||
|
||||
this.notifySuccess("Ping check was added!");
|
||||
})
|
||||
.catch(e => this.notifyError(e.response.data.error));
|
||||
.catch(e => {
|
||||
this.notifyError(e.response.data);
|
||||
console.log(e.response.data)
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -24,6 +24,8 @@ export const store = new Vuex.Store({
|
||||
winUpdates: {},
|
||||
agentChecks: {},
|
||||
automatedTasks: {},
|
||||
selectedPolicy: null,
|
||||
policyChecks: {},
|
||||
agentTableLoading: false,
|
||||
treeLoading: false,
|
||||
installedSoftware: [],
|
||||
@@ -108,6 +110,9 @@ export const store = new Vuex.Store({
|
||||
SET_AUTOMATED_TASKS(state, tasks) {
|
||||
state.automatedTasks = tasks;
|
||||
},
|
||||
setPolicyChecks(state, checks) {
|
||||
state.policyChecks = checks;
|
||||
},
|
||||
destroySubTable(state) {
|
||||
(state.agentSummary = {}),
|
||||
(state.agentChecks = {}),
|
||||
@@ -120,7 +125,10 @@ export const store = new Vuex.Store({
|
||||
},
|
||||
SET_POLICIES(state, policies) {
|
||||
state.policies = policies;
|
||||
}
|
||||
},
|
||||
setSelectedPolicy(state, pk) {
|
||||
state.selectedPolicy = pk;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
getPolicies(context) {
|
||||
@@ -158,6 +166,11 @@ export const store = new Vuex.Store({
|
||||
context.commit("setChecks", r.data);
|
||||
});
|
||||
},
|
||||
loadPolicyChecks(context, pk) {
|
||||
axios.get(`/checks/${pk}/loadpolicychecks/`).then(r => {
|
||||
context.commit("setPolicyChecks", r.data);
|
||||
});
|
||||
},
|
||||
getUpdatedSites(context) {
|
||||
axios.get("/clients/loadclients/").then(r => {
|
||||
context.commit("getUpdatedSites", r.data);
|
||||
|
||||
Reference in New Issue
Block a user