fix search/sort

This commit is contained in:
wh1te909 2021-03-03 10:17:45 +00:00
parent 3e276fc2ac
commit 129c50e598
5 changed files with 88 additions and 221 deletions

View File

@ -54,66 +54,22 @@ class TestAgentsList(TacticalTestCase):
_quantity=7,
)
data = {
"pagination": {
"rowsPerPage": 50,
"rowsNumber": None,
"sortBy": "hostname",
"descending": False,
"page": 1,
},
"monType": "mixed",
}
# test all agents
r = self.client.patch(url, format="json")
self.assertEqual(r.status_code, 200)
self.assertEqual(len(r.data), 36) # type: ignore
# test mixed
# test client1
data = {"clientPK": company1.pk} # type: ignore
r = self.client.patch(url, data, format="json")
self.assertEqual(r.status_code, 200)
self.assertEqual(r.data["total"], 36) # type: ignore
self.assertEqual(len(r.data["agents"]), 36) # type: ignore
self.assertEqual(len(r.data), 25) # type: ignore
# test servers
data["monType"] = "server"
data["pagination"]["rowsPerPage"] = 6
# test site3
data = {"sitePK": site3.pk} # type: ignore
r = self.client.patch(url, data, format="json")
self.assertEqual(r.status_code, 200)
self.assertEqual(r.data["total"], 19) # type: ignore
self.assertEqual(len(r.data["agents"]), 6) # type: ignore
# test workstations
data["monType"] = "server"
data["pagination"]["rowsPerPage"] = 6
r = self.client.patch(url, data, format="json")
self.assertEqual(r.status_code, 200)
self.assertEqual(r.data["total"], 19) # type: ignore
self.assertEqual(len(r.data["agents"]), 6) # type: ignore
# test client1 mixed
data = {
"pagination": {
"rowsPerPage": 3,
"rowsNumber": None,
"sortBy": "hostname",
"descending": False,
"page": 1,
},
"monType": "mixed",
"clientPK": company1.pk, # type: ignore
}
r = self.client.patch(url, data, format="json")
self.assertEqual(r.status_code, 200)
self.assertEqual(r.data["total"], 25) # type: ignore
self.assertEqual(len(r.data["agents"]), 3) # type: ignore
# test site3 workstations
del data["clientPK"]
data["monType"] = "workstation"
data["sitePK"] = site3.pk # type: ignore
r = self.client.patch(url, data, format="json")
self.assertEqual(r.status_code, 200)
self.assertEqual(r.data["total"], 7) # type: ignore
self.assertEqual(len(r.data["agents"]), 3) # type: ignore
self.assertEqual(len(r.data), 11) # type: ignore
self.check_not_authenticated("patch", url)

View File

@ -5,8 +5,6 @@ import random
import string
from django.conf import settings
from django.core.paginator import Paginator
from django.db.models import Q
from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from loguru import logger
@ -228,72 +226,45 @@ def send_raw_cmd(request):
class AgentsTableList(APIView):
def patch(self, request):
pagination = request.data["pagination"]
monType = request.data["monType"]
client = Q()
site = Q()
mon_type = Q()
if pagination["sortBy"] == "agentstatus":
sort = "last_seen"
elif pagination["sortBy"] == "client_name":
sort = "site__client__name"
elif pagination["sortBy"] == "site_name":
sort = "site__name"
elif pagination["sortBy"] == "user":
sort = "logged_in_username"
else:
sort = pagination["sortBy"]
order_by = f"-{sort}" if pagination["descending"] else sort
if monType == "server":
mon_type = Q(monitoring_type="server")
elif monType == "workstation":
mon_type = Q(monitoring_type="workstation")
if "clientPK" in request.data:
client = Q(site__client_id=request.data["clientPK"])
if "sitePK" in request.data:
site = Q(site_id=request.data["sitePK"])
queryset = (
Agent.objects.select_related("site")
.prefetch_related("agentchecks")
.filter(mon_type)
.filter(client)
.filter(site)
.only(
"pk",
"hostname",
"agent_id",
"site",
"monitoring_type",
"description",
"needs_reboot",
"overdue_text_alert",
"overdue_email_alert",
"overdue_time",
"offline_time",
"last_seen",
"boot_time",
"logged_in_username",
"last_logged_in_user",
"time_zone",
"maintenance_mode",
if "sitePK" in request.data.keys():
queryset = (
Agent.objects.select_related("site")
.prefetch_related("agentchecks")
.filter(site_id=request.data["sitePK"])
)
elif "clientPK" in request.data.keys():
queryset = (
Agent.objects.select_related("site")
.prefetch_related("agentchecks")
.filter(site__client_id=request.data["clientPK"])
)
else:
queryset = Agent.objects.select_related("site").prefetch_related(
"agentchecks"
)
.order_by(order_by)
)
paginator = Paginator(queryset, pagination["rowsPerPage"])
queryset = queryset.only(
"pk",
"hostname",
"agent_id",
"site",
"monitoring_type",
"description",
"needs_reboot",
"overdue_text_alert",
"overdue_email_alert",
"overdue_time",
"offline_time",
"last_seen",
"boot_time",
"logged_in_username",
"last_logged_in_user",
"time_zone",
"maintenance_mode",
)
ctx = {"default_tz": get_default_timezone()}
serializer = AgentTableSerializer(
paginator.get_page(pagination["page"]), many=True, context=ctx
)
ret = {"agents": serializer.data, "total": paginator.count}
return Response(ret)
serializer = AgentTableSerializer(queryset, many=True, context=ctx)
return Response(serializer.data)
@api_view()

View File

@ -5,7 +5,7 @@
:table-class="{ 'table-bgcolor': !$q.dark.isActive, 'table-bgcolor-dark': $q.dark.isActive }"
class="agents-tbl-sticky"
:style="{ 'max-height': agentTableHeight }"
:data="filter"
:data="frame"
:filter="search"
:filter-method="filterTable"
:columns="columns"
@ -13,11 +13,9 @@
row-key="id"
binary-state-sort
virtual-scroll
:pagination.sync="agentPagination"
:rows-per-page-options="[25, 50, 100, 200, 300, 500, 1000]"
:pagination.sync="pagination"
:rows-per-page-options="[0]"
no-data-label="No Agents"
rows-per-page-label="Agents per page:"
@request="onRequest"
>
<!-- header slots -->
<template v-slot:header-cell-smsalert="props">
@ -346,6 +344,12 @@
<q-tooltip>Pending Action Count: {{ props.row.pending_actions }}</q-tooltip>
</q-icon>
</q-td>
<!-- needs reboot -->
<q-td key="needsreboot">
<q-icon v-if="props.row.needs_reboot" name="fas fa-power-off" color="primary">
<q-tooltip>Reboot required</q-tooltip>
</q-icon>
</q-td>
<q-td key="agentstatus">
<q-icon v-if="props.row.status === 'overdue'" name="fas fa-signal" size="1.2em" color="negative">
<q-tooltip>Agent overdue</q-tooltip>
@ -357,12 +361,6 @@
<q-tooltip>Agent online</q-tooltip>
</q-icon>
</q-td>
<!-- needs reboot -->
<q-td key="needsreboot">
<q-icon v-if="props.row.needs_reboot" name="fas fa-power-off" color="primary">
<q-tooltip>Reboot required</q-tooltip>
</q-icon>
</q-td>
<q-td key="last_seen" :props="props">{{ formatDjangoDate(props.row.last_seen) }}</q-td>
<q-td key="boot_time" :props="props">{{ bootTime(props.row.boot_time) }}</q-td>
</q-tr>
@ -415,7 +413,7 @@ import RunScript from "@/components/modals/agents/RunScript";
export default {
name: "AgentTable",
props: ["frame", "columns", "tab", "filter", "userName", "search", "visibleColumns", "agentTblPagination"],
props: ["frame", "columns", "tab", "userName", "search", "visibleColumns"],
components: {
EditAgent,
RebootLater,
@ -427,6 +425,11 @@ export default {
mixins: [mixins],
data() {
return {
pagination: {
rowsPerPage: 0,
sortBy: "hostname",
descending: false,
},
showSendCommand: false,
showEditAgentModal: false,
showRebootLaterModal: false,
@ -438,15 +441,6 @@ export default {
};
},
methods: {
onRequest(props) {
if (!!props.filter) return;
const { page, rowsPerPage, sortBy, descending } = props.pagination;
this.agentTblPagination.page = page;
this.agentTblPagination.rowsPerPage = rowsPerPage;
this.agentTblPagination.sortBy = sortBy;
this.agentTblPagination.descending = descending;
this.$emit("refreshEdit");
},
filterTable(rows, terms, cols, cellValue) {
const lowerTerms = terms ? terms.toLowerCase() : "";
let advancedFilter = false;
@ -765,14 +759,6 @@ export default {
agentTableLoading() {
return this.$store.state.agentTableLoading;
},
agentPagination: {
get: function () {
return this.agentTblPagination;
},
set: function (newVal) {
this.$emit("agentPagChanged", newVal);
},
},
},
};
</script>

View File

@ -46,11 +46,6 @@
class="col-4"
/>
</q-card-section>
<q-card-section class="row">
<div class="col-6">Agent table default records per page:</div>
<div class="col-2"></div>
<q-input v-model.number="agentsPerPage" type="number" filled style="max-width: 100px" />
</q-card-section>
</q-tab-panel>
</q-tab-panels>
@ -73,7 +68,6 @@ export default {
return {
agentDblClickAction: "",
defaultAgentTblTab: "",
agentsPerPage: 50,
tab: "ui",
splitterModel: 20,
agentDblClickOptions: [
@ -111,7 +105,6 @@ export default {
this.$axios.get("/core/dashinfo/").then(r => {
this.agentDblClickAction = r.data.dbl_click_action;
this.defaultAgentTblTab = r.data.default_agent_tbl_tab;
this.agentsPerPage = r.data.agents_per_page;
});
},
editUserPrefs() {
@ -119,12 +112,10 @@ export default {
userui: true,
agent_dblclick_action: this.agentDblClickAction,
default_agent_tbl_tab: this.defaultAgentTblTab,
agents_per_page: this.agentsPerPage,
};
this.$axios.patch("/accounts/users/ui/", data).then(r => {
this.notifySuccess("Preferences were saved!");
this.$emit("edited");
this.$emit("refresh");
this.$emit("close");
});
},

View File

@ -195,7 +195,6 @@
indicator-color="primary"
align="left"
narrow-indicator
@input="tabChanged"
>
<q-tab name="server" icon="fas fa-server" label="Servers" />
<q-tab name="workstation" icon="computer" label="Workstations" />
@ -205,11 +204,10 @@
<q-input
v-model="search"
style="width: 450px"
label="Search (temporarily disabled)"
label="Search"
dense
outlined
clearable
disable
@clear="clearFilter"
class="q-pr-md q-pb-xs"
>
@ -217,7 +215,7 @@
<q-icon name="search" color="primary" />
</template>
<template v-slot:after>
<q-btn disable round dense flat icon="filter_alt" :color="isFilteringTable ? 'green' : ''">
<q-btn round dense flat icon="filter_alt" :color="isFilteringTable ? 'green' : ''">
<q-menu>
<q-list dense>
<q-item-label header>Filter Agent Table</q-item-label>
@ -320,16 +318,13 @@
</q-input>
</div>
<AgentTable
:frame="frame"
:frame="filteredAgents"
:columns="columns"
:tab="tab"
:filter="frozenAgents"
:userName="user"
:search="search"
:visibleColumns="visibleColumns"
:agentTblPagination="agentTblPagination"
@refreshEdit="refreshEntireSite"
@agentPagChanged="setAgentTblPagination"
/>
</template>
<template v-slot:separator>
@ -367,7 +362,7 @@
</q-dialog>
<!-- user preferences modal -->
<q-dialog v-model="showUserPreferencesModal">
<UserPreferences @close="showUserPreferencesModal = false" @edited="getDashInfo" @refresh="refreshEntireSite" />
<UserPreferences @close="showUserPreferencesModal = false" @edited="getDashInfo" />
</q-dialog>
</q-layout>
</template>
@ -428,13 +423,6 @@ export default {
filterRebootNeeded: false,
currentTRMMVersion: null,
showUserPreferencesModal: false,
agentTblPagination: {
rowsPerPage: 50,
rowsNumber: null,
sortBy: "hostname",
descending: false,
page: 1,
},
columns: [
{
name: "smsalert",
@ -452,8 +440,8 @@ export default {
name: "checks-status",
align: "left",
field: "checks",
sortable: false,
//sort: (a, b, rowA, rowB) => parseInt(b.failing) - a.failing,
sortable: true,
sort: (a, b, rowA, rowB) => parseInt(b.failing) - a.failing,
},
{
name: "client_name",
@ -498,18 +486,12 @@ export default {
name: "patchespending",
field: "patches_pending",
align: "left",
sortable: false,
sortable: true,
},
{
name: "pendingactions",
field: "pending_actions",
align: "left",
sortable: false,
},
{
name: "agentstatus",
field: "status",
align: "left",
sortable: true,
},
{
@ -518,13 +500,19 @@ export default {
align: "left",
sortable: true,
},
{
name: "agentstatus",
field: "status",
align: "left",
sortable: false,
},
{
name: "last_seen",
label: "Last Response",
field: "last_seen",
sortable: true,
align: "left",
//sort: (a, b) => this.dateStringToUnix(a) - this.dateStringToUnix(b),
sort: (a, b) => this.dateStringToUnix(a) - this.dateStringToUnix(b),
},
{
name: "boot_time",
@ -560,16 +548,6 @@ export default {
},
},
methods: {
tabChanged(val) {
if (this.allClientsActive) {
this.loadAllClients();
} else {
this.loadFrame(this.selectedTree, false);
}
},
setAgentTblPagination(val) {
this.agentTblPagination = val;
},
toggleDark(val) {
this.$q.dark.set(val);
this.$axios.patch("/accounts/users/ui/", { dark_mode: val });
@ -600,7 +578,7 @@ export default {
let execute = false;
let urlType, id;
let data = { pagination: this.agentTblPagination };
let data = {};
if (typeof activenode === "string") {
urlType = activenode.split("|")[0];
@ -616,15 +594,10 @@ export default {
if (execute) {
this.$store.commit("AGENT_TABLE_LOADING", true);
// give time for vuex to set the tab, otherwise will always be 'server'
setTimeout(() => {
data.monType = this.tab;
this.$axios.patch("/agents/listagents/", data).then(r => {
this.frame = r.data.agents;
this.agentTblPagination.rowsNumber = r.data.total;
this.$store.commit("AGENT_TABLE_LOADING", false);
});
}, 500);
this.$axios.patch("/agents/listagents/", data).then(r => {
this.frame = r.data;
this.$store.commit("AGENT_TABLE_LOADING", false);
});
}
}
},
@ -642,18 +615,10 @@ export default {
},
loadAllClients() {
this.$store.commit("AGENT_TABLE_LOADING", true);
// give time for vuex to set the tab, otherwise will always be 'server'
setTimeout(() => {
const data = {
pagination: this.agentTblPagination,
monType: this.tab,
};
this.$axios.patch("/agents/listagents/", data).then(r => {
this.frame = r.data.agents;
this.agentTblPagination.rowsNumber = r.data.total;
this.$store.commit("AGENT_TABLE_LOADING", false);
});
}, 500);
this.$axios.patch("/agents/listagents/").then(r => {
this.frame = r.data;
this.$store.commit("AGENT_TABLE_LOADING", false);
});
},
showPolicyAdd(node) {
if (node.children) {
@ -747,10 +712,7 @@ export default {
},
getDashInfo(edited = true) {
this.$store.dispatch("getDashInfo").then(r => {
if (edited) {
this.agentTblPagination.rowsPerPage = r.data.agents_per_page;
this.$store.commit("SET_DEFAULT_AGENT_TBL_TAB", r.data.default_agent_tbl_tab);
}
if (edited) this.$store.commit("SET_DEFAULT_AGENT_TBL_TAB", r.data.default_agent_tbl_tab);
this.darkMode = r.data.dark_mode;
this.$q.dark.set(this.darkMode);
this.currentTRMMVersion = r.data.trmm_version;
@ -850,8 +812,9 @@ export default {
allClientsActive() {
return this.selectedTree === "";
},
frozenAgents() {
return Object.freeze(this.frame);
filteredAgents() {
if (this.tab === "mixed") return Object.freeze(this.frame);
return Object.freeze(this.frame.filter(k => k.monitoring_type === this.tab));
},
activeNode() {
return {