Skip to content

Commit 35cb94a

Browse files
authored
feat(explorer): pause/resume live query (#3445)
1 parent 53f7906 commit 35cb94a

File tree

5 files changed

+42
-9
lines changed

5 files changed

+42
-9
lines changed

.changeset/fair-rocks-exercise.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@latticexyz/explorer": patch
3+
---
4+
5+
SQL live queries in the Explore view table can now be paused and resumed.

packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/explore/Explorer.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { useParams } from "next/navigation";
44
import { parseAsString, useQueryState } from "nuqs";
55
import { Hex } from "viem";
6-
import { useEffect } from "react";
6+
import { useEffect, useState } from "react";
77
import { useChain } from "../../../../hooks/useChain";
88
import { usePrevious } from "../../../../hooks/usePrevious";
99
import { useTablesQuery } from "../../../../queries/useTablesQuery";
@@ -17,6 +17,7 @@ export function Explorer() {
1717
const { worldAddress } = useParams();
1818
const { id: chainId } = useChain();
1919
const indexer = indexerForChainId(chainId);
20+
const [isLiveQuery, setIsLiveQuery] = useState(true);
2021
const [query, setQuery] = useQueryState("query", parseAsString.withDefault(""));
2122
const [selectedTableId] = useQueryState("tableId");
2223
const prevSelectedTableId = usePrevious(selectedTableId);
@@ -40,8 +41,10 @@ export function Explorer() {
4041
return (
4142
<div className="space-y-4">
4243
<TableSelector tables={tables} />
43-
{indexer.type !== "sqlite" && <SQLEditor table={table} />}
44-
<TablesViewer table={table} query={query} />
44+
{indexer.type !== "sqlite" && (
45+
<SQLEditor table={table} isLiveQuery={isLiveQuery} setIsLiveQuery={setIsLiveQuery} />
46+
)}
47+
<TablesViewer table={table} query={query} isLiveQuery={isLiveQuery} />
4548
</div>
4649
);
4750
}

packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/explore/SQLEditor.tsx

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use client";
22

3-
import { CommandIcon, CornerDownLeft } from "lucide-react";
3+
import { CommandIcon, CornerDownLeft, PauseIcon, PlayIcon } from "lucide-react";
44
import { KeyCode, KeyMod, editor } from "monaco-editor/esm/vs/editor/editor.api";
55
import { useQueryState } from "nuqs";
66
import { useEffect, useRef, useState } from "react";
@@ -16,9 +16,11 @@ import { useQueryValidator } from "./useQueryValidator";
1616

1717
type Props = {
1818
table?: Table;
19+
isLiveQuery: boolean;
20+
setIsLiveQuery: (isLiveQuery: boolean) => void;
1921
};
2022

21-
export function SQLEditor({ table }: Props) {
23+
export function SQLEditor({ table, isLiveQuery, setIsLiveQuery }: Props) {
2224
const editorRef = useRef<editor.IStandaloneCodeEditor | null>(null);
2325
const containerRef = useRef<HTMLDivElement>(null);
2426
const [isFocused, setIsFocused] = useState(false);
@@ -105,7 +107,16 @@ export function SQLEditor({ table }: Props) {
105107
) : null}
106108
</div>
107109

108-
<div className="flex justify-end">
110+
<div className="flex justify-end gap-2">
111+
<Button
112+
variant="ghost"
113+
size="icon"
114+
onClick={() => setIsLiveQuery(!isLiveQuery)}
115+
title={isLiveQuery ? "Pause live query" : "Start live query"}
116+
>
117+
{isLiveQuery ? <PlayIcon className="h-4 w-4" /> : <PauseIcon className="h-4 w-4" />}
118+
</Button>
119+
109120
<Button className="flex gap-2 pl-4 pr-3" type="submit">
110121
Run
111122
<span className="flex items-center gap-0.5 text-white/60">

packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/explore/TablesViewer.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,20 @@ import { typeSortingFn } from "./utils/typeSortingFn";
2626
const initialSortingState: SortingState = [];
2727
const initialRows: TData["rows"] = [];
2828

29-
export function TablesViewer({ table, query }: { table?: TableType; query?: string }) {
30-
const { data: tableData, isLoading: isTDataLoading, isFetched, isError, error } = useTableDataQuery({ table, query });
29+
type Props = {
30+
table?: TableType;
31+
query?: string;
32+
isLiveQuery: boolean;
33+
};
34+
35+
export function TablesViewer({ table, query, isLiveQuery }: Props) {
36+
const {
37+
data: tableData,
38+
isLoading: isTDataLoading,
39+
isFetched,
40+
isError,
41+
error,
42+
} = useTableDataQuery({ table, query, isLiveQuery });
3143
const isLoading = isTDataLoading || !isFetched;
3244
const [globalFilter, setGlobalFilter] = useQueryState("filter", parseAsString.withDefault(""));
3345
const [sorting, setSorting] = useQueryState("sort", parseAsJson<SortingState>().withDefault(initialSortingState));

packages/explorer/src/app/(explorer)/queries/useTableDataQuery.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { indexerForChainId } from "../utils/indexerForChainId";
99
type Props = {
1010
table: Table | undefined;
1111
query: string | undefined;
12+
isLiveQuery: boolean;
1213
};
1314

1415
export type TDataRow = Record<string, unknown>;
@@ -17,7 +18,7 @@ export type TData = {
1718
rows: TDataRow[];
1819
};
1920

20-
export function useTableDataQuery({ table, query }: Props) {
21+
export function useTableDataQuery({ table, query, isLiveQuery }: Props) {
2122
const { chainName, worldAddress } = useParams();
2223
const { id: chainId } = useChain();
2324
const decodedQuery = decodeURIComponent(query ?? "");
@@ -81,6 +82,7 @@ export function useTableDataQuery({ table, query }: Props) {
8182
enabled: !!table && !!query,
8283
refetchInterval: (query) => {
8384
if (query.state.error) return false;
85+
else if (isLiveQuery) return false;
8486
return 1000;
8587
},
8688
});

0 commit comments

Comments
 (0)