From 7f200820d8a69ff0414bce62df14cb44f41a2262 Mon Sep 17 00:00:00 2001 From: Aditya Hegde Date: Thu, 27 Aug 2026 10:53:43 +0530 Subject: [PATCH 1/5] feat: cloud editing view-as support --- .../edit-session/EditSessionViewAs.svelte | 72 +++++++++++++++++++ .../projects/header/ProjectHeader.svelte | 2 + 2 files changed, 74 insertions(+) create mode 100644 web-admin/src/features/edit-session/EditSessionViewAs.svelte diff --git a/web-admin/src/features/edit-session/EditSessionViewAs.svelte b/web-admin/src/features/edit-session/EditSessionViewAs.svelte new file mode 100644 index 000000000000..269cb8e3745d --- /dev/null +++ b/web-admin/src/features/edit-session/EditSessionViewAs.svelte @@ -0,0 +1,72 @@ + + +{#if hasSecurityPolicy} + +{/if} diff --git a/web-admin/src/features/projects/header/ProjectHeader.svelte b/web-admin/src/features/projects/header/ProjectHeader.svelte index 1f35ee907455..d0682b5a825e 100644 --- a/web-admin/src/features/projects/header/ProjectHeader.svelte +++ b/web-admin/src/features/projects/header/ProjectHeader.svelte @@ -54,6 +54,7 @@ import { useReports } from "../../scheduled-reports/selectors"; import SharePersonalFile from "web-admin/src/features/personal-files/SharePersonalFile.svelte"; import VisualizationsBreadcrumbDropdown from "./VisualizationsBreadcrumbDropdown.svelte"; + import EditSessionViewAs from "@rilldata/web-admin/features/edit-session/EditSessionViewAs.svelte"; export let organization: string; export let project: string; @@ -216,6 +217,7 @@
{#if editContext} + {#if $developerChat && !onEditDashboardPreview} {/if} From 503ec8b03083ee11f648c16731aeafa74145c635 Mon Sep 17 00:00:00 2001 From: Aditya Hegde Date: Thu, 27 Aug 2026 16:26:16 +0530 Subject: [PATCH 2/5] Use GetDeployment with `for:attributes` --- .../edit-session/EditSessionViewAs.svelte | 20 +++++++- .../edit-session/updateEditSessionDevJWT.ts | 51 +++++++++++++++++++ .../projects/header/ProjectHeader.svelte | 2 +- .../ViewAsButton.svelte | 16 ++++-- 4 files changed, 82 insertions(+), 7 deletions(-) create mode 100644 web-admin/src/features/edit-session/updateEditSessionDevJWT.ts diff --git a/web-admin/src/features/edit-session/EditSessionViewAs.svelte b/web-admin/src/features/edit-session/EditSessionViewAs.svelte index 269cb8e3745d..708b853cace3 100644 --- a/web-admin/src/features/edit-session/EditSessionViewAs.svelte +++ b/web-admin/src/features/edit-session/EditSessionViewAs.svelte @@ -8,9 +8,25 @@ import { useCanvas } from "@rilldata/web-common/features/canvas/selector.ts"; import ViewAsButton from "@rilldata/web-common/features/dashboards/granular-access-policies/ViewAsButton.svelte"; import { page } from "$app/state"; + import { createUpdateEditSessionDevJWT } from "@rilldata/web-admin/features/edit-session/updateEditSessionDevJWT.ts"; + import { createAdminServiceGetProject } from "@rilldata/web-admin/client"; + import { extractBranchFromPath } from "@rilldata/web-admin/features/branches/branch-utils.ts"; + + let { organization, project }: { organization: string; project: string } = + $props(); const runtimeClient = useRuntimeClient(); + let branch = extractBranchFromPath(page.url.pathname); + let projectQuery = $derived( + createAdminServiceGetProject( + organization, + project, + branch ? { branch } : undefined, + ), + ); + let deploymentId = $derived($projectQuery.data?.deployment?.id); + let onExplorePreview = $derived( !!page.route.id?.startsWith( "/[organization]/[project]/-/edit/(viz)/explore", @@ -65,8 +81,10 @@ $rillYamlPolicyCheck.data || referencedMetricsViewsHavePolicy, ); + + let devJTWUpdater = $derived(createUpdateEditSessionDevJWT(deploymentId)); {#if hasSecurityPolicy} - + {/if} diff --git a/web-admin/src/features/edit-session/updateEditSessionDevJWT.ts b/web-admin/src/features/edit-session/updateEditSessionDevJWT.ts new file mode 100644 index 000000000000..bbc28ef287f0 --- /dev/null +++ b/web-admin/src/features/edit-session/updateEditSessionDevJWT.ts @@ -0,0 +1,51 @@ +import { + selectedMockUserJWT, + selectedMockUserStore, +} from "@rilldata/web-common/features/dashboards/granular-access-policies/stores"; +import type { MockUser } from "@rilldata/web-common/features/dashboards/granular-access-policies/useMockUsers"; +import { + invalidateAllMetricsViews, + invalidateCanvasQueries, +} from "@rilldata/web-common/runtime-client/invalidation"; +import type { RuntimeClient } from "@rilldata/web-common/runtime-client/v2"; +import type { QueryClient } from "@tanstack/svelte-query"; +import { adminServiceGetDeployment } from "@rilldata/web-admin/client"; + +export function createUpdateEditSessionDevJWT(deploymentId: string) { + return async ( + queryClient: QueryClient, + client: RuntimeClient, + mockUser: MockUser | null, + ) => { + selectedMockUserStore.set(mockUser); + + if (mockUser === null) { + selectedMockUserJWT.set(null); + client.updateJwt(undefined, "user"); + } else { + try { + const { name, email, groups, admin, ...customAttributes } = mockUser; + + const { accessToken } = await adminServiceGetDeployment(deploymentId, { + attributes: { + email, + name: name || "Mock User", + admin: !!admin, + groups: groups || [], + ...customAttributes, + }, + }); + + if (!accessToken) throw new Error("No JWT returned"); + + selectedMockUserJWT.set(accessToken); + client.updateJwt(accessToken, "mock"); + } catch { + // no-op + } + } + + await invalidateAllMetricsViews(queryClient, client.instanceId); + return invalidateCanvasQueries(queryClient, client.instanceId); + }; +} diff --git a/web-admin/src/features/projects/header/ProjectHeader.svelte b/web-admin/src/features/projects/header/ProjectHeader.svelte index d0682b5a825e..b4ceca71eb71 100644 --- a/web-admin/src/features/projects/header/ProjectHeader.svelte +++ b/web-admin/src/features/projects/header/ProjectHeader.svelte @@ -217,7 +217,7 @@
{#if editContext} - + {#if $developerChat && !onEditDashboardPreview} {/if} diff --git a/web-common/src/features/dashboards/granular-access-policies/ViewAsButton.svelte b/web-common/src/features/dashboards/granular-access-policies/ViewAsButton.svelte index af690ed10e3d..04eb5cf1c8d6 100644 --- a/web-common/src/features/dashboards/granular-access-policies/ViewAsButton.svelte +++ b/web-common/src/features/dashboards/granular-access-policies/ViewAsButton.svelte @@ -16,12 +16,18 @@ import { getFileHref } from "@rilldata/web-common/layout/navigation/editor-routing"; import { escapeHtml } from "@rilldata/web-common/lib/i18n"; - let viewAsMenuOpen = false; - let open = false; + let { + devJTWUpdater = updateDevJWT, + }: { + devJTWUpdater?: typeof updateDevJWT; + } = $props(); + + let viewAsMenuOpen = $state(false); + let open = $state(false); const client = useRuntimeClient(); - $: mockUsers = useMockUsers(client); + let mockUsers = $derived(useMockUsers(client)); @@ -45,7 +51,7 @@ active={viewAsMenuOpen} removeTooltipText={m.dashboard_clear_view()} onRemove={() => { - updateDevJWT(queryClient, client, null); + devJTWUpdater(queryClient, client, null); }} >
@@ -68,7 +74,7 @@ {#each $mockUsers.data as user (user?.email)} { - updateDevJWT(queryClient, client, user); + devJTWUpdater(queryClient, client, user); }} class="flex gap-x-2 items-center" > From 238c3403f8cfce959b25403f0eb11c4cb54693ce Mon Sep 17 00:00:00 2001 From: Anshul Khandelwal <12948312+k-anshul@users.noreply.github.com> Date: Fri, 28 Aug 2026 12:20:17 +0530 Subject: [PATCH 3/5] restore jwt --- .../edit-session/EditSessionViewAs.svelte | 25 ++++++++----------- .../edit-session/updateEditSessionDevJWT.ts | 7 ++++-- .../projects/header/ProjectHeader.svelte | 9 ++++++- .../[project]/-/edit/+layout.svelte | 2 ++ 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/web-admin/src/features/edit-session/EditSessionViewAs.svelte b/web-admin/src/features/edit-session/EditSessionViewAs.svelte index 708b853cace3..35aacbca5f15 100644 --- a/web-admin/src/features/edit-session/EditSessionViewAs.svelte +++ b/web-admin/src/features/edit-session/EditSessionViewAs.svelte @@ -9,24 +9,17 @@ import ViewAsButton from "@rilldata/web-common/features/dashboards/granular-access-policies/ViewAsButton.svelte"; import { page } from "$app/state"; import { createUpdateEditSessionDevJWT } from "@rilldata/web-admin/features/edit-session/updateEditSessionDevJWT.ts"; - import { createAdminServiceGetProject } from "@rilldata/web-admin/client"; - import { extractBranchFromPath } from "@rilldata/web-admin/features/branches/branch-utils.ts"; - let { organization, project }: { organization: string; project: string } = - $props(); + let { + deploymentId, + editSessionJwt, + }: { + deploymentId: string; + editSessionJwt: string; + } = $props(); const runtimeClient = useRuntimeClient(); - let branch = extractBranchFromPath(page.url.pathname); - let projectQuery = $derived( - createAdminServiceGetProject( - organization, - project, - branch ? { branch } : undefined, - ), - ); - let deploymentId = $derived($projectQuery.data?.deployment?.id); - let onExplorePreview = $derived( !!page.route.id?.startsWith( "/[organization]/[project]/-/edit/(viz)/explore", @@ -82,7 +75,9 @@ referencedMetricsViewsHavePolicy, ); - let devJTWUpdater = $derived(createUpdateEditSessionDevJWT(deploymentId)); + let devJTWUpdater = $derived( + createUpdateEditSessionDevJWT(deploymentId, editSessionJwt), + ); {#if hasSecurityPolicy} diff --git a/web-admin/src/features/edit-session/updateEditSessionDevJWT.ts b/web-admin/src/features/edit-session/updateEditSessionDevJWT.ts index bbc28ef287f0..5eaef0326439 100644 --- a/web-admin/src/features/edit-session/updateEditSessionDevJWT.ts +++ b/web-admin/src/features/edit-session/updateEditSessionDevJWT.ts @@ -11,7 +11,10 @@ import type { RuntimeClient } from "@rilldata/web-common/runtime-client/v2"; import type { QueryClient } from "@tanstack/svelte-query"; import { adminServiceGetDeployment } from "@rilldata/web-admin/client"; -export function createUpdateEditSessionDevJWT(deploymentId: string) { +export function createUpdateEditSessionDevJWT( + deploymentId: string, + editSessionJwt: string, +) { return async ( queryClient: QueryClient, client: RuntimeClient, @@ -21,7 +24,7 @@ export function createUpdateEditSessionDevJWT(deploymentId: string) { if (mockUser === null) { selectedMockUserJWT.set(null); - client.updateJwt(undefined, "user"); + client.updateJwt(editSessionJwt, "user"); } else { try { const { name, email, groups, admin, ...customAttributes } = mockUser; diff --git a/web-admin/src/features/projects/header/ProjectHeader.svelte b/web-admin/src/features/projects/header/ProjectHeader.svelte index b4ceca71eb71..924670dcecb2 100644 --- a/web-admin/src/features/projects/header/ProjectHeader.svelte +++ b/web-admin/src/features/projects/header/ProjectHeader.svelte @@ -66,6 +66,8 @@ export let planDisplayName: string | undefined; export let organizationLogoUrl: string | undefined; export let editContext: boolean = false; + export let editSessionDeploymentId: string | undefined = undefined; + export let editSessionJwt: string | undefined = undefined; const user = createAdminServiceGetCurrentUser(); const runtimeClient = useRuntimeClient(); @@ -217,7 +219,12 @@
{#if editContext} - + {#if editSessionDeploymentId && editSessionJwt} + + {/if} {#if $developerChat && !onEditDashboardPreview} {/if} diff --git a/web-admin/src/routes/[organization]/[project]/-/edit/+layout.svelte b/web-admin/src/routes/[organization]/[project]/-/edit/+layout.svelte index b9ef1836869b..0fe886e06a8b 100644 --- a/web-admin/src/routes/[organization]/[project]/-/edit/+layout.svelte +++ b/web-admin/src/routes/[organization]/[project]/-/edit/+layout.svelte @@ -192,6 +192,8 @@ {planDisplayName} {organizationLogoUrl} editContext={true} + editSessionDeploymentId={deployment.id} + editSessionJwt={jwt} /> Date: Fri, 28 Aug 2026 15:37:05 +0530 Subject: [PATCH 4/5] Add implicit attrs like user.domain --- web-admin/src/features/edit-session/updateEditSessionDevJWT.ts | 2 ++ web-admin/src/features/projects/user-management/selectors.ts | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/web-admin/src/features/edit-session/updateEditSessionDevJWT.ts b/web-admin/src/features/edit-session/updateEditSessionDevJWT.ts index 5eaef0326439..d560048f4495 100644 --- a/web-admin/src/features/edit-session/updateEditSessionDevJWT.ts +++ b/web-admin/src/features/edit-session/updateEditSessionDevJWT.ts @@ -10,6 +10,7 @@ import { import type { RuntimeClient } from "@rilldata/web-common/runtime-client/v2"; import type { QueryClient } from "@tanstack/svelte-query"; import { adminServiceGetDeployment } from "@rilldata/web-admin/client"; +import { getDomain } from "@rilldata/web-admin/features/projects/user-management/selectors.ts"; export function createUpdateEditSessionDevJWT( deploymentId: string, @@ -32,6 +33,7 @@ export function createUpdateEditSessionDevJWT( const { accessToken } = await adminServiceGetDeployment(deploymentId, { attributes: { email, + domain: getDomain(email), name: name || "Mock User", admin: !!admin, groups: groups || [], diff --git a/web-admin/src/features/projects/user-management/selectors.ts b/web-admin/src/features/projects/user-management/selectors.ts index 7130b2bdbb10..cb3e90cba89a 100644 --- a/web-admin/src/features/projects/user-management/selectors.ts +++ b/web-admin/src/features/projects/user-management/selectors.ts @@ -27,7 +27,7 @@ export function emailIsPublic(email: string) { return RillPublicEmailDomains.includes(domain); } -function getDomain(email: string) { +export function getDomain(email: string) { const domainParts = email.split("@"); return domainParts.length ? domainParts[domainParts.length - 1] : ""; } From 19504602b64b996d505c959b10ba8154a44249cc Mon Sep 17 00:00:00 2001 From: Aditya Hegde Date: Fri, 28 Aug 2026 17:06:27 +0530 Subject: [PATCH 5/5] Fix lint --- web-admin/src/features/edit-session/updateEditSessionDevJWT.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web-admin/src/features/edit-session/updateEditSessionDevJWT.ts b/web-admin/src/features/edit-session/updateEditSessionDevJWT.ts index d560048f4495..62a92c675ef3 100644 --- a/web-admin/src/features/edit-session/updateEditSessionDevJWT.ts +++ b/web-admin/src/features/edit-session/updateEditSessionDevJWT.ts @@ -33,7 +33,7 @@ export function createUpdateEditSessionDevJWT( const { accessToken } = await adminServiceGetDeployment(deploymentId, { attributes: { email, - domain: getDomain(email), + ...(email ? { domain: getDomain(email) } : {}), name: name || "Mock User", admin: !!admin, groups: groups || [],