diff --git a/app/src/routes/explorer/(components)/cell-duration-text.svelte b/app/src/routes/explorer/(components)/cell-duration-text.svelte
new file mode 100644
index 0000000000..beec2e1bf6
--- /dev/null
+++ b/app/src/routes/explorer/(components)/cell-duration-text.svelte
@@ -0,0 +1,13 @@
+
+
+
+
diff --git a/app/src/routes/explorer/(components)/cell-text.svelte b/app/src/routes/explorer/(components)/cell-plain-text.svelte
similarity index 100%
rename from app/src/routes/explorer/(components)/cell-text.svelte
rename to app/src/routes/explorer/(components)/cell-plain-text.svelte
diff --git a/app/src/routes/explorer/(components)/menu.svelte b/app/src/routes/explorer/(components)/menu.svelte
index c1d81508ee..cffec5153b 100644
--- a/app/src/routes/explorer/(components)/menu.svelte
+++ b/app/src/routes/explorer/(components)/menu.svelte
@@ -61,7 +61,7 @@ let alwaysCollapsed = innerWidth <= alwaysCollapsedWidth
)}
>
- {route}
+ {route.replaceAll('-', ' ')}
{/if}
{/each}
diff --git a/app/src/routes/explorer/+layout.svelte b/app/src/routes/explorer/+layout.svelte
index 1840a2dbf7..600fed0718 100644
--- a/app/src/routes/explorer/+layout.svelte
+++ b/app/src/routes/explorer/+layout.svelte
@@ -6,29 +6,39 @@ import { cn } from "$lib/utilities/shadcn.ts"
import * as Resizable from "$lib/components/ui/resizable"
import GripVerticalIcon from "virtual:icons/tabler/grip-vertical"
import { ScrollArea } from "$lib/components/ui/scroll-area/index.ts"
+import { page } from "$app/stores"
+import { derived } from "svelte/store"
+import { onNavigate } from "$app/navigation"
export let data: LayoutData
-let windowSize = { width: window.innerWidth, height: window.innerHeight }
+// Pane collapse on resize has been disabled because it was throwing console errors.
-const handleResize = () => {
- requestAnimationFrame(() => {
- windowSize = { width: window.innerWidth, height: window.innerHeight }
- })
-}
+// let windowSize = { width: window.innerWidth, height: window.innerHeight }
-onMount(() => {
- window.addEventListener("resize", handleResize)
- return () => {
- window.removeEventListener("resize", handleResize)
- }
-})
+// const handleResize = () => {
+// requestAnimationFrame(() => {
+// windowSize = { width: window.innerWidth, height: window.innerHeight }
+// })
+// }
+
+// onMount(() => {
+// window.addEventListener("resize", handleResize)
+// return () => {
+// window.removeEventListener("resize", handleResize)
+// }
+// })
+
+// $: if (windowSize?.width < 900) {
+// try {
+// leftPane.collapse()
+// // biome-ignore lint/suspicious/noEmptyBlockStatements:
+// } catch {}
+// }
let isCollapsed = false
let leftPane: Resizable.PaneAPI
-$: [leftSize, rightSize] = [12, 88]
-
-$: if (windowSize.width < 900) leftPane.collapse()
+$: [leftSize, rightSize] = [14, 88]
const onLayoutChange: Resizable.PaneGroupProps["onLayoutChange"] = sizes => {
document.cookie = `PaneForge:layout=${JSON.stringify(sizes)}`
@@ -43,21 +53,29 @@ const onExpand: Resizable.PaneProps["onExpand"] = () => {
isCollapsed = false
document.cookie = `PaneForge:collapsed=${false}`
}
+
+let explorerRoute = $page.route.id?.split("/").at(-1)
+$: explorerPageDescription = data.tables.filter(t => t.route === explorerRoute)[0].description
+onNavigate(navigation => {
+ if (navigation.to?.route.id?.split("/").at(1) === "explorer") {
+ explorerRoute = navigation.to?.route.id?.split("/").at(2)
+ }
+})
-
+
@@ -71,9 +89,11 @@ const onExpand: Resizable.PaneProps["onExpand"] = () => {
-
-
-
+
+
+ {explorerRoute?.replaceAll('-', ' ')}
+ {explorerPageDescription}
+
diff --git a/app/src/routes/explorer/+layout.ts b/app/src/routes/explorer/+layout.ts
index 02853b088d..e2dc8c2a10 100644
--- a/app/src/routes/explorer/+layout.ts
+++ b/app/src/routes/explorer/+layout.ts
@@ -4,6 +4,8 @@ import type { SvelteComponent } from "svelte"
import TvIcon from "virtual:icons/lucide/tv"
import BlocksIcon from "virtual:icons/lucide/blocks"
+import RocketIcon from "virtual:icons/lucide/rocket"
+import DatabaseIcon from "virtual:icons/lucide/database"
import ConnectionIcon from "virtual:icons/mdi/connection"
import SendHorizontalIcon from "virtual:icons/lucide/send-horizontal"
@@ -12,6 +14,7 @@ const tables = ["blocks", "packets", "channels", "connections"] as const
export interface Table {
route: (typeof tables)[number]
icon: typeof SvelteComponent
+ description: string
}
export const load = (loadEvent => {
@@ -20,10 +23,24 @@ export const load = (loadEvent => {
return {
tables: [
- { route: "blocks", icon: BlocksIcon },
- { route: "channels", icon: TvIcon },
- { route: "packets", icon: SendHorizontalIcon },
- { route: "connections", icon: ConnectionIcon }
+ {
+ route: "blocks",
+ icon: BlocksIcon,
+ description: "Blocks from all chains indexed by Hubble"
+ },
+ { route: "connections", icon: ConnectionIcon, description: "Open IBC Connections" },
+ { route: "channels", icon: TvIcon, description: "Open IBC Channels" },
+ { route: "packets", icon: SendHorizontalIcon, description: "Packets sent through Union" },
+ {
+ route: "voyager-queue",
+ icon: RocketIcon,
+ description: "Voyager Relayer VM Operations Queue"
+ },
+ {
+ route: "index-status",
+ icon: DatabaseIcon,
+ description: "Statuses of Hubble indices for connected chains"
+ }
] as Array
}
}) satisfies LayoutLoad
diff --git a/app/src/routes/explorer/blocks/+page.svelte b/app/src/routes/explorer/blocks/+page.svelte
index b594c21f0c..7aeac99cda 100644
--- a/app/src/routes/explorer/blocks/+page.svelte
+++ b/app/src/routes/explorer/blocks/+page.svelte
@@ -11,16 +11,17 @@ import {
import request from "graphql-request"
import { URLS } from "$lib/constants"
import { writable } from "svelte/store"
+import { DurationUnits } from "svelte-ux"
import { cn } from "$lib/utilities/shadcn.ts"
import { CHAIN_MAP } from "$lib/constants/chains"
import * as Table from "$lib/components/ui/table"
-import { Duration, DurationUnits } from "svelte-ux"
import { createQuery } from "@tanstack/svelte-query"
-import CellText from "../(components)/cell-text.svelte"
import { removeArrayDuplicates } from "$lib/utilities"
import type { Override } from "$lib/utilities/types.ts"
import { createVirtualizer } from "@tanstack/svelte-virtual"
import Button from "$lib/components/ui/button/button.svelte"
+import CellText from "../(components)/cell-plain-text.svelte"
+import CellDurationText from "../(components)/cell-duration-text.svelte"
import { cosmosBlocksQuery } from "$lib/graphql/documents/cosmos-blocks.ts"
$: cosmosBlocks = createQuery({
@@ -47,26 +48,24 @@ $: if (blockData) {
const defaultColumns: Array> = [
{
accessorKey: "time",
- size: 105,
- maxSize: 105,
+ size: 100,
meta: {
class: "ml-1.5 justify-start"
},
header: info => "Time",
cell: info =>
- flexRender(Duration, {
+ flexRender(CellDurationText, {
totalUnits: 3,
variant: "short",
+ class: "pl-2 text-clip",
minUnits: DurationUnits.Second,
- start: new Date(info.getValue() as string),
- class: "pl-2 after:content-['_ago'] sm:after:content-[''] text-clip"
+ start: new Date(info.getValue() as string)
})
},
{
accessorKey: "height",
header: info => "Height",
size: 100,
- maxSize: 100,
meta: {
class: "w-full justify-start"
},
@@ -98,11 +97,10 @@ const defaultColumns: Array> = [
{
accessorKey: "hash",
meta: {
- class: "w-full justify-end"
+ class: "w-full justify-start ml-1.5"
},
- header: info => flexRender(CellText, { value: "Hash", class: "text-right pr-3" }),
- size: 400,
- maxSize: 400,
+ header: info => flexRender(CellText, { value: "Hash", class: "text-left" }),
+ size: 1000,
cell: info =>
flexRender(Button, {
class: "py-0 px-2.5 max-w-[600px]",
@@ -152,12 +150,13 @@ $: virtualizer = createVirtualizer({
})
-
+
+ Union - Explorer
+
+
({
on:click={header.column.getToggleSortingHandler()}
class={cn(
header.column.columnDef.meta?.class,
- 'cursor-pointer select-none capitalize px-0 hover:bg-transparent font-mono text-md',
+ 'cursor-pointer select-none capitalize px-0 hover:bg-transparent text-md',
)}
>
({
-