Apply filters to nodes list.
This commit is contained in:
parent
5b703917b5
commit
cce665d149
6 changed files with 96 additions and 77 deletions
frontend/src
|
@ -1,37 +1,24 @@
|
|||
<script setup lang="ts">
|
||||
import {computed, defineProps} from "vue";
|
||||
import type {NodesFilter} from "@/types";
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
variant: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
value: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
link: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
filter: {
|
||||
type: Object,
|
||||
required: false,
|
||||
},
|
||||
});
|
||||
interface Props {
|
||||
title: string;
|
||||
icon: string;
|
||||
variant: string;
|
||||
value: number;
|
||||
link: string;
|
||||
filter?: NodesFilter;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const linkTarget = computed(() => {
|
||||
if (props.filter) {
|
||||
const json = JSON.stringify(props.filter);
|
||||
return `${props.link}?search=${encodeURIComponent(json)}`;
|
||||
return {
|
||||
path: props.link,
|
||||
query: props.filter,
|
||||
}
|
||||
} else {
|
||||
return props.link;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { createRouter, createWebHistory } from "vue-router";
|
||||
import {createRouter, createWebHistory} from "vue-router";
|
||||
import AdminDashboardView from "@/views/AdminDashboardView.vue";
|
||||
import AdminNodesView from "@/views/AdminNodesView.vue";
|
||||
import HomeView from "@/views/HomeView.vue";
|
||||
import {isNodesFilter} from "@/types";
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
|
@ -20,6 +21,9 @@ const router = createRouter({
|
|||
path: "/admin/nodes",
|
||||
name: "admin-nodes",
|
||||
component: AdminNodesView,
|
||||
props: route => ({
|
||||
filter: isNodesFilter(route.query) ? route.query : {}
|
||||
})
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {defineStore} from "pinia";
|
||||
import {isEnhancedNode, type EnhancedNode} from "@/types";
|
||||
import {type EnhancedNode, isEnhancedNode, type NodesFilter} from "@/types";
|
||||
import {internalApi} from "@/utils/Api";
|
||||
|
||||
interface NodesStoreState {
|
||||
|
@ -37,12 +37,13 @@ export const useNodesStore = defineStore({
|
|||
},
|
||||
},
|
||||
actions: {
|
||||
async refresh(page: number, nodesPerPage: number): Promise<void> {
|
||||
async refresh(page: number, nodesPerPage: number, filter: NodesFilter): Promise<void> {
|
||||
const result = await internalApi.getPagedList<EnhancedNode>(
|
||||
"nodes",
|
||||
isEnhancedNode,
|
||||
page,
|
||||
nodesPerPage,
|
||||
filter,
|
||||
);
|
||||
this.nodes = result.entries;
|
||||
this.totalNodes = result.total;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import type {TypeGuard} from "@/types/shared";
|
||||
import {toIsArray} from "@/types/shared";
|
||||
import {toIsArray, type TypeGuard} from "@/types";
|
||||
import type {Headers} from "request";
|
||||
import {parseInteger} from "@/utils/Numbers";
|
||||
|
||||
|
@ -63,10 +62,12 @@ class Api {
|
|||
isT: TypeGuard<T>,
|
||||
page: number,
|
||||
itemsPerPage: number,
|
||||
filter?: object,
|
||||
): Promise<PagedListResult<T>> {
|
||||
const response = await this.doGet(path, toIsArray(isT), {
|
||||
_page: page,
|
||||
_perPage: itemsPerPage,
|
||||
...filter,
|
||||
});
|
||||
const totalStr = response.headers.get("x-total-count");
|
||||
const total = parseInteger(totalStr, 10);
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
<script setup lang="ts">
|
||||
import {useNodesStore} from "@/stores/nodes";
|
||||
import {onMounted, ref} from "vue";
|
||||
import type {EnhancedNode, MAC} from "@/types";
|
||||
import type {EnhancedNode, MAC, NodesFilter} from "@/types";
|
||||
import Pager from "@/components/Pager.vue";
|
||||
import LoadingContainer from "@/components/LoadingContainer.vue";
|
||||
|
||||
const NODE_PER_PAGE = 50;
|
||||
|
||||
interface Props {
|
||||
filter: NodesFilter;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
type NodeRedactField = "nickname" | "email" | "token";
|
||||
type NodeRedactFieldsMap = Partial<Record<NodeRedactField, boolean>>;
|
||||
|
||||
|
@ -21,7 +27,7 @@ async function refresh(page: number): Promise<void> {
|
|||
loading.value = true;
|
||||
redactAllFields(true);
|
||||
try {
|
||||
await nodes.refresh(page, NODE_PER_PAGE);
|
||||
await nodes.refresh(page, NODE_PER_PAGE, props.filter);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue