Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
2f3b3f6
POC
royendo Mar 4, 2026
acd8ed5
query cells, data explorer, + to add table instread of clcik
royendo Mar 5, 2026
40310b6
cache schema,
royendo Mar 5, 2026
8aa64c3
fix connector bug, simplify schema, edit messaging for nonlimits
royendo Mar 5, 2026
5713dca
prettier
royendo Mar 5, 2026
26631f1
fix schema cache
royendo Mar 5, 2026
91e844c
loical ux and code review
royendo Mar 5, 2026
90d2dd5
limit bug ui juimping to query editor, typo
royendo Mar 5, 2026
8484b2c
fix no rows returned vs run query to view rows
royendo Mar 5, 2026
7d5b4ea
fix a11y lint, distinguish hydrated vs executed empty results
royendo Mar 5, 2026
464f8dd
prettier
royendo Mar 5, 2026
88320e5
basic tests
royendo Mar 5, 2026
253be10
web code qual
royendo Mar 5, 2026
4d3f535
code qual
royendo Mar 5, 2026
6da3b23
local UX review
royendo Mar 5, 2026
6fc2d1c
code review
royendo Mar 5, 2026
43c16aa
9-13
royendo Mar 5, 2026
06150eb
revert behavior to insert at keyboard location instead of new cell
royendo Mar 5, 2026
049682d
Update QueryWorkspace.svelte
royendo Mar 5, 2026
ad2a625
prettier
royendo Mar 5, 2026
6bf63e1
fix ci/cd
royendo Mar 6, 2026
212bb21
Merge remote-tracking branch 'origin/main' into feat-sql-query-cloud
royendo Mar 6, 2026
c97fa64
instanceId to runtimeClient
royendo Mar 6, 2026
3a75960
no connectors listed
royendo Mar 6, 2026
e4db118
edit cell height, correct CTA when returning to Query
royendo Mar 6, 2026
5bbd399
editor and cell height adjustability
royendo Mar 6, 2026
138d610
local PR ux and code review changes
royendo Mar 6, 2026
4953ec6
cd/cd fix
royendo Mar 6, 2026
49bbd37
code fixes
royendo Mar 6, 2026
aaf8084
default off
royendo Mar 6, 2026
9cfe56a
fix go test
royendo Mar 6, 2026
499d096
review fixes
royendo Mar 6, 2026
27f6378
fix error UI and add download output data option
royendo Mar 18, 2026
67a411a
fix error icon
royendo Mar 18, 2026
1db0505
ai chat, to help with SQL syntax and hide schema button
royendo Mar 18, 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
3 changes: 3 additions & 0 deletions runtime/feature_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ var defaultFeatureFlags = map[string]string{
"deploy": "true",
// Controls if the developer agent tool is available.
"developer_agent": "true",
// Controls visibility of the SQL query editor in Rill Cloud.
// Set to "true" in rill.yaml to enable.
"query_editor": "false",
// Controls if the dashboard state is persisted when navigating to a different dashboard.
"sticky_dashboard_state": "false",
}
Expand Down
4 changes: 4 additions & 0 deletions runtime/feature_flags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ func Test_ResolveFeatureFlags(t *testing.T) {
"chatCharts": true,
"deploy": true,
"developerAgent": true,
"queryEditor": false,
"stickyDashboardState": false,
},
},
Expand All @@ -66,6 +67,7 @@ func Test_ResolveFeatureFlags(t *testing.T) {
"chatCharts": true,
"deploy": true,
"developerAgent": true,
"queryEditor": false,
"stickyDashboardState": false,
},
},
Expand All @@ -90,6 +92,7 @@ func Test_ResolveFeatureFlags(t *testing.T) {
"chatCharts": true,
"deploy": true,
"developerAgent": true,
"queryEditor": false,
"stickyDashboardState": false,
},
},
Expand All @@ -114,6 +117,7 @@ func Test_ResolveFeatureFlags(t *testing.T) {
"chatCharts": true,
"deploy": true,
"developerAgent": true,
"queryEditor": false,
"stickyDashboardState": false,
},
},
Expand Down
6 changes: 6 additions & 0 deletions web-admin/src/features/navigation/TopNavigationBar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
isOrganizationPage,
isProjectPage,
isPublicURLPage,
isQueryPage,
} from "./nav-utils";

export let createMagicAuthTokens: boolean;
Expand Down Expand Up @@ -77,6 +78,7 @@
$: onCanvasDashboardPage = isCanvasDashboardPage($page);
$: onPublicURLPage = isPublicURLPage($page);
$: onOrgPage = isOrganizationPage($page);
$: onQueryPage = isQueryPage($page);

// When "View As" is active, fetch deployment credentials for the mocked user.
// TanStack Query deduplicates by query key, so if the project layout already
Expand Down Expand Up @@ -352,6 +354,10 @@
<CanvasBookmarks {organization} {project} canvasName={dashboard} />
<ShareDashboardPopover createMagicAuthTokens={false} />
{/if}

{#if onQueryPage && $dashboardChat}
<ChatToggle />
{/if}
</RuntimeContextBridge>
{/key}
{/if}
Expand Down
4 changes: 4 additions & 0 deletions web-admin/src/features/navigation/nav-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ export function isCanvasDashboardPage(page: Page): boolean {
return page.route.id === "/[organization]/[project]/canvas/[dashboard]";
}

export function isQueryPage(page: Page): boolean {
return page.route.id === "/[organization]/[project]/-/query";
}

/**
* Returns true if the page is any kind of dashboard page (either a Metrics Explorer or a Custom Dashboard).
*/
Expand Down
4 changes: 2 additions & 2 deletions web-admin/src/features/projects/ProjectTabs.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
export let project: string;
export let pathname: string;

const { chat, reports, alerts } = featureFlags;
const { chat, queryEditor, reports, alerts } = featureFlags;

$: tabs = [
{
Expand All @@ -33,7 +33,7 @@
{
route: `/${organization}/${project}/-/query`,
label: "Query",
hasPermission: false,
hasPermission: $queryEditor,
},
{
route: `/${organization}/${project}/-/reports`,
Expand Down
23 changes: 23 additions & 0 deletions web-admin/src/routes/[organization]/[project]/-/query/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<script lang="ts">
import SidebarChat from "@rilldata/web-common/features/chat/layouts/sidebar/SidebarChat.svelte";
import { chatOpen } from "@rilldata/web-common/features/chat/layouts/sidebar/sidebar-store";
import { featureFlags } from "@rilldata/web-common/features/feature-flags";
import { createQueryChatConfig } from "@rilldata/web-common/features/query/query-chat-config";
import QueryWorkspace from "@rilldata/web-common/features/query/QueryWorkspace.svelte";
import { page } from "$app/stores";

const { dashboardChat } = featureFlags;
const chatConfig = createQueryChatConfig();

$: organization = $page.params.organization;
$: project = $page.params.project;
</script>

<div class="flex size-full overflow-hidden">
<div class="flex-1 overflow-hidden">
<QueryWorkspace projectId="{organization}/{project}" />
</div>
{#if $dashboardChat && $chatOpen}
<SidebarChat config={chatConfig} />
{/if}
</div>
34 changes: 33 additions & 1 deletion web-common/src/features/connectors/explorer/TableEntry.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@
$: expandedStore = store.getItem(connector, database, databaseSchema, table);
$: showSchema = $expandedStore;

const { allowContextMenu, allowNavigateToTable, allowShowSchema } = store;
const {
allowContextMenu,
allowNavigateToTable,
allowShowSchema,
onInsertTable,
} = store;

$: isModelingSupportedForConnector = useIsModelingSupportedForConnector(
client,
Expand Down Expand Up @@ -94,6 +99,18 @@
</span>
</svelte:element>

{#if onInsertTable}
<button
class="insert-button"
aria-label="Insert {table} into query"
title="Insert into query"
on:click|stopPropagation={() =>
onInsertTable(driver, connector, database, databaseSchema, table)}
>
+
</button>
{/if}

{#if allowContextMenu && (showGenerateMetricsAndDashboard || isModelingSupported || showGenerateModel)}
<DropdownMenu.Root bind:open={contextMenuOpen}>
<DropdownMenu.Trigger asChild let:builder>
Expand Down Expand Up @@ -161,4 +178,19 @@
.selected:hover {
@apply bg-gray-200;
}

.insert-button {
@apply hidden flex-none items-center justify-center;
@apply w-5 h-5 rounded text-xs font-semibold;
@apply text-fg-secondary bg-transparent;
}

.table-entry-header:hover .insert-button,
.open .insert-button {
@apply flex;
}

.insert-button:hover {
@apply text-fg-primary bg-gray-200;
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import Tooltip from "../../../components/tooltip/Tooltip.svelte";
import TooltipContent from "../../../components/tooltip/TooltipContent.svelte";
import { extractErrorMessage } from "../../../lib/errors";
import { prettyPrintType } from "../../query/query-utils";
import { useGetTable } from "../selectors";
import { useRuntimeClient } from "../../../runtime-client/v2";

Expand Down Expand Up @@ -31,12 +32,6 @@
$: error = $newTableQuery?.error;
$: isError = !!$newTableQuery?.error;
$: isLoading = $newTableQuery?.isLoading;

function prettyPrintType(type: string) {
// Remove CODE_ prefix and normalize unsupported types to just "UNKNOWN"
const normalized = type.replace(/^CODE_/, "");
return normalized.startsWith("UNKNOWN(") ? "UNKNOWN" : normalized;
}
</script>

<ul class="table-schema-list">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@ export class ConnectorExplorerStore {
table?: string,
) => void) = undefined;

/** Optional callback shown as a "+" button on table rows */
onInsertTable:
| undefined
| ((
driver: string,
connector: string,
database: string,
schema: string,
table: string,
) => void) = undefined;

constructor(
{
allowNavigateToTable = true,
Expand All @@ -32,19 +43,29 @@ export class ConnectorExplorerStore {
expandedItems = {},
localStorage = true,
} = {},
onToggleItem?: (
connector: string,
database?: string,
schema?: string,
table?: string,
) => void,
callbacks?: {
onToggleItem?: (
connector: string,
database?: string,
schema?: string,
table?: string,
) => void;
onInsertTable?: (
driver: string,
connector: string,
database: string,
schema: string,
table: string,
) => void;
},
) {
this.allowNavigateToTable = allowNavigateToTable;
this.allowContextMenu = allowContextMenu;
this.allowShowSchema = allowShowSchema;
this.allowSelectTable = allowSelectTable;

if (onToggleItem) this.onToggleItem = onToggleItem;
if (callbacks?.onToggleItem) this.onToggleItem = callbacks.onToggleItem;
if (callbacks?.onInsertTable) this.onInsertTable = callbacks.onInsertTable;

this.store = localStorage
? localStorageStore<ConnectorExplorerState>("connector-explorer-state", {
Expand Down Expand Up @@ -94,7 +115,7 @@ export class ConnectorExplorerStore {
showConnectors: state.showConnectors,
expandedItems: {},
},
onToggleItem ?? this.onToggleItem,
{ onToggleItem: onToggleItem ?? this.onToggleItem },
);
}

Expand Down
1 change: 1 addition & 0 deletions web-common/src/features/feature-flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class FeatureFlags {
dashboardChat = new FeatureFlag("user", false);
developerChat = new FeatureFlag("user", false);
deploy = new FeatureFlag("user", true);
queryEditor = new FeatureFlag("user", false);
stickyDashboardState = new FeatureFlag("user", false);

private flagsUnsub?: () => void;
Expand Down
50 changes: 50 additions & 0 deletions web-common/src/features/query/ConnectorSelector.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<script lang="ts">
import Select from "@rilldata/web-common/components/forms/Select.svelte";
import { createRuntimeServiceAnalyzeConnectors } from "@rilldata/web-common/runtime-client";
import { useRuntimeClient } from "../../runtime-client/v2";

export let id: string = "connector-selector";
export let value: string = "";
export let onChange: (connector: string) => void = () => {};

const runtimeClient = useRuntimeClient();

// Get all connectors that support SQL queries
$: connectorsQuery = createRuntimeServiceAnalyzeConnectors(
runtimeClient,
{},
{
query: {
select: (data) => {
if (!data?.connectors) return [];
return data.connectors
.filter(
(c) =>
c?.driver?.implementsOlap ||
c?.driver?.implementsSqlStore ||
c?.driver?.implementsWarehouse,
)
.sort((a, b) => (a?.name ?? "").localeCompare(b?.name ?? ""));
},
},
},
);

$: options = ($connectorsQuery.data ?? []).map((c) => ({
value: c.name as string,
label: c.name as string,
}));
</script>

<Select
{id}
ariaLabel="Select connector"
size="sm"
{value}
{options}
optionsLoading={$connectorsQuery.isLoading}
onChange={(newValue) => {
value = newValue;
onChange(newValue);
}}
/>
Loading