feat(rnpath): RNPathPage with interface discovery and improved search functionality

This commit is contained in:
Ivan committed 2026-04-04 23:32:30 -05:00
1 parent 9f8ffbfc9b
commit a729e0320f
2 files changed
+38 -5

No files matched your search

@@ -56,11 +56,13 @@
v-model="searchQuery"
type="text"
placeholder="Search Hash or Via..."
class="input-field pl-10"
class="input-field pr-10"
autocomplete="off"
/>
<MaterialDesignIcon
icon-name="magnify"
class="absolute left-3 top-1/2 -translate-y-1/2 size-5 text-gray-400"
class="pointer-events-none absolute right-3 top-1/2 size-5 -translate-y-1/2 text-gray-400"
aria-hidden="true"
/>
</div>
<select v-model="filterInterface" class="input-field">
@@ -361,17 +363,29 @@ export default {
async refreshAll() {
this.isLoading = true;
try {
const [pathRes, rateRes, ifaceRes] = await Promise.all([
const [pathRes, rateRes, ifaceRes, discRes] = await Promise.all([
this.fetchPathTable(),
window.api.get("/api/v1/rnpath/rates"),
window.api.get("/api/v1/reticulum/interfaces"),
window.api.get("/api/v1/reticulum/discovered-interfaces").catch(() => ({ data: {} })),
]);
this.pathTable = pathRes.table;
this.totalItems = pathRes.total;
this.responsiveItems = pathRes.responsive;
this.unresponsiveItems = pathRes.unresponsive;
this.rateTable = rateRes.data.rates;
this.interfaces = Object.keys(ifaceRes.data.interfaces);
const nameSet = new Set(Object.keys(ifaceRes.data?.interfaces || {}));
for (const row of discRes.data?.active || []) {
if (row?.name) {
nameSet.add(String(row.name));
}
}
for (const d of discRes.data?.interfaces || []) {
if (d && typeof d === "object" && d.name) {
nameSet.add(String(d.name));
}
}
this.interfaces = Array.from(nameSet).sort();
} catch (e) {
console.error(e);
ToastUtils.error(this.$t("tools.rnpath.failed_fetch"));
+20 -1
View File
@@ -13,7 +13,7 @@ describe("RNPathPage.vue", () => {
window.api = axiosMock;
axiosMock.get.mockImplementation((url) => {
if (url === "/api/v1/rnpath/table") {
if (url.startsWith("/api/v1/rnpath/table")) {
return Promise.resolve({
data: {
table: [
@@ -25,6 +25,9 @@ describe("RNPathPage.vue", () => {
expires: 1234567890,
},
],
total: 1,
responsive: 1,
unresponsive: 0,
},
});
}
@@ -43,6 +46,21 @@ describe("RNPathPage.vue", () => {
},
});
}
if (url === "/api/v1/reticulum/interfaces") {
return Promise.resolve({
data: {
interfaces: { UDP: {} },
},
});
}
if (url === "/api/v1/reticulum/discovered-interfaces") {
return Promise.resolve({
data: {
interfaces: [{ name: "Discovered-IF" }],
active: [{ name: "Active-IF" }],
},
});
}
return Promise.resolve({ data: {} });
});
});
@@ -74,6 +92,7 @@ describe("RNPathPage.vue", () => {
expect(wrapper.text()).toContain("RNPath");
expect(wrapper.vm.pathTable.length).toBe(1);
expect(wrapper.vm.rateTable.length).toBe(1);
expect(wrapper.vm.interfaces).toEqual(["Active-IF", "Discovered-IF", "UDP"]);
});
it("switches tabs", async () => {