Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
3d27a16
feat: limit navbar on branch views
royendo May 1, 2026
c89f4f3
feat: hide Branches status tab and always show Cluster Size
royendo May 1, 2026
ad579d7
feat: only hide Branches status tab on branch views
royendo May 1, 2026
6cda11f
feat: redirect hidden sections to branch home on branch views
royendo May 1, 2026
4470427
feat: jump straight into edit mode from branch views
royendo May 1, 2026
60cb49e
prettier
royendo May 1, 2026
aba9440
feat: consolidate dashboard `Preview` into project navbar
royendo May 1, 2026
ecd238a
Show project Status tab to editors
royendo May 1, 2026
50ad577
Grant `ReadInstance` to editors via `read_prod_status`
royendo May 1, 2026
f353fd0
Merge navbar branch-view limits and keep Status visible on branch views
royendo May 1, 2026
fef1930
Show Status tab on branch views
royendo May 1, 2026
8e3affb
Hide branch pill for viewers
royendo May 1, 2026
c6507eb
Smart-route Preview toggle to the current dashboard
royendo May 1, 2026
fd9cd11
Hide navbar Preview/Edit toggle on `/explore` and `/canvas` routes
royendo May 1, 2026
092bc6e
Show "View as" in the local project preview navbar
royendo May 1, 2026
1c0c6a8
Widen project-preview ViewAs check to per-dashboard policies
royendo May 1, 2026
dbfc9ec
Hide AI chat toggle on the project preview pages
royendo May 1, 2026
0af0436
Reset chat and View as on mode toggle
royendo May 1, 2026
919dc14
Consolidate `View as` into a split Preview button
royendo May 1, 2026
2adec7e
Fix circular `@apply truncate` in `PreviewModeToggleButton`
royendo May 1, 2026
ab85806
Polish split Preview button: square corners, hover-only tint, auto-na…
royendo May 1, 2026
a90cb1e
Apply split-button polish and auto-nav on user pick
royendo May 1, 2026
744b2cb
Revert "feat: redirect hidden sections to branch home on branch views"
royendo May 1, 2026
9a14b67
Separate `Viewing as` pill from the Preview/Edit toggle
royendo May 1, 2026
208e4a3
feat: redirect hidden sections to branch home (section-scoped)
royendo May 1, 2026
b34638b
Merge remote-tracking branch 'origin/main' into worktree-feat-preview…
royendo May 1, 2026
3d9fb37
Reset chat + View as on explicit Preview/Edit click; decouple in RD
royendo May 1, 2026
3224ee8
docs: explain branch redirect scoping on each section loader
royendo May 1, 2026
04b4dc2
RD: split Preview button in Dev mode, standalone View as in Preview mode
royendo May 1, 2026
4934379
fix: drop unresolved `./$types` import from new section loaders
royendo May 1, 2026
a0da6dd
RD: always show View as in the navbar (drop policy gate)
royendo May 1, 2026
4ac79b8
Restyle `View as` default pill: bg-primary tint, user icon, no caret
royendo May 1, 2026
82c179f
Merge remote-tracking branch 'origin/worktree-feat-preview-pr-1-updat…
royendo May 1, 2026
4d4e294
Merge branch 'worktree-feat-preview-pr-3-consolidate-dashboard-previe…
royendo May 1, 2026
d58737b
Allow Status loader for editors on branch views
royendo May 1, 2026
a7d2939
Drop default background on `View as` pill; tint only on hover
royendo May 1, 2026
8605db3
prettier
royendo May 1, 2026
f260082
Add `/-/edit/dashboards`, `/-/edit/status`, `/-/edit/ai` routes
royendo May 1, 2026
47a6190
Match local-app look in `/-/edit/{dashboards,status,ai}`
royendo May 1, 2026
0466b12
Cloud: render dev-preview chrome on `/-/edit/{dashboards,status,ai}`
royendo May 1, 2026
a5b5ed9
Cloud editor: drop sidebar + chat on dev-preview sub-routes
royendo May 1, 2026
cb95dea
Add Dashboards/AI/Status tab nav to cloud dev-preview routes
royendo May 1, 2026
76bad6d
Cloud dev preview: gate View as on `manageDev` instead of `manageProj…
royendo May 1, 2026
14bf3dc
Surface View as on cloud non-edit preview + RD `--preview` lock
royendo May 1, 2026
3f4fffc
Remove Play/Pencil icons from Preview/Edit buttons
royendo May 1, 2026
5122a9a
Cloud dev preview: drop double border, fix `getHref` runtime crash
royendo May 1, 2026
71aa08c
Cloud dev preview: status side nav + resources sub-route
royendo May 1, 2026
3ae857c
Strip PR1/PR2 changes from this branch
royendo May 1, 2026
af1cd8a
RD: project name + logo target `/dashboards` on viz routes
royendo May 1, 2026
b9effbf
Cloud: reset chat + View as on Preview/Edit swap; add Tables tab
royendo May 1, 2026
f8fc49b
Consolidate dashboards listing page into a shared web-common component
royendo May 1, 2026
66a6e75
Consolidate full-page AI chat into a shared web-common component
royendo May 1, 2026
0ee9bee
Consolidate Status layout + Overview page into shared web-common comp…
royendo May 1, 2026
1effc6d
Consolidate Status > Resources page into a shared web-common component
royendo May 1, 2026
1d82c08
Consolidate Status > Tables page into a shared web-common component
royendo May 1, 2026
08b2f68
Consolidate preview-mode tab nav into a shared web-common component
royendo May 1, 2026
5ca50bb
Cloud dev preview: use mock_users-based View as (match local)
royendo May 1, 2026
048bb52
Revert mock-user View as in cloud dev preview
royendo May 1, 2026
caf41c5
Cloud editor: reset chat + View as on dev-preview → edit transition
royendo May 1, 2026
005ffa9
Cloud editor: honor `viewAsUserStore` in the dev runtime
royendo May 1, 2026
c0997f8
Cloud editor View as: pass authContext=mock so queries invalidate
royendo May 1, 2026
048863f
Revert "Cloud editor View as: pass authContext=mock so queries invali…
royendo May 1, 2026
a2f3a36
Revert "Cloud editor: honor `viewAsUserStore` in the dev runtime"
royendo May 1, 2026
e5a8ae2
Reset View as + chat on platform navigation
royendo May 1, 2026
fca28aa
Preserve View as across user-pick navigation; allowlist new edit routes
royendo May 1, 2026
37a8006
Drop unused `reconcileError` from `MetricsWorkspace`
royendo May 1, 2026
5f74091
Drop unused `showProjectViewAs` + its deps from `ApplicationHeader`
royendo May 1, 2026
351def5
Add Developer/Preview pill to cloud editor header
royendo May 1, 2026
363e167
Add Publish (Merge to production) button to cloud dev-preview chrome
royendo May 1, 2026
7dd6d5a
Revert "Add Publish (Merge to production) button to cloud dev-preview…
royendo May 1, 2026
9588300
Revert "Add Developer/Preview pill to cloud editor header"
royendo May 1, 2026
3881fde
Treat `/-/edit/{explore,canvas}/[name]` as full-screen preview
royendo May 1, 2026
948a9f8
Render `ProjectTabs` instead of `PreviewModeNav` on dev-preview
royendo May 1, 2026
126fab9
Route Preview button and dashboard rows into the dev-preview chrome
royendo May 1, 2026
d6cc20d
Render `EditActions` on the dev-preview right cluster
royendo May 1, 2026
4356353
Surface dashboard breadcrumb on `/-/edit/{explore,canvas}/[name]`
royendo May 1, 2026
f8e4731
Keep nav inside `/-/edit/...` from the dev-preview chrome
royendo May 1, 2026
5fac16d
Hide Home tab in `ProjectTabs` editMode
royendo May 1, 2026
6b3e077
Pin breadcrumb resource swaps to `/-/edit/...` in dev-preview
royendo May 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions scripts/check-edit-route-parity.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,18 @@ const ADMIN_ONLY_ALLOWLIST = [
"/welcome/+page.svelte",
"/welcome/add-data/+page.svelte",
"/welcome/add-data/+page.ts",

// Dev-preview routes inside the cloud editor. Locally these surfaces live
// at the top level (`/dashboards`, `/status*`, `/ai`) since the local app
// toggles into Preview mode via the navbar instead of nesting it under an
// editor URL. Each editor page thinly wraps the same shared
// `web-common/features/preview-mode/*` component the local routes use.
"/dashboards/+page.svelte",
"/status/+layout.svelte",
"/status/+page.svelte",
"/status/resources/+page.svelte",
"/status/tables/+page.svelte",
"/ai/+page.svelte",
];

function walkRoutes(absRoot) {
Expand Down
25 changes: 0 additions & 25 deletions web-admin/src/features/authentication/AvatarButton.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
createAdminServiceGetCurrentUser,
type V1ProjectPermissions,
} from "../../client";
import ViewAsUserPopover from "../view-as-user/ViewAsUserPopover.svelte";
import ThemeToggle from "@rilldata/web-common/features/themes/ThemeToggle.svelte";

export let projectPermissions: V1ProjectPermissions | undefined = undefined;
Expand All @@ -35,7 +34,6 @@

let imgContainer: HTMLElement;
let primaryMenuOpen = false;
let subMenuOpen = false;

onMount(() => {
const photoUrl = $user.data?.user?.photoUrl;
Expand Down Expand Up @@ -90,29 +88,6 @@
</DropdownMenu.Trigger>
<DropdownMenu.Content align="end">
{#if params.organization && params.project && projectPermissions}
{#if projectPermissions.manageProject}
<DropdownMenu.Sub bind:open={subMenuOpen}>
<DropdownMenu.SubTrigger
onclick={() => {
subMenuOpen = !subMenuOpen;
}}
>
View as
</DropdownMenu.SubTrigger>
<DropdownMenu.SubContent
class="flex flex-col min-w-[150px] max-w-[300px]"
>
<ViewAsUserPopover
organization={params.organization}
project={params.project}
onSelectUser={() => {
subMenuOpen = false;
primaryMenuOpen = false;
}}
/>
</DropdownMenu.SubContent>
</DropdownMenu.Sub>
{/if}
{#if params.dashboard}
<DropdownMenu.Item
href={`/${params.organization}/${params.project}/-/alerts`}
Expand Down
18 changes: 18 additions & 0 deletions web-admin/src/features/branches/deployment-utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,5 +261,23 @@ describe("deployment-utils", () => {
const result = await call("/rilldata/openrtb");
expect(result).toBeUndefined();
});

it("does not redirect away from the deploying page", async () => {
// Conditions that would otherwise trigger a redirect:
// no prod deployment, an active editable dev deployment, no @branch in URL.
listDeploymentsMock.mockResolvedValue({
deployments: [
makeDeployment({
environment: "dev",
editable: true,
branch: "edit-branch",
status: V1DeploymentStatus.DEPLOYMENT_STATUS_RUNNING,
}),
],
});

const result = await call("/rilldata/openrtb/-/deploying");
expect(result).toBeUndefined();
});
});
});
4 changes: 4 additions & 0 deletions web-admin/src/features/branches/deployment-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ export async function maybeRedirectToEditableDeployment(
project: string,
url: URL,
) {
// The deploying page is a transitional progress screen for a prod deployment
// that is still provisioning. Do not redirect away from it.
if (url.pathname.endsWith("/-/deploying")) return;

const deploymentsResp = await queryClient.fetchQuery({
queryKey: getAdminServiceListDeploymentsQueryKey(organization, project, {}),
queryFn: () => adminServiceListDeployments(organization, project, {}),
Expand Down
38 changes: 35 additions & 3 deletions web-admin/src/features/edit-session/EditActions.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,52 @@
import { Button } from "@rilldata/web-common/components/button";
import Tooltip from "@rilldata/web-common/components/tooltip/Tooltip.svelte";
import TooltipContent from "@rilldata/web-common/components/tooltip/TooltipContent.svelte";
import { LogOut } from "lucide-svelte";
import { extractErrorMessage } from "@rilldata/web-common/lib/errors";
import { createRuntimeServiceGitStatus } from "@rilldata/web-common/runtime-client";
import { useRuntimeClient } from "@rilldata/web-common/runtime-client/v2";
import { GitBranch, LogOut } from "lucide-svelte";
import CommitPopover from "./CommitPopover.svelte";
import MergePopover from "./MergePopover.svelte";
import PublishPopover from "./PublishPopover.svelte";

export let organization: string;
export let project: string;
export let branch: string;
export let primaryBranch: string | undefined = undefined;

const client = useRuntimeClient();
const gitStatusQuery = createRuntimeServiceGitStatus(client, {});

$: closeHref = `/${organization}/${project}${branchPathPrefix(branch)}`;
$: managedGit = $gitStatusQuery.data?.managedGit;
$: gitStatusLoaded = $gitStatusQuery.data !== undefined;
// Show the parent-level error UI only when GitStatus has never loaded.
// After a successful load, TanStack keeps `data` populated through transient
// refetch errors, so the popovers stay mounted and the user keeps the toolbar.
$: gitStatusErrorMessage =
!gitStatusLoaded && $gitStatusQuery.isError
? extractErrorMessage($gitStatusQuery.error)
: "";
</script>

<CommitPopover />
<MergePopover {organization} {project} {primaryBranch} />
{#if gitStatusLoaded}
{#if managedGit}
<PublishPopover {organization} {project} {primaryBranch} />
{:else}
<CommitPopover />
<MergePopover {organization} {project} {primaryBranch} />
{/if}
{:else if gitStatusErrorMessage}
<Tooltip distance={8}>
<Button type="primary" disabled>
<GitBranch size="14" />
Git unavailable
</Button>
<TooltipContent slot="tooltip-content" maxWidth="220px">
<span class="text-xs">{gitStatusErrorMessage}</span>
</TooltipContent>
</Tooltip>
{/if}

<Tooltip distance={8}>
<Button type="secondary" href={closeHref}>
Expand Down
73 changes: 24 additions & 49 deletions web-admin/src/features/edit-session/MergePopover.svelte
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
<script lang="ts">
import { goto } from "$app/navigation";
import {
createAdminServiceDeleteDeployment,
createAdminServiceListDeployments,
} from "@rilldata/web-admin/client";
import { getRpcErrorMessage } from "@rilldata/web-admin/components/errors/error-utils";
import { optimisticallyRemoveDeployment } from "@rilldata/web-admin/features/branches/branch-actions";
import { requestSkipBranchInjection } from "@rilldata/web-admin/features/branches/branch-utils";
import { Button } from "@rilldata/web-common/components/button";
import * as Popover from "@rilldata/web-common/components/popover";
import Tooltip from "@rilldata/web-common/components/tooltip/Tooltip.svelte";
import TooltipContent from "@rilldata/web-common/components/tooltip/TooltipContent.svelte";
import { getGitUrlFromRemote } from "@rilldata/web-common/features/project/deploy/github-utils";
import { extractErrorMessage } from "@rilldata/web-common/lib/errors";
import { queryClient } from "@rilldata/web-common/lib/svelte-query/globalQueryClient";
import {
createRuntimeServiceGitMergeToBranchMutation,
createRuntimeServiceGitStatus,
type RpcStatus,
getRuntimeServiceGitStatusQueryKey,
} from "@rilldata/web-common/runtime-client";
import { useRuntimeClient } from "@rilldata/web-common/runtime-client/v2";
import { ExternalLink, GitPullRequest } from "lucide-svelte";
Expand All @@ -31,21 +27,8 @@
const client = useRuntimeClient();
const gitMergeMutation = createRuntimeServiceGitMergeToBranchMutation(client);
const gitStatusQuery = createRuntimeServiceGitStatus(client, {});
const deploymentsQuery = createAdminServiceListDeployments(
organization,
project,
{},
);
const deleteDeploymentMutation = createAdminServiceDeleteDeployment();

$: currentBranch = $gitStatusQuery.data?.branch ?? "";
$: gitStatusErrorMessage = $gitStatusQuery.isError
? (getRpcErrorMessage($gitStatusQuery.error as RpcStatus) ??
"Couldn't load branch info")
: "";
$: devDeploymentId = $deploymentsQuery.data?.deployments?.find(
(d) => d.runtimeInstanceId === client.instanceId,
)?.id;
$: branchUrl =
$gitStatusQuery.data?.githubUrl && currentBranch
? `${getGitUrlFromRemote($gitStatusQuery.data.githubUrl)}/tree/${encodeURIComponent(currentBranch)}`
Expand All @@ -68,29 +51,27 @@
branch: primaryBranch,
force: false,
});
// gitStatus tracks currentBranch; refresh so subscribers see the merge.
await queryClient.invalidateQueries({
queryKey: getRuntimeServiceGitStatusQueryKey(client.instanceId, {}),
});
} catch (err) {
errorMessage = getRpcErrorMessage(err as RpcStatus) ?? "Failed to merge";
errorMessage = extractErrorMessage(err) || "Failed to merge";
isMerging = false;
return;
}

// First, leave the edit page. Deleting the deployment while the page is still
// mounted would 404 its deployment queries and flash an error. The skip call
// opts out of the project layout's `beforeNavigate` branch injection so we
// actually land on the production project home, not back on the dev branch.
requestSkipBranchInjection();
await goto(`/${organization}/${project}`);
isMerging = false;
open = false;

// Second, delete the dev deployment. On success, drop it from the
// ListDeployments cache so the BranchSelector on the destination page
// doesn't show the now-deleted branch.
// Note that the browser may cancel this request on page tear-down, so a better approach may be to
// hand off the deployment id via sessionStorage and fire the delete from the destination.
if (devDeploymentId) {
const id = devDeploymentId;
$deleteDeploymentMutation.mutate({ deploymentId: id });
void optimisticallyRemoveDeployment(organization, project, id);
}
// Defer goto to the next task. Calling it synchronously after a mutation
// races with TanStack's invalidation/refetch teardown, whose abort listeners
// can throw and silently cancel the navigation. Same workaround as
// welcome/organization/+page.svelte after createOrg.
setTimeout(() => {
requestSkipBranchInjection();
void goto(`/${organization}/${project}`);
});
}
</script>

Expand All @@ -106,16 +87,12 @@
</Popover.Trigger>
<Popover.Content align="end" class="!w-[320px]">
<div class="flex flex-col gap-y-3">
{#if gitStatusErrorMessage}
<p class="text-xs text-red-600">{gitStatusErrorMessage}</p>
{:else}
<p class="text-xs text-fg-secondary">
Merging pushes changes from
<span class="font-semibold text-fg-primary">"{currentBranch}"</span>
to production and returns you to the project home. Viewers will see updates
as the project reconciles.
</p>
{/if}
<p class="text-xs text-fg-secondary">
Merging pushes changes from
<span class="font-semibold text-fg-primary">"{currentBranch}"</span>
to production and returns you to the project home. Viewers will see updates
as the project reconciles.
</p>
{#if branchUrl}
<a
class="github-link"
Expand Down Expand Up @@ -147,8 +124,6 @@
<span class="text-xs">
{#if alreadyOnPrimary}
Already on production
{:else if gitStatusErrorMessage}
{gitStatusErrorMessage}
{:else if !primaryBranch || !currentBranch}
Loading project...
{:else}
Expand Down
Loading
Loading