-
-
+
+
+
+
+ {#if $dashboardChat && activeResource?.kind === ResourceKind.Explore}
+
+ {/if}
- {#if $dashboardChat && activeResource?.kind === ResourceKind.Explore}
-
- {/if}
-
+
{/if}
diff --git a/web-admin/src/routes/-/embed/+layout.ts b/web-admin/src/routes/-/embed/+layout.ts
index 58f66473381..e7e440f7586 100644
--- a/web-admin/src/routes/-/embed/+layout.ts
+++ b/web-admin/src/routes/-/embed/+layout.ts
@@ -2,8 +2,6 @@ import { EmbedStore } from "@rilldata/web-common/features/embeds/embed-store.ts"
import { removeEmbedParams } from "@rilldata/web-admin/features/embeds/init-embed-public-api.ts";
import { ResourceKind } from "@rilldata/web-common/features/entity-management/resource-selectors.ts";
import { redirect } from "@sveltejs/kit";
-import { runtime } from "@rilldata/web-common/runtime-client/runtime-store.ts";
-import { queryClient } from "@rilldata/web-common/lib/svelte-query/globalQueryClient.ts";
export const load = async ({ url }) => {
const embedStore = EmbedStore.getInstance();
@@ -36,14 +34,6 @@ export const load = async ({ url }) => {
visibleExplores,
} = embedStore;
- await runtime.setRuntime(
- queryClient,
- runtimeHost,
- instanceId,
- accessToken,
- "embed",
- );
-
return {
instanceId,
runtimeHost,
diff --git a/web-admin/src/routes/-/embed/canvas/[name]/+page.svelte b/web-admin/src/routes/-/embed/canvas/[name]/+page.svelte
index a2ca814dd0b..ceffe8243ce 100644
--- a/web-admin/src/routes/-/embed/canvas/[name]/+page.svelte
+++ b/web-admin/src/routes/-/embed/canvas/[name]/+page.svelte
@@ -8,6 +8,8 @@
$: ({ canvasName, instanceId, navigationEnabled } = data);
-
-
-
+{#key instanceId}
+
+
+
+{/key}
diff --git a/web-admin/src/routes/[organization]/[project]/-/ai/+layout.ts b/web-admin/src/routes/[organization]/[project]/-/ai/+layout.ts
index 93caf27dbb2..d06fb2b190a 100644
--- a/web-admin/src/routes/[organization]/[project]/-/ai/+layout.ts
+++ b/web-admin/src/routes/[organization]/[project]/-/ai/+layout.ts
@@ -2,9 +2,8 @@ import {
getLastConversationId,
setLastConversationId,
} from "@rilldata/web-common/features/chat/layouts/fullpage/fullpage-store";
-import { featureFlags } from "@rilldata/web-common/features/feature-flags.js";
+import { getFeatureFlags } from "@rilldata/web-common/features/feature-flags.js";
import { redirect } from "@sveltejs/kit";
-import { get } from "svelte/store";
export const load = async ({
params: { organization, project, conversationId },
@@ -13,15 +12,13 @@ export const load = async ({
parent,
}) => {
// Wait for the feature flags to load
- await parent();
+ const { runtime } = await parent();
- // There is a potential race condition where feature flags from instance is not loaded yet.
- // So wait until it is ready before checking for "chat"
- await featureFlags.ready;
+ const fetchedFeatureFlags = await getFeatureFlags(runtime);
// Redirect to `/-/dashboards` if chat feature is disabled
// NOTE: In the future, we'll use user-level `ai` permissions for more granular access control
- const chatEnabled = get(featureFlags.chat);
+ const chatEnabled = Boolean(fetchedFeatureFlags.chat);
if (!chatEnabled) {
throw redirect(307, `/${organization}/${project}/-/dashboards`);
}
diff --git a/web-admin/src/routes/[organization]/[project]/-/alerts/[alert]/+layout.ts b/web-admin/src/routes/[organization]/[project]/-/alerts/[alert]/+layout.ts
index e5b659c85e5..921436f721e 100644
--- a/web-admin/src/routes/[organization]/[project]/-/alerts/[alert]/+layout.ts
+++ b/web-admin/src/routes/[organization]/[project]/-/alerts/[alert]/+layout.ts
@@ -9,7 +9,7 @@ export async function load({ params, parent }) {
const alertData = await queryClient
.fetchQuery(
- getRuntimeServiceGetResourceQueryOptions(runtime.instanceId, {
+ getRuntimeServiceGetResourceQueryOptions(runtime, {
"name.kind": ResourceKind.Alert,
"name.name": params.alert,
}),
diff --git a/web-admin/src/routes/[organization]/[project]/-/open-query/+page.ts b/web-admin/src/routes/[organization]/[project]/-/open-query/+page.ts
index e686e560d6c..114286d7d87 100644
--- a/web-admin/src/routes/[organization]/[project]/-/open-query/+page.ts
+++ b/web-admin/src/routes/[organization]/[project]/-/open-query/+page.ts
@@ -3,12 +3,13 @@ import type { PageLoad } from "./$types";
export const load: PageLoad = async ({ params, url, parent }) => {
// Only proceed once the runtime in parent is ready
- await parent();
+ const parentData = await parent();
// Get the organization and project from the URL
const organization = params.organization;
const project = params.project;
+ const runtime = parentData.runtime;
// Open the query (this'll redirect to the relevant Explore page)
- await openQuery({ url, organization, project });
+ await openQuery({ url, organization, project, runtime });
};
diff --git a/web-admin/src/routes/[organization]/[project]/-/reports/[report]/+layout.ts b/web-admin/src/routes/[organization]/[project]/-/reports/[report]/+layout.ts
index 84239f1d323..80f70692a77 100644
--- a/web-admin/src/routes/[organization]/[project]/-/reports/[report]/+layout.ts
+++ b/web-admin/src/routes/[organization]/[project]/-/reports/[report]/+layout.ts
@@ -9,7 +9,7 @@ export async function load({ params, parent }) {
const reportData = await queryClient
.fetchQuery(
- getRuntimeServiceGetResourceQueryOptions(runtime.instanceId, {
+ getRuntimeServiceGetResourceQueryOptions(runtime, {
"name.kind": ResourceKind.Report,
"name.name": params.report,
}),
diff --git a/web-admin/src/routes/[organization]/[project]/canvas/[dashboard]/+page.svelte b/web-admin/src/routes/[organization]/[project]/canvas/[dashboard]/+page.svelte
index 0d51586e43a..6342cd40fc4 100644
--- a/web-admin/src/routes/[organization]/[project]/canvas/[dashboard]/+page.svelte
+++ b/web-admin/src/routes/[organization]/[project]/canvas/[dashboard]/+page.svelte
@@ -13,6 +13,8 @@
$: ({ instanceId } = $runtime);
-
-
-
+{#key instanceId}
+
+
+
+{/key}
diff --git a/web-admin/tests/README.md b/web-admin/tests/README.md
index 43058531dbf..555554d68d0 100644
--- a/web-admin/tests/README.md
+++ b/web-admin/tests/README.md
@@ -11,7 +11,7 @@ Playwright recommends that global setup takes place in a dedicated Playwright "p
1. Starts a fresh instance of Rill Cloud
2. Logs-in via the e2e-admin@rilldata.com user (which has been pre-populated in our Auth0 staging database)
3. Creates an organization named `e2e`
-4. Deploys the OpenRTB project
+4. Deploys the OpenRTB and AdBids projects
5. Waits for data ingestion and asserts when the primary dashboard is ready-to-go
```bash
diff --git a/web-admin/tests/canvas.spec.ts b/web-admin/tests/canvas.spec.ts
index fae68017dc5..63c50d1c6ca 100644
--- a/web-admin/tests/canvas.spec.ts
+++ b/web-admin/tests/canvas.spec.ts
@@ -15,4 +15,23 @@ test.describe("Canvases", () => {
page.getByText("Advertising Spend Overall $3,900"),
).toBeVisible();
});
+
+ test("can switch projects from canvas", async ({ page }) => {
+ // Navigate to canvas
+ await page.goto("/e2e/openrtb/-/dashboards");
+ await page
+ .getByRole("link", { name: "Bids Canvas Dashboard" })
+ .first()
+ .click();
+
+ // navigate via breadcrumbs to another project
+ await page
+ .getByRole("button", { name: "Breadcrumb dropdown" })
+ .first()
+ .click();
+
+ await page.getByRole("link", { name: "AdBids" }).click();
+
+ await expect(page.getByText("Adbids Canvas Dashboard")).toBeVisible();
+ });
});
diff --git a/web-admin/tests/setup/setup.ts b/web-admin/tests/setup/setup.ts
index 09f68cbdb7f..ce2ddd7dd07 100644
--- a/web-admin/tests/setup/setup.ts
+++ b/web-admin/tests/setup/setup.ts
@@ -261,4 +261,68 @@ setup.describe("global setup", () => {
}),
).toContainText("Last refreshed", { timeout: 15_000 });
});
+
+ setup("should deploy the AdBids project", async ({ adminPage }) => {
+ // increase project quota for the organization
+ const { stdout: quotaUpdateStdout } = await execAsync(
+ `rill sudo quota set --org ${RILL_ORG_NAME} --projects 10`,
+ );
+ expect(quotaUpdateStdout).toContain(`Projects: 10`);
+
+ // Deploy the AdBids project
+ const { match } = await spawnAndMatch(
+ "rill",
+ [
+ "deploy",
+ "--path",
+ "../web-common/tests/projects/AdBids",
+ "--project",
+ "AdBids",
+ "--archive",
+ "--interactive=false",
+ ],
+ /https?:\/\/[^\s]+/,
+ );
+
+ // Navigate to the project URL and expect to see the successful deployment
+ const url = match[0];
+ await adminPage.goto(url);
+ await expect(
+ adminPage.getByRole("link", { name: RILL_ORG_NAME }),
+ ).toBeVisible(); // Organization breadcrumb
+ await expect(
+ adminPage.getByRole("link", { name: "AdBids", exact: true }),
+ ).toBeVisible(); // Project breadcrumb
+
+ // Expect to land on the project home page
+ await adminPage.waitForURL(`/${RILL_ORG_NAME}/AdBids`);
+ // Temporary fix to wait for the project to be ready.
+ // TODO: add a refetch to the project API
+ await expect
+ .poll(
+ async () => {
+ await adminPage.reload();
+ return adminPage.getByLabel("Project title").textContent();
+ },
+ { intervals: Array(4).fill(30_000), timeout: 120_000 },
+ )
+ .toContain(`Welcome to Untitled Rill Project`);
+
+ // Navigate to the dashboards page to validate the deployment
+ await adminPage.getByRole("link", { name: "Dashboards" }).click();
+ await adminPage.waitForURL("**/-/dashboards");
+
+ // Wait for the project to be ready
+ await expect(adminPage.getByLabel("Container title")).toHaveText(
+ "Project dashboards",
+ );
+
+ // Check that the dashboards are listed
+ await expect(
+ adminPage.getByRole("link", { name: "Adbids Canvas Dashboard" }).first(),
+ ).toBeVisible();
+ await expect(
+ adminPage.getByRole("link", { name: "Adbids dashboard" }),
+ ).toBeVisible();
+ });
});
diff --git a/web-common/src/features/canvas/CanvasInitialization.svelte b/web-common/src/features/canvas/CanvasInitialization.svelte
index a03bc7d2fbd..5b44bca537e 100644
--- a/web-common/src/features/canvas/CanvasInitialization.svelte
+++ b/web-common/src/features/canvas/CanvasInitialization.svelte
@@ -85,6 +85,7 @@
fetchedCanvas,
isReconciling,
existingStore,
+ instanceId,
);
$: ready = !!resolvedStore;
@@ -146,6 +147,7 @@
fetchedCanvas: V1ResolveCanvasResponse | undefined,
isReconciling: boolean,
existingStore: CanvasStore | undefined,
+ instanceId: string,
) {
if (fetchedCanvas && !isReconciling) {
const metricsViews: Record
= {};
diff --git a/web-common/src/features/canvas/selector.ts b/web-common/src/features/canvas/selector.ts
index ca581c5d792..b42eac3c4e1 100644
--- a/web-common/src/features/canvas/selector.ts
+++ b/web-common/src/features/canvas/selector.ts
@@ -125,7 +125,7 @@ export function useCanvas(
};
},
- enabled: !!canvasName,
+ enabled: !!canvasName && !!instanceId,
...queryOptions,
},
},
diff --git a/web-common/src/features/explore-mappers/open-query.ts b/web-common/src/features/explore-mappers/open-query.ts
index 5818e5eccf8..c8c8b4bdde2 100644
--- a/web-common/src/features/explore-mappers/open-query.ts
+++ b/web-common/src/features/explore-mappers/open-query.ts
@@ -1,25 +1,35 @@
import type { ExploreState } from "@rilldata/web-common/features/dashboards/stores/explore-state";
import { ResourceKind } from "@rilldata/web-common/features/entity-management/resource-selectors.js";
-import { generateExploreLink } from "@rilldata/web-common/features/explore-mappers/generate-explore-link";
+import { getUrlForExplore } from "@rilldata/web-common/features/explore-mappers/generate-explore-link";
import { mapMetricsResolverQueryToDashboard } from "@rilldata/web-common/features/explore-mappers/map-metrics-resolver-query-to-dashboard.ts";
import { queryClient } from "@rilldata/web-common/lib/svelte-query/globalQueryClient";
import {
+ getQueryServiceMetricsViewTimeRangeQueryKey,
getRuntimeServiceGetExploreQueryKey,
getRuntimeServiceListResourcesQueryKey,
- runtimeServiceGetExplore,
- runtimeServiceListResources,
+ type V1ExploreSpec,
+ type V1GetExploreResponse,
+ type V1ListResourcesResponse,
+ type V1MetricsViewSpec,
+ type V1MetricsViewTimeRangeResponse,
} from "@rilldata/web-common/runtime-client";
import type { Schema as MetricsResolverQuery } from "@rilldata/web-common/runtime-client/gen/resolvers/metrics/schema.ts";
-import { runtime } from "@rilldata/web-common/runtime-client/runtime-store";
import { error, redirect } from "@sveltejs/kit";
-import { get } from "svelte/store";
+import type { Runtime } from "@rilldata/web-common/runtime-client/runtime-store.ts";
+import httpClient from "@rilldata/web-common/runtime-client/http-client.ts";
+import { getTimeControlState } from "@rilldata/web-common/features/dashboards/time-controls/time-control-store.ts";
+import { convertPartialExploreStateToUrlParams } from "@rilldata/web-common/features/dashboards/url-state/convert-partial-explore-state-to-url-params.ts";
+import { createLinkError } from "@rilldata/web-common/features/explore-mappers/explore-validation.ts";
+import { ExploreLinkErrorType } from "@rilldata/web-common/features/explore-mappers/types.ts";
export async function openQuery({
url,
organization,
project,
+ runtime,
}: {
url: URL;
+ runtime: Runtime;
organization?: string;
project?: string;
}) {
@@ -49,14 +59,29 @@ export async function openQuery({
}
// Find an explore dashboard that uses this metrics view
- const exploreName = await findExploreForMetricsView(metricsViewName);
+ const exploreName = await findExploreForMetricsView(
+ runtime,
+ metricsViewName,
+ );
+
+ const { metricsViewSpec, exploreSpec } = await getExploreSpecs(
+ runtime,
+ exploreName,
+ );
// Convert query to ExploreState
- const exploreState = await convertQueryToExploreState(query, exploreName);
+ const exploreState = mapMetricsResolverQueryToDashboard(
+ metricsViewSpec,
+ exploreSpec,
+ query,
+ );
// Generate the final explore URL
exploreURL = await generateExploreLink(
+ runtime,
exploreState,
+ metricsViewSpec,
+ exploreSpec,
exploreName,
organization,
project,
@@ -81,21 +106,27 @@ export async function openQuery({
* TODO: try to find an explore that has as many measures/dimensions in the query
*/
async function findExploreForMetricsView(
+ runtime: Runtime,
metricsViewName: string,
): Promise {
- const instanceId = get(runtime).instanceId;
-
// List all explore resources
const exploreResources = await queryClient.fetchQuery({
- queryKey: getRuntimeServiceListResourcesQueryKey(instanceId, {
+ queryKey: getRuntimeServiceListResourcesQueryKey(runtime.instanceId, {
kind: ResourceKind.Explore,
}),
queryFn: ({ signal }) =>
- runtimeServiceListResources(
- instanceId,
- { kind: ResourceKind.Explore },
+ httpClient({
+ url: `/v1/instances/${runtime.instanceId}/resources`,
+ method: "GET",
+ params: { kind: ResourceKind.Explore },
signal,
- ),
+ baseUrl: runtime.host,
+ headers: runtime.jwt
+ ? {
+ Authorization: `Bearer ${runtime.jwt?.token}`,
+ }
+ : undefined,
+ }),
});
// Look for an explore that references this metrics view
@@ -113,28 +144,25 @@ async function findExploreForMetricsView(
);
}
-/**
- * Convert Query directly to ExploreState without going through URL parameters.
- */
-async function convertQueryToExploreState(
- query: MetricsResolverQuery,
- exploreName: string,
-): Promise> {
- const instanceId = get(runtime).instanceId;
-
+async function getExploreSpecs(runtime: Runtime, exploreName: string) {
// Get explore and metrics view specs
const getExploreResponse = await queryClient.fetchQuery({
- queryKey: getRuntimeServiceGetExploreQueryKey(instanceId, {
+ queryKey: getRuntimeServiceGetExploreQueryKey(runtime.instanceId, {
name: exploreName,
}),
queryFn: ({ signal }) =>
- runtimeServiceGetExplore(
- instanceId,
- {
- name: exploreName,
- },
+ httpClient({
+ url: `/v1/instances/${runtime.instanceId}/resources/explore`,
+ method: "GET",
+ params: { name: exploreName },
signal,
- ),
+ baseUrl: runtime.host,
+ headers: runtime.jwt
+ ? {
+ Authorization: `Bearer ${runtime.jwt?.token}`,
+ }
+ : undefined,
+ }),
});
const exploreResource = getExploreResponse.explore;
const metricsViewResource = getExploreResponse.metricsView;
@@ -150,8 +178,79 @@ async function convertQueryToExploreState(
const metricsViewSpec = metricsViewResource?.metricsView?.state?.validSpec;
const exploreSpec = exploreResource.explore.state.validSpec;
- const partialExploreState: Partial =
- mapMetricsResolverQueryToDashboard(metricsViewSpec, exploreSpec, query);
+ return { metricsViewSpec, exploreSpec };
+}
+
+/**
+ * Generates the explore page URL with proper search parameters
+ */
+async function generateExploreLink(
+ runtime: Runtime,
+ exploreState: Partial,
+ metricsViewSpec: V1MetricsViewSpec,
+ exploreSpec: V1ExploreSpec,
+ exploreName: string,
+ organization?: string | undefined,
+ project?: string | undefined,
+): Promise {
+ try {
+ // Build base URL
+ const url = getUrlForExplore(exploreName, organization, project);
+
+ const metricsViewName = exploreSpec.metricsView;
+ let fullTimeRange: V1MetricsViewTimeRangeResponse | undefined;
+ if (metricsViewSpec.timeDimension && metricsViewName) {
+ fullTimeRange = await queryClient.fetchQuery({
+ queryFn: ({ signal }) =>
+ httpClient({
+ url: `/v1/instances/${runtime.instanceId}/queries/metrics-views/${metricsViewName}/time-range-summary`,
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ ...(runtime.jwt
+ ? {
+ Authorization: `Bearer ${runtime.jwt?.token}`,
+ }
+ : {}),
+ },
+ data: {},
+ signal,
+ baseUrl: runtime.host,
+ }),
+ queryKey: getQueryServiceMetricsViewTimeRangeQueryKey(
+ runtime.instanceId,
+ metricsViewName,
+ {},
+ ),
+ staleTime: Infinity,
+ gcTime: Infinity,
+ });
+ }
- return partialExploreState;
+ // This is just for an initial redirect.
+ // DashboardStateDataLoader will handle compression etc. during init
+ // So no need to use getCleanedUrlParamsForGoto
+ const searchParams = convertPartialExploreStateToUrlParams(
+ exploreSpec,
+ exploreState,
+ getTimeControlState(
+ metricsViewSpec,
+ exploreSpec,
+ fullTimeRange?.timeRangeSummary,
+ exploreState,
+ ),
+ );
+
+ searchParams.forEach((value, key) => {
+ url.searchParams.set(key, value);
+ });
+
+ return url.toString();
+ } catch (error) {
+ throw createLinkError(
+ ExploreLinkErrorType.TRANSFORMATION_ERROR,
+ `Failed to generate explore link: ${error.message}`,
+ error,
+ );
+ }
}
diff --git a/web-common/src/features/feature-flags.ts b/web-common/src/features/feature-flags.ts
index 9d736fcea3a..a838158aef6 100644
--- a/web-common/src/features/feature-flags.ts
+++ b/web-common/src/features/feature-flags.ts
@@ -2,9 +2,12 @@ import { queryClient } from "@rilldata/web-common/lib/svelte-query/globalQueryCl
import { writable } from "svelte/store";
import {
createRuntimeServiceGetInstance,
+ getRuntimeServiceGetInstanceQueryKey,
+ type V1GetInstanceResponse,
type V1InstanceFeatureFlags,
} from "../runtime-client";
-import { runtime } from "../runtime-client/runtime-store";
+import { type Runtime, runtime } from "../runtime-client/runtime-store";
+import httpClient from "@rilldata/web-common/runtime-client/http-client.ts";
class FeatureFlag {
private _internal = false;
@@ -123,3 +126,25 @@ class FeatureFlags {
}
export const featureFlags = new FeatureFlags();
+
+export async function getFeatureFlags(runtime: Runtime) {
+ const instanceResp = await queryClient.fetchQuery({
+ queryKey: getRuntimeServiceGetInstanceQueryKey(
+ runtime.instanceId,
+ undefined,
+ ),
+ queryFn: () =>
+ httpClient({
+ url: `/v1/instances/${runtime.instanceId}`,
+ method: "GET",
+ baseUrl: runtime.host,
+ headers: runtime.jwt
+ ? {
+ Authorization: `Bearer ${runtime.jwt?.token}`,
+ }
+ : undefined,
+ }),
+ });
+
+ return instanceResp.instance?.featureFlags ?? {};
+}
diff --git a/web-common/src/features/workspaces/CanvasWorkspace.svelte b/web-common/src/features/workspaces/CanvasWorkspace.svelte
index 42459b480d5..2dfdaac1a9d 100644
--- a/web-common/src/features/workspaces/CanvasWorkspace.svelte
+++ b/web-common/src/features/workspaces/CanvasWorkspace.svelte
@@ -121,20 +121,18 @@
{lineBasedRuntimeErrors}
/>
{:else if selectedView === "viz"}
- {#if ready}
-
-
-
- {/if}
+
+
+
{/if}
diff --git a/web-common/src/runtime-client/http-client.ts b/web-common/src/runtime-client/http-client.ts
index b51c75331ea..6a5fcb1aa6e 100644
--- a/web-common/src/runtime-client/http-client.ts
+++ b/web-common/src/runtime-client/http-client.ts
@@ -23,9 +23,10 @@ export const httpClient = async (
): Promise => {
// Naive request interceptors
+ const interceptedConfig = { ...config };
// Set host
const host = get(runtime).host;
- const interceptedConfig = { ...config, baseUrl: host };
+ if (host) interceptedConfig.baseUrl = host;
// Set JWT
let jwt = get(runtime).jwt;
diff --git a/web-common/src/runtime-client/http-request-queue/HttpRequestQueue.ts b/web-common/src/runtime-client/http-request-queue/HttpRequestQueue.ts
index 8b2a9fe4850..5158ecb3ab8 100644
--- a/web-common/src/runtime-client/http-request-queue/HttpRequestQueue.ts
+++ b/web-common/src/runtime-client/http-request-queue/HttpRequestQueue.ts
@@ -51,7 +51,7 @@ export class HttpRequestQueue {
public add(requestOptions: FetchWrapperOptions) {
// prepend after parsing to make parsing faster
- requestOptions.url = `${requestOptions?.baseUrl}${requestOptions.url}`;
+ requestOptions.url = `${requestOptions?.baseUrl ?? ""}${requestOptions.url}`;
const urlMatch = UrlExtractorRegex.exec(requestOptions.url);
diff --git a/web-common/src/runtime-client/query-options.ts b/web-common/src/runtime-client/query-options.ts
index baab2c7e692..bbc7a29cd45 100644
--- a/web-common/src/runtime-client/query-options.ts
+++ b/web-common/src/runtime-client/query-options.ts
@@ -1,18 +1,31 @@
import type { FetchQueryOptions } from "@tanstack/svelte-query";
-import type { RuntimeServiceGetResourceParams } from "./gen/index.schemas";
+import type {
+ RuntimeServiceGetResourceParams,
+ V1GetResourceResponse,
+} from "./gen/index.schemas";
import type { RuntimeServiceGetResourceQueryResult } from "./gen/runtime-service/runtime-service";
-import {
- getRuntimeServiceGetResourceQueryKey,
- runtimeServiceGetResource,
-} from "./gen/runtime-service/runtime-service";
+import { getRuntimeServiceGetResourceQueryKey } from "./gen/runtime-service/runtime-service";
+import httpClient from "@rilldata/web-common/runtime-client/http-client.ts";
+import type { Runtime } from "@rilldata/web-common/runtime-client/runtime-store.ts";
export function getRuntimeServiceGetResourceQueryOptions(
- instanceId: string,
+ runtime: Runtime,
params: RuntimeServiceGetResourceParams,
) {
return >{
- queryKey: getRuntimeServiceGetResourceQueryKey(instanceId, params),
- queryFn: () => runtimeServiceGetResource(instanceId, params),
+ queryKey: getRuntimeServiceGetResourceQueryKey(runtime.instanceId, params),
+ queryFn: () =>
+ httpClient({
+ url: `/v1/instances/${runtime.instanceId}/resource`,
+ method: "GET",
+ params,
+ baseUrl: runtime.host,
+ headers: runtime.jwt
+ ? {
+ Authorization: `Bearer ${runtime.jwt?.token}`,
+ }
+ : undefined,
+ }),
staleTime: Infinity,
};
}
diff --git a/web-local/src/routes/(viz)/-/open-query/+page.ts b/web-local/src/routes/(viz)/-/open-query/+page.ts
index 7b927a008af..41913ceaffa 100644
--- a/web-local/src/routes/(viz)/-/open-query/+page.ts
+++ b/web-local/src/routes/(viz)/-/open-query/+page.ts
@@ -1,6 +1,10 @@
import { openQuery } from "@rilldata/web-common/features/explore-mappers/open-query";
+import { runtime } from "@rilldata/web-common/runtime-client/runtime-store";
+import { get } from "svelte/store";
export async function load({ url }) {
+ const rt = get(runtime);
+
// Open the query (this'll redirect to the relevant Explore page)
- await openQuery({ url });
+ await openQuery({ url, runtime: rt });
}
diff --git a/web-local/src/routes/(viz)/canvas/[name]/+page.svelte b/web-local/src/routes/(viz)/canvas/[name]/+page.svelte
index ea60dfe8220..83f6c69c117 100644
--- a/web-local/src/routes/(viz)/canvas/[name]/+page.svelte
+++ b/web-local/src/routes/(viz)/canvas/[name]/+page.svelte
@@ -10,6 +10,8 @@
$: ({ canvasName } = data);
-
-
-
+{#key instanceId}
+
+
+
+{/key}