mirror of
https://github.com/jpros/tacticalrmm-web.git
synced 2026-03-01 07:41:00 +00:00
Merge pull request #7 from sadnub/feature-automation-alerts
Automation and Alerts Overview
This commit is contained in:
86
src/components/AlertsIcon.vue
Normal file
86
src/components/AlertsIcon.vue
Normal file
@@ -0,0 +1,86 @@
|
||||
<template>
|
||||
<q-btn dense flat icon="notifications">
|
||||
<q-badge color="red" floating transparent>
|
||||
{{ test_alerts.length }}
|
||||
</q-badge>
|
||||
<q-menu>
|
||||
<q-list separator>
|
||||
<q-item v-for="alert in test_alerts" :key="alert.id">
|
||||
<q-item-section>
|
||||
<q-item-label>{{ alert.client }} - {{ alert.hostname }}</q-item-label>
|
||||
<q-item-label caption>
|
||||
<q-icon :class="`text-${alertColor(alert.type)}`" :name="alert.type"></q-icon>
|
||||
{{ alert.message }}</q-item-label>
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section side top>
|
||||
<q-item-label caption>{{ alert.timestamp }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item clickable @click="showAlertsModal = true">
|
||||
View All Alerts ({{test_alerts.length}})
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
|
||||
<q-dialog
|
||||
v-model="showAlertsModal"
|
||||
maximized
|
||||
transition-show="slide-up"
|
||||
transition-hide="slide-down"
|
||||
>
|
||||
<AlertsOverview @close="showAlertsModal = false" />
|
||||
</q-dialog>
|
||||
|
||||
</q-btn>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex';
|
||||
import AlertsOverview from '@/components/modals/alerts/AlertsOverview'
|
||||
|
||||
export default {
|
||||
name: "AlertsIcon",
|
||||
components: {AlertsOverview},
|
||||
data () {
|
||||
return {
|
||||
showAlertsModal: false,
|
||||
test_alerts: [
|
||||
{
|
||||
id: 1,
|
||||
client: "NMHSI",
|
||||
site: "Default",
|
||||
hostname: "NMSC-BACK01",
|
||||
message: "HDD error. Stuff ain't working",
|
||||
type: "error",
|
||||
timestamp: "2 min ago"
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
client: "Dove IT",
|
||||
site: "Default",
|
||||
hostname: "NMSC-ANOTHER",
|
||||
message: "Big error. Stuff still ain't working",
|
||||
type: "warning",
|
||||
timestamp: "5 hours ago"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
alertColor (type) {
|
||||
if (type === "error"){
|
||||
return "red";
|
||||
}
|
||||
if (type === "warning"){
|
||||
return "orange"
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('alerts/', {
|
||||
alerts: state => state.alerts
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
217
src/components/AutomationManager.vue
Normal file
217
src/components/AutomationManager.vue
Normal file
@@ -0,0 +1,217 @@
|
||||
<template>
|
||||
<div class="q-pa-md q-gutter-sm">
|
||||
<q-dialog :value="toggleAutomationManager" @hide="hideAutomationManager" @show="getPolicies">
|
||||
<q-card style="width: 900px; max-width: 90vw;">
|
||||
<q-bar>
|
||||
<q-btn @click="getPolicies" class="q-mr-sm" dense flat push icon="refresh" />Automation Manager
|
||||
<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>
|
||||
<div class="q-pa-md">
|
||||
<div class="q-gutter-sm">
|
||||
<q-btn
|
||||
label="New"
|
||||
dense
|
||||
flat
|
||||
push
|
||||
unelevated
|
||||
no-caps
|
||||
icon="add"
|
||||
@click="showAddPolicyModal = true; clearRow"
|
||||
/>
|
||||
<q-btn
|
||||
label="Edit"
|
||||
:disable="selectedRow === null"
|
||||
dense
|
||||
flat
|
||||
push
|
||||
unelevated
|
||||
no-caps
|
||||
icon="edit"
|
||||
@click="showEditPolicyModal = true"
|
||||
/>
|
||||
<q-btn
|
||||
label="Delete"
|
||||
:disable="selectedRow === null"
|
||||
dense
|
||||
flat
|
||||
push
|
||||
unelevated
|
||||
no-caps
|
||||
icon="delete"
|
||||
@click="deletePolicy"
|
||||
/>
|
||||
<q-btn
|
||||
label="Policy Overview"
|
||||
dense
|
||||
flat
|
||||
push
|
||||
unelevated
|
||||
no-caps
|
||||
icon="remove_red_eye"
|
||||
@click="showPolicyOverviewModal = true"
|
||||
/>
|
||||
</div>
|
||||
<q-table
|
||||
dense
|
||||
class="automation-sticky-header-table"
|
||||
:data="policies"
|
||||
:columns="columns"
|
||||
:visible-columns="visibleColumns"
|
||||
:pagination.sync="pagination"
|
||||
row-key="id"
|
||||
binary-state-sort
|
||||
hide-bottom
|
||||
virtual-scroll
|
||||
flat
|
||||
:rows-per-page-options="[0]"
|
||||
>
|
||||
<template slot="body" slot-scope="props" :props="props">
|
||||
<q-tr
|
||||
:class="{highlight: selectedRow === props.row.id}"
|
||||
@click="policyRowSelected(props.row.id)"
|
||||
>
|
||||
<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-tr>
|
||||
</template>
|
||||
</q-table>
|
||||
</div>
|
||||
<q-card-section></q-card-section>
|
||||
<q-separator />
|
||||
<q-card-section></q-card-section>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
<q-dialog v-model="showAddPolicyModal">
|
||||
<AddPolicy @close="showAddPolicyModal = false" @added="getPolicies" />
|
||||
</q-dialog>
|
||||
<q-dialog v-model="showEditPolicyModal">
|
||||
<EditPolicy :pk="selectedRow" @close="showEditPolicyModal = false" @edited="getPolicies" />
|
||||
</q-dialog>
|
||||
<q-dialog v-model="showPolicyOverviewModal">
|
||||
<PolicyOverview @close="showPolicyOverviewModal = false" />
|
||||
</q-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from "axios";
|
||||
import mixins from "@/mixins/mixins";
|
||||
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";
|
||||
|
||||
export default {
|
||||
name: "AutomationManager",
|
||||
components: { AddPolicy, EditPolicy, PolicyOverview },
|
||||
mixins: [mixins],
|
||||
data() {
|
||||
return {
|
||||
selectedRow: null,
|
||||
showAddPolicyModal: false,
|
||||
showEditPolicyModal: false,
|
||||
showPolicyOverviewModal: false,
|
||||
pagination: {
|
||||
rowsPerPage: 0,
|
||||
sortBy: "id",
|
||||
descending: false
|
||||
},
|
||||
columns: [
|
||||
{ name: "id", label: "ID", field: "id" },
|
||||
{
|
||||
name: "name",
|
||||
label: "Name",
|
||||
field: "name",
|
||||
align: "left",
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
name: "desc",
|
||||
label: "Description",
|
||||
field: "desc",
|
||||
align: "left",
|
||||
sortable: false
|
||||
},
|
||||
{
|
||||
name: "active",
|
||||
label: "Active",
|
||||
field: "active",
|
||||
align: "left",
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
name: "applied_to",
|
||||
label: "Applied To",
|
||||
field: "applied_to",
|
||||
align: "left",
|
||||
sortable: false
|
||||
}
|
||||
],
|
||||
visibleColumns: ["name", "desc", "active", "applied_to"]
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getPolicies() {
|
||||
this.clearRow();
|
||||
this.$store.dispatch("getPolicies");
|
||||
},
|
||||
hideAutomationManager() {
|
||||
this.$store.commit("TOGGLE_AUTOMATION_MANAGER", false);
|
||||
},
|
||||
policyRowSelected(pk) {
|
||||
this.selectedRow = pk;
|
||||
},
|
||||
clearRow() {
|
||||
this.selectedRow = null;
|
||||
},
|
||||
deletePolicy() {
|
||||
this.$q
|
||||
.dialog({
|
||||
title: "Delete policy?",
|
||||
cancel: true,
|
||||
ok: { label: "Delete", color: "negative" }
|
||||
})
|
||||
.onOk(() => {
|
||||
axios.delete(`/automation/policies/${this.selectedRow}`).then(r => {
|
||||
this.getPolicies();
|
||||
this.notifySuccess(`Policy ${r.data} was deleted!`);
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
toggleAutomationManager: state => state.toggleAutomationManager,
|
||||
policies: state => state.policies
|
||||
})
|
||||
},
|
||||
mounted() {
|
||||
this.getPolicies();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="stylus">
|
||||
.automation-sticky-header-table {
|
||||
/* max height is important */
|
||||
.q-table__middle {
|
||||
max-height: 500px;
|
||||
}
|
||||
|
||||
.q-table__top, .q-table__bottom, thead tr:first-child th {
|
||||
background-color: #CBCBCB;
|
||||
}
|
||||
|
||||
thead tr:first-child th {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
opacity: 1;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -40,6 +40,10 @@
|
||||
<q-item clickable v-close-popup @click="showScriptManager">
|
||||
<q-item-section>Script Manager</q-item-section>
|
||||
</q-item>
|
||||
<!-- automation manager -->
|
||||
<q-item clickable v-close-popup @click="showAutomationManager">
|
||||
<q-item-section>Automation Manager</q-item-section>
|
||||
</q-item>
|
||||
<!-- core settings -->
|
||||
<q-item clickable v-close-popup @click="showEditCoreSettingsModal = true">
|
||||
<q-item-section>Global Settings</q-item-section>
|
||||
@@ -75,6 +79,9 @@
|
||||
</div>
|
||||
<!-- Script Manager -->
|
||||
<ScriptManager />
|
||||
|
||||
<!-- Automation Manager -->
|
||||
<AutomationManager />
|
||||
</q-bar>
|
||||
</div>
|
||||
</template>
|
||||
@@ -86,6 +93,8 @@ import AddSite from "@/components/modals/clients/AddSite";
|
||||
import UpdateAgents from "@/components/modals/agents/UpdateAgents";
|
||||
import ScriptManager from "@/components/ScriptManager";
|
||||
import EditCoreSettings from "@/components/modals/coresettings/EditCoreSettings";
|
||||
import AutomationManager from "@/components/AutomationManager";
|
||||
|
||||
export default {
|
||||
name: "FileBar",
|
||||
components: {
|
||||
@@ -94,7 +103,8 @@ export default {
|
||||
AddSite,
|
||||
UpdateAgents,
|
||||
ScriptManager,
|
||||
EditCoreSettings
|
||||
EditCoreSettings,
|
||||
AutomationManager
|
||||
},
|
||||
props: ["clients"],
|
||||
data() {
|
||||
@@ -111,6 +121,9 @@ export default {
|
||||
},
|
||||
showScriptManager() {
|
||||
this.$store.commit("TOGGLE_SCRIPT_MANAGER", true);
|
||||
},
|
||||
showAutomationManager() {
|
||||
this.$store.commit("TOGGLE_AUTOMATION_MANAGER", true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
53
src/components/modals/alerts/AlertsOverview.vue
Normal file
53
src/components/modals/alerts/AlertsOverview.vue
Normal file
@@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<q-card>
|
||||
<q-bar>
|
||||
Alerts 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-separator />
|
||||
<q-card-section>
|
||||
All Alerts
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<q-btn
|
||||
label="Update"
|
||||
color="primary"
|
||||
/>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from "axios";
|
||||
export default {
|
||||
name: "AlertsOverview",
|
||||
data() {
|
||||
return {
|
||||
alerts: [],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getAlerts() {
|
||||
this.$q.loading.show();
|
||||
axios
|
||||
.get("/alerts/")
|
||||
.then(r => {
|
||||
this.alerts = r.data.alerts
|
||||
})
|
||||
.catch(() => {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError("Something went wrong");
|
||||
});
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
created() {
|
||||
this.getAlerts();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
66
src/components/modals/automation/AddPolicy.vue
Normal file
66
src/components/modals/automation/AddPolicy.vue
Normal file
@@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<q-card style="width: 40vw">
|
||||
<q-form @submit.prevent="addPolicy">
|
||||
<q-card-section class="row items-center">
|
||||
<div class="text-h6">Add Policy</div>
|
||||
<q-space />
|
||||
<q-btn icon="close" flat round dense v-close-popup />
|
||||
</q-card-section>
|
||||
<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']" />
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">Description:</div>
|
||||
<div class="col-10">
|
||||
<q-input outlined dense v-model="desc" type="textarea" />
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="row items-center">
|
||||
<q-btn label="Add" color="primary" type="submit" />
|
||||
</q-card-section>
|
||||
</q-form>
|
||||
</q-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from "axios";
|
||||
import mixins from "@/mixins/mixins";
|
||||
export default {
|
||||
name: "AddPolicy",
|
||||
mixins: [mixins],
|
||||
data() {
|
||||
return {
|
||||
name: "",
|
||||
desc: ""
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
addPolicy() {
|
||||
if (!this.name) {
|
||||
this.notifyError("Name is required!");
|
||||
return false;
|
||||
}
|
||||
|
||||
this.$q.loading.show();
|
||||
let formData = new FormData();
|
||||
formData.append("name", this.name);
|
||||
formData.append("desc", this.desc);
|
||||
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!");
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError(e.response.data);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
79
src/components/modals/automation/EditPolicy.vue
Normal file
79
src/components/modals/automation/EditPolicy.vue
Normal file
@@ -0,0 +1,79 @@
|
||||
<template>
|
||||
<q-card style="width: 40vw">
|
||||
<q-form @submit.prevent="editPolicy">
|
||||
<q-card-section class="row items-center">
|
||||
<div class="text-h6">Edit Policy</div>
|
||||
<q-space />
|
||||
<q-btn icon="close" flat round dense v-close-popup />
|
||||
</q-card-section>
|
||||
<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']" />
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">Description:</div>
|
||||
<div class="col-10">
|
||||
<q-input outlined dense v-model="desc" type="textarea" />
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="row items-center">
|
||||
<q-btn label="Edit" color="primary" type="submit" />
|
||||
</q-card-section>
|
||||
</q-form>
|
||||
</q-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from "axios";
|
||||
import mixins from "@/mixins/mixins";
|
||||
|
||||
export default {
|
||||
name: "EditPolicy",
|
||||
mixins: [mixins],
|
||||
props: ["pk"],
|
||||
data() {
|
||||
return {
|
||||
name: "",
|
||||
desc: "",
|
||||
associations: []
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getPolicy() {
|
||||
axios.get(`/automation/policies/${this.pk}/`).then(r => {
|
||||
this.name = r.data.name;
|
||||
this.desc = r.data.desc;
|
||||
})
|
||||
},
|
||||
editPolicy() {
|
||||
if (!this.name) {
|
||||
this.notifyError("Name is required!");
|
||||
return false;
|
||||
}
|
||||
|
||||
this.$q.loading.show();
|
||||
let formData = new FormData();
|
||||
|
||||
formData.append("name", this.name);
|
||||
formData.append("desc", this.desc);
|
||||
|
||||
axios.put(`/automation/policies/${this.pk}/`, formData)
|
||||
.then(r => {
|
||||
this.$q.loading.hide();
|
||||
this.$emit("close");
|
||||
this.$emit("edited");
|
||||
this.notifySuccess("Policy edited!");
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError(e.response.data);
|
||||
});
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getPolicy();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
7
src/components/modals/automation/PolicyOverview.vue
Normal file
7
src/components/modals/automation/PolicyOverview.vue
Normal file
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<div>Policy Overview</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
</script>
|
||||
29
src/store/alerts.js
Normal file
29
src/store/alerts.js
Normal file
@@ -0,0 +1,29 @@
|
||||
export default {
|
||||
namespaced: true,
|
||||
state: {
|
||||
alerts: [],
|
||||
},
|
||||
|
||||
getters:{
|
||||
getAlerts(state) {
|
||||
return state.alerts;
|
||||
},
|
||||
getUncheckedAlerts(state) {
|
||||
//filter for non-dismissed active alerts
|
||||
}
|
||||
},
|
||||
|
||||
mutation: {
|
||||
SET_ALERTS(state, alerts) {
|
||||
state.alerts = alerts;
|
||||
},
|
||||
},
|
||||
|
||||
actions: {
|
||||
getAlerts(context) {
|
||||
axios.get(`/alerts/getAlerts/`).then(r => {
|
||||
context.commit("SET_ALERTS", r.data);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,14 @@ import axios from "axios";
|
||||
import { Notify } from "quasar";
|
||||
import router from "../router";
|
||||
import logModule from "./logs";
|
||||
import alertsModule from "./alerts";
|
||||
|
||||
Vue.use(Vuex);
|
||||
|
||||
export const store = new Vuex.Store({
|
||||
modules: {
|
||||
logs: logModule
|
||||
logs: logModule,
|
||||
alerts: alertsModule
|
||||
},
|
||||
state: {
|
||||
username: localStorage.getItem("user_name") || null,
|
||||
@@ -25,7 +27,9 @@ export const store = new Vuex.Store({
|
||||
treeLoading: false,
|
||||
installedSoftware: [],
|
||||
scripts: [],
|
||||
toggleScriptManager: false
|
||||
toggleScriptManager: false,
|
||||
policies: [],
|
||||
toggleAutomationManager: false
|
||||
},
|
||||
getters: {
|
||||
loggedIn(state) {
|
||||
@@ -55,9 +59,15 @@ export const store = new Vuex.Store({
|
||||
},
|
||||
scripts(state) {
|
||||
return state.scripts;
|
||||
},
|
||||
policies(state) {
|
||||
return state.policies;
|
||||
}
|
||||
},
|
||||
mutations: {
|
||||
TOGGLE_AUTOMATION_MANAGER(state, action) {
|
||||
state.toggleAutomationManager = action;
|
||||
},
|
||||
TOGGLE_SCRIPT_MANAGER(state, action) {
|
||||
state.toggleScriptManager = action;
|
||||
},
|
||||
@@ -103,9 +113,17 @@ export const store = new Vuex.Store({
|
||||
},
|
||||
SET_SCRIPTS(state, scripts) {
|
||||
state.scripts = scripts;
|
||||
},
|
||||
SET_POLICIES(state, policies) {
|
||||
state.policies = policies;
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
getPolicies(context) {
|
||||
axios.get("/automation/policies/").then(r => {
|
||||
context.commit("SET_POLICIES", r.data);
|
||||
})
|
||||
},
|
||||
getScripts(context) {
|
||||
axios.get("/checks/getscripts/").then(r => {
|
||||
context.commit("SET_SCRIPTS", r.data);
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
<q-toolbar-title>
|
||||
Tactical RMM
|
||||
</q-toolbar-title>
|
||||
|
||||
<AlertsIcon />
|
||||
|
||||
<q-btn-dropdown flat no-caps stretch :label="user">
|
||||
<q-list>
|
||||
<q-item to="/logout" exact>
|
||||
@@ -88,11 +91,13 @@ import { mapState, mapGetters } from 'vuex';
|
||||
import FileBar from "@/components/FileBar";
|
||||
import AgentTable from "@/components/AgentTable";
|
||||
import SubTableTabs from "@/components/SubTableTabs";
|
||||
import AlertsIcon from "@/components/AlertsIcon";
|
||||
export default {
|
||||
components: {
|
||||
FileBar,
|
||||
AgentTable,
|
||||
SubTableTabs
|
||||
SubTableTabs,
|
||||
AlertsIcon
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -171,7 +176,7 @@ export default {
|
||||
sortable: true,
|
||||
align: "left"
|
||||
}
|
||||
]
|
||||
],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
@@ -242,7 +247,7 @@ export default {
|
||||
//this.$store.commit("destroySubTable");
|
||||
this.$store.commit("AGENT_TABLE_LOADING", false);
|
||||
});
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
|
||||
Reference in New Issue
Block a user