Skip to content

Commit

Permalink
Client dashboard improvements (#130)
Browse files Browse the repository at this point in the history
* Fix tunnel list ordering
* Add search functionality for tunnel list
* Proper error handling for empty request search
  • Loading branch information
amalshaji authored Dec 14, 2024
1 parent e3fee05 commit 2f4b6df
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 32 deletions.
18 changes: 16 additions & 2 deletions tunnel/internal/client/dashboard/service/tunnels.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
package service

import "github.com/amalshaji/portr/internal/client/db"
import (
"github.com/amalshaji/portr/internal/client/db"
)

func (s *Service) GetTunnels() ([]*db.Request, error) {
var result []*db.Request
s.db.Conn.Distinct("subdomain", "localport").Order("logged_at desc").Find(&result)
s.db.Conn.Raw(`
SELECT r.subdomain AS subdomain, r.localport AS localport
FROM requests r
INNER JOIN (
SELECT subdomain, localport, MAX(logged_at) as max_logged_at
FROM requests
GROUP BY subdomain, localport
) latest
ON r.subdomain = latest.subdomain
AND r.localport = latest.localport
AND r.logged_at = latest.max_logged_at
ORDER BY r.logged_at DESC
`).Find(&result)
return result, nil
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1 @@
<svg
width="231.4"
height="26.819654148298632"
viewBox="0 0 370 42.88363022848095"
><defs id="SvgjsDefs1483"></defs><g
id="SvgjsG1484"
transform="matrix(0.7177205101974772,0,0,0.7177205101974772,-10.886384173001131,-14.428765943671163)"
fill="#000000"
><g xmlns="http://www.w3.org/2000/svg"
><path
d="M26.957,43.888c-0.042-0.002-0.082-0.013-0.124-0.013h-8.831c-1.565,0-2.834,1.269-2.834,2.834v6.581 c0,1.565,1.269,2.835,2.834,2.835h8.831c0.042,0,0.082-0.011,0.124-0.013c2.537,7.35,9.499,12.638,17.71,12.638v-37.5 C36.455,31.25,29.494,36.538,26.957,43.888z"
></path><path
d="M81.999,43.875h-8.831c-0.042,0-0.082,0.011-0.124,0.013c-2.537-7.35-9.498-12.638-17.711-12.638v11.138h-6 c-0.829,0-1.5,0.671-1.5,1.5s0.671,1.5,1.5,1.5h6v9.225h-6c-0.829,0-1.5,0.672-1.5,1.5s0.671,1.5,1.5,1.5h6V68.75 c8.213,0,15.174-5.288,17.711-12.638c0.042,0.002,0.082,0.013,0.124,0.013h8.831c1.565,0,2.834-1.27,2.834-2.835v-6.581 C84.833,45.144,83.564,43.875,81.999,43.875z"
></path></g
></g
><g
id="SvgjsG1485"
transform="matrix(2.3180340664043757,0,0,2.3180340664043757,66.01298133946499,-13.073711825029742)"
fill="#2e2e2e"
><path
d="M3.66 7.300000000000001 l0 4.98 l3.86 0 c1.74 0 2.92 -0.64 2.92 -2.58 c0 -1.82 -1.24 -2.4 -2.84 -2.4 l-3.94 0 z M3.66 13.940000000000001 l0 6.06 l-1.94 0 l0 -14.36 l6.46 0 c2.66 0 4.26 1.72 4.26 4.04 c0 2 -1.14 4.26 -4.26 4.26 l-4.52 0 z M14.04 14.76 c0 -2.7 1.52 -5.52 4.86 -5.52 s4.86 2.82 4.86 5.52 s-1.52 5.52 -4.86 5.52 s-4.86 -2.82 -4.86 -5.52 z M15.86 14.76 c0 1.4 0.52 4 3.04 4 s3.04 -2.6 3.04 -4 s-0.52 -4 -3.04 -4 s-3.04 2.6 -3.04 4 z M27.76 13.92 l0 6.08 l-1.76 0 l0 -10.46 l1.66 0 l0 1.74 l0.04 0 c0.7 -1.22 1.62 -2.04 2.94 -2.04 c0.22 0 0.32 0.02 0.46 0.06 l0 1.82 l-0.66 0 c-1.64 0 -2.68 1.28 -2.68 2.8 z M36.26 11 l-1.68 0 l0 6.8 c0 0.82 0.7 0.82 1.06 0.82 l0.62 0 l0 1.38 c-0.64 0.06 -1.14 0.14 -1.32 0.14 c-1.74 0 -2.12 -0.98 -2.12 -2.24 l0 -6.9 l-1.42 0 l0 -1.46 l1.42 0 l0 -2.92 l1.76 0 l0 2.92 l1.68 0 l0 1.46 z M39.98 13.92 l0 6.08 l-1.76 0 l0 -10.46 l1.66 0 l0 1.74 l0.04 0 c0.7 -1.22 1.62 -2.04 2.94 -2.04 c0.22 0 0.32 0.02 0.46 0.06 l0 1.82 l-0.66 0 c-1.64 0 -2.68 1.28 -2.68 2.8 z M52.660000000000004 5.640000000000001 l0 14.36 l-1.94 0 l0 -14.36 l1.94 0 z M64.28 12.879999999999999 l0 7.12 l-1.76 0 l0 -6.44 c0 -1.82 -0.52 -2.74 -2.24 -2.74 c-1 0 -2.76 0.64 -2.76 3.48 l0 5.7 l-1.76 0 l0 -10.46 l1.66 0 l0 1.48 l0.04 0 c0.38 -0.56 1.36 -1.78 3.16 -1.78 c1.62 0 3.66 0.66 3.66 3.64 z M74.52000000000001 12.52 l-1.7 0 c-0.02 -0.66 -0.26 -1.76 -2.48 -1.76 c-0.54 0 -2.08 0.18 -2.08 1.48 c0 0.86 0.54 1.06 1.9 1.4 l1.76 0.44 c2.18 0.54 2.94 1.34 2.94 2.76 c0 2.16 -1.78 3.46 -4.14 3.46 c-4.14 0 -4.44 -2.4 -4.5 -3.66 l1.7 0 c0.06 0.82 0.3 2.14 2.78 2.14 c1.26 0 2.4 -0.5 2.4 -1.66 c0 -0.84 -0.58 -1.12 -2.08 -1.5 l-2.04 -0.5 c-1.46 -0.36 -2.42 -1.1 -2.42 -2.54 c0 -2.3 1.9 -3.34 3.96 -3.34 c3.74 0 4 2.76 4 3.28 z M78.42000000000002 15.26 c0 2.78 1.74 3.52 2.86 3.52 c1.92 0 2.82 -1.74 2.82 -4.04 c0 -1.34 -0.14 -3.92 -2.86 -3.92 c-2.54 0 -2.82 2.74 -2.82 4.44 z M76.74000000000001 24.14 l0 -14.6 l1.66 0 l0 1.48 l0.04 0 c0.42 -0.6 1.22 -1.78 3.12 -1.78 c2.78 0 4.36 2.28 4.36 5.22 c0 2.5 -1.04 5.84 -4.6 5.84 c-1.4 0 -2.32 -0.66 -2.78 -1.4 l-0.04 0 l0 5.24 l-1.76 0 z M95.12000000000002 16.72 l1.76 0 c-0.06 0.5 -0.54 1.98 -1.86 2.86 c-0.48 0.32 -1.16 0.72 -2.84 0.72 c-2.94 0 -4.68 -2.22 -4.68 -5.24 c0 -3.24 1.56 -5.82 5.02 -5.82 c3.02 0 4.5 2.4 4.5 6.1 l-7.64 0 c0 2.18 1.02 3.44 3.04 3.44 c1.66 0 2.64 -1.28 2.7 -2.06 z M89.38000000000002 13.940000000000001 l5.82 0 c-0.1 -1.62 -0.78 -3.12 -2.92 -3.12 c-1.62 0 -2.9 1.5 -2.9 3.12 z M107.36000000000001 13.059999999999999 l-1.7 0 c-0.22 -1.4 -1 -2.24 -2.48 -2.24 c-2.18 0 -2.88 2.08 -2.88 3.94 c0 1.8 0.44 4.02 2.86 4.02 c1.18 0 2.2 -0.88 2.5 -2.48 l1.7 0 c-0.18 1.66 -1.2 4 -4.26 4 c-2.94 0 -4.68 -2.22 -4.68 -5.24 c0 -3.24 1.56 -5.82 5.02 -5.82 c2.74 0 3.78 2 3.92 3.82 z M112.96000000000002 11 l-1.68 0 l0 6.8 c0 0.82 0.7 0.82 1.06 0.82 l0.62 0 l0 1.38 c-0.64 0.06 -1.14 0.14 -1.32 0.14 c-1.74 0 -2.12 -0.98 -2.12 -2.24 l0 -6.9 l-1.42 0 l0 -1.46 l1.42 0 l0 -2.92 l1.76 0 l0 2.92 l1.68 0 l0 1.46 z M114.08000000000003 14.76 c0 -2.7 1.52 -5.52 4.86 -5.52 s4.86 2.82 4.86 5.52 s-1.52 5.52 -4.86 5.52 s-4.86 -2.82 -4.86 -5.52 z M115.90000000000002 14.76 c0 1.4 0.52 4 3.04 4 s3.04 -2.6 3.04 -4 s-0.52 -4 -3.04 -4 s-3.04 2.6 -3.04 4 z M127.80000000000003 13.92 l0 6.08 l-1.76 0 l0 -10.46 l1.66 0 l0 1.74 l0.04 0 c0.7 -1.22 1.62 -2.04 2.94 -2.04 c0.22 0 0.32 0.02 0.46 0.06 l0 1.82 l-0.66 0 c-1.64 0 -2.68 1.28 -2.68 2.8 z"
></path></g
></svg
>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-search-code"><path d="m13 13.5 2-2.5-2-2.5"/><path d="m21 21-4.3-4.3"/><path d="M9 8.5 7 11l2 2.5"/><circle cx="11" cy="11" r="8"/></svg>
23 changes: 21 additions & 2 deletions tunnel/internal/client/dashboard/ui/src/pages/Home.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import { navigate } from "svelte-routing";
let tunnels: Tunnel[] = [];
let searchQuery = "";
const getRecentTunnels = async () => {
const response = await fetch("/api/tunnels");
Expand All @@ -15,14 +16,32 @@
navigate(`/${tunnel.Subdomain}-${tunnel.Localport}`);
};
$: filteredTunnels = tunnels.filter((tunnel) => {
const query = searchQuery.toLowerCase();
return (
tunnel.Subdomain.toLowerCase().includes(query) ||
tunnel.Localport.toString().includes(query)
);
});
onMount(() => {
getRecentTunnels();
});
</script>

<div class="mt-4 mx-auto grid place-items-center">
<input
type="text"
placeholder="Search by subdomain or port..."
bind:value={searchQuery}
class="w-1/4 mx-auto px-3 py-2 border rounded-md focus:outline-none"
/>
</div>

<div
class="place-items-center w-1/4 border mx-auto h-[750px] items-center overflow-auto my-12 rounded-lg"
class="place-items-center w-1/4 border mx-auto h-[750px] items-center overflow-auto mt-4 mb-12 rounded-lg"
>

<Table.Root>
<Table.Header>
<Table.Row>
Expand All @@ -31,7 +50,7 @@
</Table.Row>
</Table.Header>
<Table.Body>
{#each tunnels as tunnel, i (i)}
{#each filteredTunnels as tunnel, i (i)}
<Table.Row
on:click={() => gotoTunnel(tunnel)}
class="hover:cursor-pointer hover:bg-gray-100"
Expand Down
14 changes: 10 additions & 4 deletions tunnel/internal/client/dashboard/ui/src/pages/Inspect.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
let requests: Request[] = [];
let filteredRequests: Request[] = [];
let filterRequestError: string | null = null;
let search = "";
const getRequests = async () => {
Expand All @@ -44,12 +45,14 @@
const filterRequestsBasedOnUrl = () => {
filteredRequests = requests.filter((request) => {
return request.Url.includes(search);
return request.Url.toLowerCase().includes(search.toLowerCase().trim());
});
if (filteredRequests.length === 0) {
currentRequest.set(null);
filteredRequests = requests;
filterRequestError = "No results found";
} else {
currentRequest.set(filteredRequests[0]);
filterRequestError = null;
}
};
Expand All @@ -76,10 +79,13 @@
<header
class="flex items-center justify-between px-6 py-2 border-b dark:border-gray-800 bg-white dark:bg-gray-800"
>
<Link to="/">
<InspectorIcon />
<Link to="/" class="flex items-center gap-2">
<InspectorIcon /> <span class="text-lg">Portr Inspector</span>
</Link>
<div class="flex items-center space-x-4">
{#if filterRequestError}
<div class="text-red-500 text-sm">{filterRequestError}</div>
{/if}
<input
class="flex h-10 rounded-md border outline-none px-3 py-1 text-sm w-64"
placeholder="Filter URL"
Expand Down

0 comments on commit 2f4b6df

Please sign in to comment.