Dashboard: link each route to its public URL
This commit is contained in:
@@ -157,3 +157,12 @@ button:hover {
|
|||||||
.dim {
|
.dim {
|
||||||
color: #8b949e;
|
color: #8b949e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #58a6ff;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { Tunnel } from "./api";
|
import type { Tunnel } from "./api";
|
||||||
import { fmtDate, fmtRoutes } from "./format";
|
import { fmtDate, routeUrl } from "./format";
|
||||||
|
|
||||||
let { tunnels }: { tunnels: Tunnel[] | null } = $props();
|
let { tunnels }: { tunnels: Tunnel[] | null } = $props();
|
||||||
</script>
|
</script>
|
||||||
@@ -8,16 +8,34 @@
|
|||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Hostname</th><th>State</th><th>Routes</th><th>Visitors</th><th>Cert expiry</th><th>Created</th>
|
<th>Hostname</th><th>State</th><th>URLs</th><th>Visitors</th><th>Cert expiry</th><th>Created</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{#if tunnels && tunnels.length > 0}
|
{#if tunnels && tunnels.length > 0}
|
||||||
{#each tunnels as tunnel (tunnel.id)}
|
{#each tunnels as tunnel (tunnel.id)}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{tunnel.hostname}</td>
|
<td>
|
||||||
|
<a href={routeUrl(tunnel.hostname, "@")} target="_blank" rel="noreferrer">
|
||||||
|
{tunnel.hostname}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
<td><span class="pill {tunnel.state}">{tunnel.state}</span></td>
|
<td><span class="pill {tunnel.state}">{tunnel.state}</span></td>
|
||||||
<td class="dim">{fmtRoutes(tunnel.routes)}</td>
|
<td>
|
||||||
|
{#if tunnel.routes && tunnel.routes.length > 0}
|
||||||
|
<ul class="urls">
|
||||||
|
{#each tunnel.routes as route (route)}
|
||||||
|
<li>
|
||||||
|
<a href={routeUrl(tunnel.hostname, route)} target="_blank" rel="noreferrer">
|
||||||
|
{route === "@" ? tunnel.hostname : `${route}.${tunnel.hostname}`}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
{:else}
|
||||||
|
<span class="dim">–</span>
|
||||||
|
{/if}
|
||||||
|
</td>
|
||||||
<td>{tunnel.visitors}</td>
|
<td>{tunnel.visitors}</td>
|
||||||
<td>{fmtDate(tunnel.certificate_expiry)}</td>
|
<td>{fmtDate(tunnel.certificate_expiry)}</td>
|
||||||
<td>{fmtDate(tunnel.created_at)}</td>
|
<td>{fmtDate(tunnel.created_at)}</td>
|
||||||
@@ -28,3 +46,14 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.urls {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.urls li + li {
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -15,3 +15,9 @@ export function fmtUptime(seconds: number): string {
|
|||||||
export function fmtRoutes(routes: string[] | null): string {
|
export function fmtRoutes(routes: string[] | null): string {
|
||||||
return routes && routes.length > 0 ? routes.join(", ") : "–";
|
return routes && routes.length > 0 ? routes.join(", ") : "–";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// routeUrl is the public URL a route is served at: "@" is the tunnel
|
||||||
|
// hostname itself, any other route is a subdomain of it.
|
||||||
|
export function routeUrl(hostname: string, route: string): string {
|
||||||
|
return route === "@" ? `https://${hostname}` : `https://${route}.${hostname}`;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user