diff --git a/web-admin/src/features/dashboards/share/ShareDashboardPopover.svelte b/web-admin/src/features/dashboards/share/ShareDashboardPopover.svelte index 520d5ccb97b..54fd4cbcd08 100644 --- a/web-admin/src/features/dashboards/share/ShareDashboardPopover.svelte +++ b/web-admin/src/features/dashboards/share/ShareDashboardPopover.svelte @@ -16,11 +16,11 @@ } from "@rilldata/web-common/components/tabs"; import Tooltip from "@rilldata/web-common/components/tooltip/Tooltip.svelte"; import TooltipContent from "@rilldata/web-common/components/tooltip/TooltipContent.svelte"; - import { featureFlags } from "@rilldata/web-common/features/feature-flags"; + import { useFeatureFlags } from "@rilldata/web-common/features/feature-flags"; export let createMagicAuthTokens: boolean; - const { hidePublicUrl } = featureFlags; + const { hidePublicUrl } = useFeatureFlags(); let isOpen = false; let copied = false; diff --git a/web-admin/src/features/embeds/EmbedHeader.svelte b/web-admin/src/features/embeds/EmbedHeader.svelte index 65a1ba35360..0cc9072fe50 100644 --- a/web-admin/src/features/embeds/EmbedHeader.svelte +++ b/web-admin/src/features/embeds/EmbedHeader.svelte @@ -3,7 +3,7 @@ import BreadcrumbItem from "@rilldata/web-common/components/navigation/breadcrumbs/BreadcrumbItem.svelte"; import TwoTieredBreadcrumbItem from "@rilldata/web-common/components/navigation/breadcrumbs/TwoTieredBreadcrumbItem.svelte"; import { useValidDashboards } from "@rilldata/web-common/features/dashboards/selectors"; - import { featureFlags } from "@rilldata/web-common/features/feature-flags"; + import { useFeatureFlags } from "@rilldata/web-common/features/feature-flags"; import LastRefreshedDate from "@rilldata/web-admin/features/dashboards/listing/LastRefreshedDate.svelte"; import ChatToggle from "@rilldata/web-common/features/chat/layouts/sidebar/ChatToggle.svelte"; import type { @@ -16,7 +16,7 @@ export let navigationEnabled: boolean = true; const runtimeClient = useRuntimeClient(); - const { twoTieredNavigation, dashboardChat } = featureFlags; + const { twoTieredNavigation, dashboardChat } = useFeatureFlags(); $: onProjectPage = !activeResource; $: showDashboardChat = $dashboardChat && !onProjectPage; diff --git a/web-admin/src/features/embeds/EmbedShell.svelte b/web-admin/src/features/embeds/EmbedShell.svelte new file mode 100644 index 00000000000..cf2b74b0dca --- /dev/null +++ b/web-admin/src/features/embeds/EmbedShell.svelte @@ -0,0 +1,46 @@ + + +{#if showTopBar} + +
+ +
+
+{/if} + +
+
+ +
+ {#if showDashboardChat && correctedKindForChat} + + {/if} +
diff --git a/web-admin/src/features/projects/ProjectHeader.svelte b/web-admin/src/features/projects/ProjectHeader.svelte index f15aaa8a73d..e198383d81d 100644 --- a/web-admin/src/features/projects/ProjectHeader.svelte +++ b/web-admin/src/features/projects/ProjectHeader.svelte @@ -15,7 +15,7 @@ import StateManagersProvider from "@rilldata/web-common/features/dashboards/state-managers/StateManagersProvider.svelte"; import { ResourceKind } from "@rilldata/web-common/features/entity-management/resource-selectors"; import { useExplore } from "@rilldata/web-common/features/explores/selectors"; - import { featureFlags } from "@rilldata/web-common/features/feature-flags"; + import { useFeatureFlags } from "@rilldata/web-common/features/feature-flags"; import Header from "@rilldata/web-common/layout/header/Header.svelte"; import HeaderLogo from "@rilldata/web-common/layout/header/HeaderLogo.svelte"; import { useRuntimeClient } from "@rilldata/web-common/runtime-client/v2"; @@ -62,7 +62,7 @@ dimensionSearch, dashboardChat, stickyDashboardState, - } = featureFlags; + } = useFeatureFlags(); $: ({ params: { dashboard, alert, report }, diff --git a/web-admin/src/features/projects/ProjectTabs.svelte b/web-admin/src/features/projects/ProjectTabs.svelte index 0c951097c68..834ebb34ad8 100644 --- a/web-admin/src/features/projects/ProjectTabs.svelte +++ b/web-admin/src/features/projects/ProjectTabs.svelte @@ -5,7 +5,7 @@ } from "@rilldata/web-admin//components/nav/Tab.svelte"; import Tab from "@rilldata/web-admin/components/nav/Tab.svelte"; import { removeBranchFromPath } from "@rilldata/web-admin/features/branches/branch-utils"; - import { featureFlags } from "@rilldata/web-common/features/feature-flags"; + import { useFeatureFlags } from "@rilldata/web-common/features/feature-flags"; import { type V1ProjectPermissions } from "../../client"; export let projectPermissions: V1ProjectPermissions; @@ -14,7 +14,7 @@ export let pathname: string; export let branchPrefix: string = ""; - const { chat, reports, alerts } = featureFlags; + const { chat, reports, alerts } = useFeatureFlags(); $: tabs = [ { diff --git a/web-admin/src/routes/+layout.svelte b/web-admin/src/routes/+layout.svelte index d771155b618..d00182d7751 100644 --- a/web-admin/src/routes/+layout.svelte +++ b/web-admin/src/routes/+layout.svelte @@ -16,7 +16,10 @@ import { initCloudMetrics } from "@rilldata/web-admin/features/telemetry/initCloudMetrics"; import BannerCenter from "@rilldata/web-common/components/banner/BannerCenter.svelte"; import NotificationCenter from "@rilldata/web-common/components/notifications/NotificationCenter.svelte"; - import { featureFlags } from "@rilldata/web-common/features/feature-flags"; + import { + adminServer, + readOnly, + } from "@rilldata/web-common/features/app-flags"; import { initPylonWidget } from "@rilldata/web-common/features/help/initPylonWidget"; import { isEmbedPage } from "@rilldata/web-common/layout/navigation/navigation-utils.ts"; import { eventBus } from "@rilldata/web-common/lib/event-bus/event-bus.ts"; @@ -74,7 +77,8 @@ // The admin server enables some dashboard features like scheduled reports and alerts // Set read-only mode so that the user can't edit the dashboard - featureFlags.set(true, "adminServer", "readOnly"); + adminServer.set(true); + readOnly.set(true); let removeJavascriptListeners: () => void; diff --git a/web-admin/src/routes/-/embed/+layout.svelte b/web-admin/src/routes/-/embed/+layout.svelte index ad384907837..4ce3e1b0a5a 100644 --- a/web-admin/src/routes/-/embed/+layout.svelte +++ b/web-admin/src/routes/-/embed/+layout.svelte @@ -5,15 +5,12 @@ getDashboardFromEmbedRoute, isDifferentDashboard, } from "@rilldata/web-admin/features/embeds/embed-route-utils.ts"; + import EmbedShell from "@rilldata/web-admin/features/embeds/EmbedShell.svelte"; import initEmbedPublicAPI from "@rilldata/web-admin/features/embeds/init-embed-public-api.ts"; - import EmbedHeader from "@rilldata/web-admin/features/embeds/EmbedHeader.svelte"; import ErrorPage from "@rilldata/web-common/components/ErrorPage.svelte"; import { VegaLiteTooltipHandler } from "@rilldata/web-common/components/vega/vega-tooltip.ts"; import { ResourceKind } from "@rilldata/web-common/features/entity-management/resource-selectors.ts"; - import { featureFlags } from "@rilldata/web-common/features/feature-flags"; - import DashboardChat from "@rilldata/web-common/features/chat/DashboardChat.svelte"; - import ThemeProvider from "@rilldata/web-common/features/dashboards/ThemeProvider.svelte"; - import { activeDashboardTheme } from "@rilldata/web-common/features/themes/active-dashboard-theme"; + import { adminServer } from "@rilldata/web-common/features/app-flags"; import { createIframeRPCHandler, emitNotification, @@ -32,11 +29,9 @@ accessToken, } = data; - const { dashboardChat } = featureFlags; - // Embedded dashboards communicate directly with the project runtime and do not communicate with the admin server. // One by-product of this is that they have no access to control plane features like alerts, bookmarks, and scheduled reports. - featureFlags.set(false, "adminServer"); + adminServer.set(false); // Extract active resource info from current route // Falls back to Canvas if route doesn't match a dashboard pattern (e.g., project page) @@ -50,18 +45,6 @@ $: onProjectPage = !activeResource; - $: showDashboardChat = $dashboardChat && !onProjectPage; - // Resource kind can be metrics view in some cases. But internally to render it will have to have an equivalent explore. - $: correctedKindForChat = - activeResource?.kind === ResourceKind.MetricsView - ? ResourceKind.Explore - : (activeResource?.kind as - | ResourceKind.Explore - | ResourceKind.Canvas - | undefined); - - $: showTopBar = navigationEnabled || showDashboardChat; - // Suppress browser back/forward beforeNavigate((nav) => { if (!navigationEnabled) { @@ -135,24 +118,8 @@ jwt={accessToken} authContext="embed" > - {#if showTopBar} - -
- -
-
- {/if} - -
-
- -
- {#if showDashboardChat && correctedKindForChat} - - {/if} -
+ + + {/if} diff --git a/web-admin/src/routes/[organization]/[project]/+page.svelte b/web-admin/src/routes/[organization]/[project]/+page.svelte index 14fb72ceb2d..2f0d51411ed 100644 --- a/web-admin/src/routes/[organization]/[project]/+page.svelte +++ b/web-admin/src/routes/[organization]/[project]/+page.svelte @@ -4,11 +4,11 @@ import DashboardsTable from "@rilldata/web-admin/features/dashboards/listing/DashboardsTable.svelte"; import InlineChat from "@rilldata/web-common/features/chat/layouts/inline/InlineChat.svelte"; import DelayedContent from "@rilldata/web-common/features/entity-management/DelayedContent.svelte"; - import { featureFlags } from "@rilldata/web-common/features/feature-flags"; + import { useFeatureFlags } from "@rilldata/web-common/features/feature-flags"; import { createRuntimeServiceGetInstance } from "@rilldata/web-common/runtime-client"; import { useRuntimeClient } from "@rilldata/web-common/runtime-client/v2"; - const { chat } = featureFlags; + const { chat } = useFeatureFlags(); const runtimeClient = useRuntimeClient(); diff --git a/web-common/src/features/add-data/manager/GenerateDashboardStatus.svelte b/web-common/src/features/add-data/manager/GenerateDashboardStatus.svelte index 5cd29472097..5716707bc18 100644 --- a/web-common/src/features/add-data/manager/GenerateDashboardStatus.svelte +++ b/web-common/src/features/add-data/manager/GenerateDashboardStatus.svelte @@ -18,6 +18,7 @@ } from "@rilldata/web-common/features/add-data/manager/steps/import.ts"; import { onMount } from "svelte"; import { useRuntimeClient } from "@rilldata/web-common/runtime-client/v2"; + import { useFeatureFlags } from "@rilldata/web-common/features/feature-flags"; import { addLeadingSlash } from "@rilldata/web-common/features/entity-management/entity-mappers.ts"; import { queryClient } from "@rilldata/web-common/lib/svelte-query/globalQueryClient.ts"; import { @@ -35,6 +36,7 @@ export let onDone: () => void; const runtimeClient = useRuntimeClient(); + const { ai } = useFeatureFlags(); const initialAddDataStep = { ...importAddDataStep }; const StepLabels = [ @@ -98,6 +100,7 @@ } } }, + $ai, ); onDone(); return goto(currentFileRoute); diff --git a/web-common/src/features/add-data/manager/ImportDataStatus.svelte b/web-common/src/features/add-data/manager/ImportDataStatus.svelte index 7fb771b1184..8e4b812dd61 100644 --- a/web-common/src/features/add-data/manager/ImportDataStatus.svelte +++ b/web-common/src/features/add-data/manager/ImportDataStatus.svelte @@ -19,7 +19,7 @@ } from "@rilldata/web-common/features/metrics-views/ai-generation/generateMetricsView.ts"; import { MetricsEventSpace } from "@rilldata/web-common/metrics/service/MetricsTypes.ts"; import { BehaviourEventMedium } from "@rilldata/web-common/metrics/service/BehaviourEventTypes.ts"; - import { featureFlags } from "@rilldata/web-common/features/feature-flags.ts"; + import { useFeatureFlags } from "@rilldata/web-common/features/feature-flags"; import { addLeadingSlash } from "@rilldata/web-common/features/entity-management/entity-mappers.ts"; import { getFileHref, @@ -34,7 +34,7 @@ export let importAddDataStep: ImportAddDataStep; export let onDone: () => void; - const { ai, developerChat } = featureFlags; + const { ai, developerChat } = useFeatureFlags(); const runtimeClient = useRuntimeClient(); @@ -55,6 +55,7 @@ sourceName, BehaviourEventMedium.Button, MetricsEventSpace.Modal, + $ai, ); async function runImport() { @@ -73,6 +74,7 @@ } } }, + $ai, ); } catch (e) { error = e?.response?.data?.message ?? e?.message ?? "Unknown error"; @@ -89,6 +91,7 @@ "", "", sourceName, + $ai, ); } else { await createDashboardFromTable(); diff --git a/web-common/src/features/add-data/manager/steps/import.ts b/web-common/src/features/add-data/manager/steps/import.ts index 81e56c6306d..f5e9301f62f 100644 --- a/web-common/src/features/add-data/manager/steps/import.ts +++ b/web-common/src/features/add-data/manager/steps/import.ts @@ -23,13 +23,11 @@ import { import { ResourceKind } from "@rilldata/web-common/features/entity-management/resource-selectors.ts"; import { fileArtifacts } from "@rilldata/web-common/features/entity-management/file-artifacts.ts"; import { queryClient } from "@rilldata/web-common/lib/svelte-query/globalQueryClient.ts"; -import { get } from "svelte/store"; import { RuntimeClient } from "@rilldata/web-common/runtime-client/v2"; import { compileSourceYAML, inferModelNameFromSQL, } from "@rilldata/web-common/features/sources/sourceUtils.ts"; -import { featureFlags } from "@rilldata/web-common/features/feature-flags.ts"; import { generateBlobForNewResourceFile } from "@rilldata/web-common/features/entity-management/add/new-files.ts"; import { getName } from "@rilldata/web-common/features/entity-management/name-utils.ts"; import type { QueryClient } from "@tanstack/svelte-query"; @@ -46,6 +44,7 @@ export async function runImportSteps( step: ImportDataStep, currentFilePath: string | undefined, ) => void, + isAiEnabled: boolean, ) { for (const step of addDataStep.config.importSteps) { fireImportStepEvent(addDataConfig, addDataStep, step); @@ -56,13 +55,21 @@ export async function runImportSteps( break; case ImportDataStep.CreateMetricsView: onProgress(step, addDataStep.config.importTo.metricsViewPath); - await runCreateMetricsViewStep(runtimeClient, addDataStep.config); + await runCreateMetricsViewStep( + runtimeClient, + addDataStep.config, + isAiEnabled, + ); break; case ImportDataStep.CreateDashboard: onProgress(step, addDataStep.config.importTo.explorePath); await runCreateExploreStep(runtimeClient, addDataStep.config); onProgress(step, addDataStep.config.importTo.canvasPath); - await runCreateCanvasStep(runtimeClient, addDataStep.config); + await runCreateCanvasStep( + runtimeClient, + addDataStep.config, + isAiEnabled, + ); break; } } @@ -286,6 +293,7 @@ async function runCreateModelStep( async function runCreateMetricsViewStep( runtimeClient: RuntimeClient, config: ImportStepConfig, + isAiEnabled: boolean, ) { // Validate metrics view name and path are generated upstream const importToConfig = config.importTo; @@ -330,7 +338,7 @@ async function runCreateMetricsViewStep( database, databaseSchema, path: importToConfig.metricsViewPath, - useAi: get(featureFlags.ai), + useAi: isAiEnabled, }); // Wait for the metrics view to successfully reconcile await waitForResourceReconciliation( @@ -385,6 +393,7 @@ async function runCreateExploreStep( async function runCreateCanvasStep( runtimeClient: RuntimeClient, config: ImportStepConfig, + isAiEnabled: boolean, ) { // Validate canvas name and path are generated upstream const importToConfig = config.importTo; @@ -395,7 +404,7 @@ async function runCreateCanvasStep( await runtimeServiceGenerateCanvasFile(runtimeClient, { metricsViewName: importToConfig.metricsViewName, path: importToConfig.canvasPath, - useAi: get(featureFlags.ai), + useAi: isAiEnabled, }); // Wait for canvas to reconcile diff --git a/web-common/src/features/app-flags.ts b/web-common/src/features/app-flags.ts new file mode 100644 index 00000000000..197661ec52c --- /dev/null +++ b/web-common/src/features/app-flags.ts @@ -0,0 +1,14 @@ +import { writable } from "svelte/store"; + +// ── App-wide flags ───────────────────────────────────────────────────── +// +// These flags depend on which frontend app is running (web-admin, web-local, +// or an embed iframe), not on which Rill runtime is connected. Each app's +// root layout seeds them at startup; child layouts (e.g. embed) override +// where needed. + +export const adminServer = writable(false); +export const readOnly = writable(false); +export const legacyArchiveDeploy = writable( + !!import.meta.env.VITE_PLAYWRIGHT_TEST, +); diff --git a/web-common/src/features/canvas/AddComponentDropdown.svelte b/web-common/src/features/canvas/AddComponentDropdown.svelte index c40b9332cb7..6a319972109 100644 --- a/web-common/src/features/canvas/AddComponentDropdown.svelte +++ b/web-common/src/features/canvas/AddComponentDropdown.svelte @@ -4,7 +4,7 @@ CHART_CONFIG, VISIBLE_CHART_TYPES, } from "@rilldata/web-common/features/components/charts/config"; - import { featureFlags } from "@rilldata/web-common/features/feature-flags"; + import { useFeatureFlags } from "@rilldata/web-common/features/feature-flags"; import { Plus, PlusCircle } from "lucide-svelte"; import type { ComponentType, SvelteComponent } from "svelte"; import type { ChartType } from "../components/charts/types"; @@ -40,7 +40,7 @@ export let onMouseEnter: () => void = () => {}; export let onOpenChange: (isOpen: boolean) => void = () => {}; - const { customCharts } = featureFlags; + const { customCharts } = useFeatureFlags(); const ADD_DROPDOWN_CHART_TYPES = VISIBLE_CHART_TYPES.filter((type) => { return type !== "stacked_bar" && type !== "stacked_bar_normalized"; diff --git a/web-common/src/features/canvas/CanvasPreviewCTAs.svelte b/web-common/src/features/canvas/CanvasPreviewCTAs.svelte index 163726bf908..2c6eec855da 100644 --- a/web-common/src/features/canvas/CanvasPreviewCTAs.svelte +++ b/web-common/src/features/canvas/CanvasPreviewCTAs.svelte @@ -2,7 +2,8 @@ import { useCanvas } from "@rilldata/web-common/features/canvas/selector"; import { Button } from "../../components/button"; import { useRuntimeClient } from "../../runtime-client/v2"; - import { featureFlags } from "../feature-flags"; + import { readOnly } from "../app-flags"; + import { useFeatureFlags } from "../feature-flags"; import { getFileHref } from "../../layout/navigation/editor-routing"; import ChatToggle from "@rilldata/web-common/features/chat/layouts/sidebar/ChatToggle.svelte"; import ViewAsButton from "../dashboards/granular-access-policies/ViewAsButton.svelte"; @@ -31,7 +32,7 @@ $rillYamlPolicyCheck.data || referencedMetricsViewsHavePolicy; - const { dashboardChat, readOnly } = featureFlags; + const { dashboardChat } = useFeatureFlags(); $: hasAnyContent = hasSecurityPolicy || $dashboardChat || !$readOnly; diff --git a/web-common/src/features/canvas/ai-generation/generateCanvas.ts b/web-common/src/features/canvas/ai-generation/generateCanvas.ts index 3c597e64ae9..fe5598529a6 100644 --- a/web-common/src/features/canvas/ai-generation/generateCanvas.ts +++ b/web-common/src/features/canvas/ai-generation/generateCanvas.ts @@ -18,7 +18,6 @@ import { get, writable } from "svelte/store"; import { overlay } from "../../../layout/overlay-store"; import { queryClient } from "../../../lib/svelte-query/globalQueryClient"; import { getName } from "../../entity-management/name-utils"; -import { featureFlags } from "../../feature-flags"; import OptionToCancelAIGeneration from "../../metrics-views/ai-generation/OptionToCancelAIGeneration.svelte"; export const generatingCanvas = writable(false); @@ -34,9 +33,8 @@ async function createMetricsViewFromTable( databaseSchema: string, tableName: string, abortController: AbortController, + isAiEnabled: boolean, ): Promise { - const isAiEnabled = get(featureFlags.ai); - const newMetricsViewName = getName( `${tableName}_metrics`, fileArtifacts.getNamesForKind(ResourceKind.MetricsView), @@ -94,8 +92,8 @@ async function createMetricsViewFromTable( export async function createCanvasDashboardFromMetricsView( client: RuntimeClient, metricsViewName: string, + isAiEnabled: boolean, ) { - const isAiEnabled = get(featureFlags.ai); const abortController = new AbortController(); overlay.set({ @@ -219,8 +217,8 @@ export async function createCanvasDashboardFromTableWithAgent( database: string, databaseSchema: string, tableName: string, + isAiEnabled: boolean, ): Promise { - const isAiEnabled = get(featureFlags.ai); const abortController = new AbortController(); // Show overlay while creating metrics view @@ -245,6 +243,7 @@ export async function createCanvasDashboardFromTableWithAgent( databaseSchema, tableName, abortController, + isAiEnabled, ); const metricsViewName = resource.meta?.name?.name; @@ -276,8 +275,8 @@ export async function createCanvasDashboardFromTableWithAgent( export async function createCanvasDashboardWithoutNavigation( client: RuntimeClient, metricsViewName: string, + isAiEnabled: boolean, ): Promise { - const isAiEnabled = get(featureFlags.ai); const abortController = new AbortController(); // Get a unique name for the canvas dashboard diff --git a/web-common/src/features/chat/DashboardChat.svelte b/web-common/src/features/chat/DashboardChat.svelte index d2cb5a949af..af0573b40fd 100644 --- a/web-common/src/features/chat/DashboardChat.svelte +++ b/web-common/src/features/chat/DashboardChat.svelte @@ -1,5 +1,5 @@ {#if $dashboardChat && $chatOpen} diff --git a/web-common/src/features/chat/DeveloperChat.svelte b/web-common/src/features/chat/DeveloperChat.svelte index 84c6af8f1d2..84d3de1ba47 100644 --- a/web-common/src/features/chat/DeveloperChat.svelte +++ b/web-common/src/features/chat/DeveloperChat.svelte @@ -1,10 +1,10 @@ {#if $developerChat && $chatOpen} diff --git a/web-common/src/features/chat/core/context/picker/data/index.ts b/web-common/src/features/chat/core/context/picker/data/index.ts index e6b895d86f3..fb87545eee3 100644 --- a/web-common/src/features/chat/core/context/picker/data/index.ts +++ b/web-common/src/features/chat/core/context/picker/data/index.ts @@ -1,5 +1,5 @@ import { derived, get, readable, type Readable } from "svelte/store"; -import { featureFlags } from "@rilldata/web-common/features/feature-flags.ts"; +import { adminServer } from "@rilldata/web-common/features/app-flags.ts"; import { getMetricsViewPickerOptions } from "@rilldata/web-common/features/chat/core/context/picker/data/metrics-views.ts"; import { getModelsPickerOptions } from "@rilldata/web-common/features/chat/core/context/picker/data/models.ts"; import { ContextPickerUIState } from "@rilldata/web-common/features/chat/core/context/picker/ui-state.ts"; @@ -21,7 +21,7 @@ export function getPickerOptions( client: RuntimeClient, uiState: ContextPickerUIState, ): Readable { - const isRillDev = !get(featureFlags.adminServer); + const isRillDev = !get(adminServer); return derived( [ diff --git a/web-common/src/features/chat/layouts/fullpage/FullPageChat.svelte b/web-common/src/features/chat/layouts/fullpage/FullPageChat.svelte index bd745c4be2b..46fd290f89a 100644 --- a/web-common/src/features/chat/layouts/fullpage/FullPageChat.svelte +++ b/web-common/src/features/chat/layouts/fullpage/FullPageChat.svelte @@ -1,7 +1,7 @@ diff --git a/web-common/src/features/connectors/explorer/TableWorkspaceHeader.svelte b/web-common/src/features/connectors/explorer/TableWorkspaceHeader.svelte index 3a3d1426c5c..006d4eb60f9 100644 --- a/web-common/src/features/connectors/explorer/TableWorkspaceHeader.svelte +++ b/web-common/src/features/connectors/explorer/TableWorkspaceHeader.svelte @@ -11,7 +11,7 @@ import { MetricsEventSpace } from "../../../metrics/service/MetricsTypes"; import { useRuntimeClient } from "../../../runtime-client/v2"; import { ResourceKind } from "../../entity-management/resource-selectors"; - import { featureFlags } from "../../feature-flags"; + import { useFeatureFlags } from "../../feature-flags"; import { useCreateMetricsViewFromTableUIAction } from "../../metrics-views/ai-generation/generateMetricsView"; export let connector: string; @@ -19,7 +19,7 @@ export let databaseSchema: string; export let table: string; - const { ai } = featureFlags; + const { ai } = useFeatureFlags(); const client = useRuntimeClient(); @@ -33,6 +33,7 @@ false, BehaviourEventMedium.Button, MetricsEventSpace.RightPanel, + $ai, ); function isHeaderWidthSmall(width: number) { diff --git a/web-common/src/features/dashboards/dimension-table/DimensionHeader.svelte b/web-common/src/features/dashboards/dimension-table/DimensionHeader.svelte index ec0ce2048b6..535281f428a 100644 --- a/web-common/src/features/dashboards/dimension-table/DimensionHeader.svelte +++ b/web-common/src/features/dashboards/dimension-table/DimensionHeader.svelte @@ -6,7 +6,8 @@ import { splitPivotChips } from "@rilldata/web-common/features/dashboards/pivot/pivot-utils"; import { PivotChipType } from "@rilldata/web-common/features/dashboards/pivot/types"; import { metricsExplorerStore } from "@rilldata/web-common/features/dashboards/stores/dashboard-stores"; - import { featureFlags } from "@rilldata/web-common/features/feature-flags"; + import { adminServer } from "@rilldata/web-common/features/app-flags"; + import { useFeatureFlags } from "@rilldata/web-common/features/feature-flags"; import { onDestroy } from "svelte"; import ExportMenu from "../../exports/ExportMenu.svelte"; import { SortType } from "../proto-state/derived-types"; @@ -43,7 +44,7 @@ exploreName, } = stateManagers; - const { adminServer, exports } = featureFlags; + const { exports } = useFeatureFlags(); $: exploreHasTimeDimension = !!$timeRangeSummaryStore.data; diff --git a/web-common/src/features/dashboards/filters/Filters.svelte b/web-common/src/features/dashboards/filters/Filters.svelte index 9638b91456e..e9386bf4e78 100644 --- a/web-common/src/features/dashboards/filters/Filters.svelte +++ b/web-common/src/features/dashboards/filters/Filters.svelte @@ -41,7 +41,7 @@ import { useTimeControlStore } from "../time-controls/time-control-store"; import FilterButton from "./FilterButton.svelte"; import DimensionFilter from "./dimension-filters/DimensionFilter.svelte"; - import { featureFlags } from "../../feature-flags"; + import { useFeatureFlags } from "../../feature-flags"; import Timestamp from "@rilldata/web-common/features/dashboards/time-controls/super-pill/components/Timestamp.svelte"; import { getDefaultTimeGrain } from "@rilldata/web-common/lib/time/grains"; import * as Tooltip from "@rilldata/web-common/components/tooltip-v2"; @@ -50,7 +50,7 @@ import { getPinnedTimeZones } from "../url-state/getDefaultExplorePreset"; import { useRuntimeClient } from "@rilldata/web-common/runtime-client/v2"; - const { rillTime } = featureFlags; + const { rillTime } = useFeatureFlags(); export let readOnly = false; export let timeRanges: V1ExploreTimeRange[]; diff --git a/web-common/src/features/dashboards/pivot/PivotDisplay.svelte b/web-common/src/features/dashboards/pivot/PivotDisplay.svelte index 8b4844085eb..765a64e2a1a 100644 --- a/web-common/src/features/dashboards/pivot/PivotDisplay.svelte +++ b/web-common/src/features/dashboards/pivot/PivotDisplay.svelte @@ -4,7 +4,11 @@ import { getStateManagers } from "@rilldata/web-common/features/dashboards/state-managers/state-managers"; import { metricsExplorerStore } from "@rilldata/web-common/features/dashboards/stores/dashboard-stores"; import ExportMenu from "@rilldata/web-common/features/exports/ExportMenu.svelte"; - import { featureFlags } from "@rilldata/web-common/features/feature-flags"; + import { + adminServer, + readOnly, + } from "@rilldata/web-common/features/app-flags"; + import { useFeatureFlags } from "@rilldata/web-common/features/feature-flags"; import { dynamicHeight } from "@rilldata/web-common/layout/layout-settings.ts"; import { derived } from "svelte/store"; import { useTimeControlStore } from "web-common/src/features/dashboards/time-controls/time-control-store.ts"; @@ -30,7 +34,7 @@ timeRangeSummaryStore, } = stateManagers; - const { adminServer, exports } = featureFlags; + const { exports, cloudDataViewer } = useFeatureFlags(); const timeControlsStore = useTimeControlStore(stateManagers); $: timeControlsForPillActions = { @@ -41,8 +45,6 @@ $: exploreHasTimeDimension = !!$timeRangeSummaryStore.data; - const { cloudDataViewer, readOnly } = featureFlags; - $: isRillDeveloper = $readOnly === false; $: canShowDataViewer = Boolean($cloudDataViewer || isRillDeveloper); diff --git a/web-common/src/features/dashboards/rows-viewer/RowsViewerAccordion.svelte b/web-common/src/features/dashboards/rows-viewer/RowsViewerAccordion.svelte index 15327770f79..048f289c67e 100644 --- a/web-common/src/features/dashboards/rows-viewer/RowsViewerAccordion.svelte +++ b/web-common/src/features/dashboards/rows-viewer/RowsViewerAccordion.svelte @@ -10,12 +10,12 @@ import { useRuntimeClient } from "@rilldata/web-common/runtime-client/v2"; import { useExploreState } from "web-common/src/features/dashboards/stores/dashboard-stores"; import ExportMenu from "../../exports/ExportMenu.svelte"; - import { featureFlags } from "../../feature-flags"; + import { useFeatureFlags } from "../../feature-flags"; import { mergeDimensionAndMeasureFilters } from "../filters/measure-filters/measure-filter-utils"; import type { PivotFilter } from "../pivot/types"; import RowsViewer from "./RowsViewer.svelte"; - const { exports } = featureFlags; + const { exports } = useFeatureFlags(); const timeControlsStore = useTimeControlStore(getStateManagers()); export let metricsViewName: string; diff --git a/web-common/src/features/dashboards/state-managers/loaders/DashboardStateDataLoader.ts b/web-common/src/features/dashboards/state-managers/loaders/DashboardStateDataLoader.ts index 6c49f4e6392..da85b866731 100644 --- a/web-common/src/features/dashboards/state-managers/loaders/DashboardStateDataLoader.ts +++ b/web-common/src/features/dashboards/state-managers/loaders/DashboardStateDataLoader.ts @@ -23,7 +23,7 @@ import type { RuntimeClient } from "@rilldata/web-common/runtime-client/v2"; import type { AfterNavigate } from "@sveltejs/kit"; import { createQuery, type QueryClient } from "@tanstack/svelte-query"; import { Settings } from "luxon"; -import { featureFlags } from "@rilldata/web-common/features/feature-flags"; +import { adminServer } from "@rilldata/web-common/features/app-flags"; import { selectedMockUserStore } from "@rilldata/web-common/features/dashboards/granular-access-policies/stores"; import { derived, get } from "svelte/store"; import { correctExploreState } from "@rilldata/web-common/features/dashboards/stores/correct-explore-state.ts"; @@ -262,8 +262,7 @@ export class DashboardStateDataLoader { // In Cloud (or Developer with a mock user), access policies may be restricting data. // In Developer without a mock user, the issue is more likely data configuration. const isCloudOrMockUser = - get(featureFlags.adminServer) || - get(selectedMockUserStore) !== null; + get(adminServer) || get(selectedMockUserStore) !== null; const message = isCloudOrMockUser ? "This dashboard currently has no data to display. This may be due to the data source configuration or access permissions." : "This dashboard currently has no data to display. Check that your data source has rows and the time dimension column contains non-NULL values."; diff --git a/web-common/src/features/dashboards/time-controls/super-pill/SuperPill.svelte b/web-common/src/features/dashboards/time-controls/super-pill/SuperPill.svelte index 8e83ab809e4..e2baafe9dd8 100644 --- a/web-common/src/features/dashboards/time-controls/super-pill/SuperPill.svelte +++ b/web-common/src/features/dashboards/time-controls/super-pill/SuperPill.svelte @@ -16,7 +16,7 @@ import TimeGrainSelector from "../TimeGrainSelector.svelte"; import * as Elements from "./components"; import RangePickerV2 from "./new-time-dropdown/RangePickerV2.svelte"; - import { featureFlags } from "@rilldata/web-common/features/feature-flags"; + import { useFeatureFlags } from "@rilldata/web-common/features/feature-flags"; export let minDate: DateTime | undefined; export let maxDate: DateTime | undefined; @@ -54,7 +54,7 @@ export let onTimeDimensionSelect: ((dimension: string) => void) | undefined = undefined; - const newPicker = featureFlags.rillTime; + const { rillTime: newPicker } = useFeatureFlags(); $: rangeBuckets = bucketYamlRanges(timeRanges, minTimeGrain, $newPicker); diff --git a/web-common/src/features/dashboards/time-dimension-details/TDDHeader.svelte b/web-common/src/features/dashboards/time-dimension-details/TDDHeader.svelte index 60ca4cf8083..5f136ac1c16 100644 --- a/web-common/src/features/dashboards/time-dimension-details/TDDHeader.svelte +++ b/web-common/src/features/dashboards/time-dimension-details/TDDHeader.svelte @@ -17,7 +17,8 @@ } from "@rilldata/web-common/lib/time/types"; import { V1TimeGrain } from "@rilldata/web-common/runtime-client"; import ExportMenu from "../../exports/ExportMenu.svelte"; - import { featureFlags } from "../../feature-flags"; + import { adminServer } from "../../app-flags"; + import { useFeatureFlags } from "../../feature-flags"; import { PivotChipType } from "../pivot/types"; import { useTimeControlStore } from "../time-controls/time-control-store"; import TimeGrainSelector from "../time-controls/TimeGrainSelector.svelte"; @@ -39,7 +40,7 @@ export let onToggleSearchItems: () => void; export let hideStartPivotButton = false; - const { adminServer, exports } = featureFlags; + const { exports } = useFeatureFlags(); const stateManagers = getStateManagers(); const { diff --git a/web-common/src/features/dashboards/time-series/MetricsTimeSeriesCharts.svelte b/web-common/src/features/dashboards/time-series/MetricsTimeSeriesCharts.svelte index 559305143cd..bac7281f2f3 100644 --- a/web-common/src/features/dashboards/time-series/MetricsTimeSeriesCharts.svelte +++ b/web-common/src/features/dashboards/time-series/MetricsTimeSeriesCharts.svelte @@ -38,14 +38,14 @@ import { TIME_GRAIN } from "../../../lib/time/config"; import { DashboardState_ActivePage } from "../../../proto/gen/rill/ui/v1/dashboard_pb"; import Spinner from "../../entity-management/Spinner.svelte"; - import { featureFlags } from "../../feature-flags"; + import { useFeatureFlags } from "../../feature-flags"; import MeasureBigNumber from "../big-number/MeasureBigNumber.svelte"; import ChartInteractions from "./ChartInteractions.svelte"; import MeasureChart from "./measure-chart/MeasureChart.svelte"; import MeasureChartXAxis from "./measure-chart/MeasureChartXAxis.svelte"; import { ScrubController } from "./measure-chart/ScrubController"; - const { rillTime } = featureFlags; + const { rillTime } = useFeatureFlags(); // Singleton scrub controller — shared across all charts const scrubController = new ScrubController(); diff --git a/web-common/src/features/dashboards/time-series/measure-selection/measure-selection.ts b/web-common/src/features/dashboards/time-series/measure-selection/measure-selection.ts index d2064487fb2..7f4f09142db 100644 --- a/web-common/src/features/dashboards/time-series/measure-selection/measure-selection.ts +++ b/web-common/src/features/dashboards/time-series/measure-selection/measure-selection.ts @@ -5,9 +5,6 @@ import { } from "@rilldata/web-common/features/chat/core/context/inline-context.ts"; import { sidebarActions } from "@rilldata/web-common/features/chat/layouts/sidebar/sidebar-store.ts"; import { get, writable } from "svelte/store"; -import { featureFlags } from "@rilldata/web-common/features/feature-flags.ts"; -import { getExploreNameStore } from "@rilldata/web-common/features/dashboards/nav-utils.ts"; -import { derived } from "svelte/store"; import { V1TimeGrain } from "@rilldata/web-common/runtime-client"; import { roundDownToTimeUnit } from "@rilldata/web-common/features/dashboards/time-series/round-to-nearest-time-unit.ts"; import { TIME_GRAIN } from "@rilldata/web-common/lib/time/config.ts"; @@ -98,15 +95,6 @@ export class MeasureSelection { sidebarActions.startChat(prompt); } - - public getEnabledStore() { - return derived( - [featureFlags.dashboardChat, getExploreNameStore()], - ([dashboardChat, exploreName]) => { - return Boolean(dashboardChat && exploreName); - }, - ); - } } export const measureSelection = new MeasureSelection(); diff --git a/web-common/src/features/dashboards/workspace/Dashboard.svelte b/web-common/src/features/dashboards/workspace/Dashboard.svelte index 760fed08581..111306e9549 100644 --- a/web-common/src/features/dashboards/workspace/Dashboard.svelte +++ b/web-common/src/features/dashboards/workspace/Dashboard.svelte @@ -8,7 +8,8 @@ import PivotDisplay from "@rilldata/web-common/features/dashboards/pivot/PivotDisplay.svelte"; import TabBar from "@rilldata/web-common/features/dashboards/tab-bar/TabBar.svelte"; import { useExploreValidSpec } from "@rilldata/web-common/features/explores/selectors"; - import { featureFlags } from "@rilldata/web-common/features/feature-flags"; + import { readOnly } from "@rilldata/web-common/features/app-flags"; + import { useFeatureFlags } from "@rilldata/web-common/features/feature-flags"; import { dynamicHeight } from "@rilldata/web-common/layout/layout-settings.ts"; import { navigationOpen } from "@rilldata/web-common/layout/navigation/Navigation.svelte"; import Resizer from "@rilldata/web-common/layout/Resizer.svelte"; @@ -48,7 +49,7 @@ dashboardStore, } = StateManagers; - const { cloudDataViewer, readOnly } = featureFlags; + const { cloudDataViewer } = useFeatureFlags(); const timeControlsStore = useTimeControlStore(StateManagers); diff --git a/web-common/src/features/entity-management/add/AddAssetButton.svelte b/web-common/src/features/entity-management/add/AddAssetButton.svelte index cb13eab6e67..fa314e29bb0 100644 --- a/web-common/src/features/entity-management/add/AddAssetButton.svelte +++ b/web-common/src/features/entity-management/add/AddAssetButton.svelte @@ -11,7 +11,7 @@ import { navigateToFile } from "@rilldata/web-common/layout/navigation/editor-routing"; import Button from "../../../components/button/Button.svelte"; import * as DropdownMenu from "@rilldata/web-common/components/dropdown-menu"; - import { featureFlags } from "@rilldata/web-common/features/feature-flags.ts"; + import { useFeatureFlags } from "@rilldata/web-common/features/feature-flags"; import { getScreenNameFromPage } from "@rilldata/web-common/features/file-explorer/telemetry.ts"; import GenerateSampleData from "@rilldata/web-common/features/sample-data/GenerateSampleData.svelte"; import CaretDownIcon from "../../../components/icons/CaretDownIcon.svelte"; @@ -57,7 +57,7 @@ const createFile = createRuntimeServicePutFileMutation(runtimeClient); const createFolder = createRuntimeServiceCreateDirectoryMutation(runtimeClient); - const { developerChat } = featureFlags; + const { developerChat } = useFeatureFlags(); $: currentFile = $page.params.file; $: currentDirectory = currentFile diff --git a/web-common/src/features/explores/ExplorePreviewCTAs.svelte b/web-common/src/features/explores/ExplorePreviewCTAs.svelte index e8affd59341..931ffe83e17 100644 --- a/web-common/src/features/explores/ExplorePreviewCTAs.svelte +++ b/web-common/src/features/explores/ExplorePreviewCTAs.svelte @@ -14,7 +14,8 @@ useRillYamlPolicyCheck, } from "../dashboards/granular-access-policies/useSecurityPolicyCheck"; import StateManagersProvider from "../dashboards/state-managers/StateManagersProvider.svelte"; - import { featureFlags } from "../feature-flags"; + import { readOnly } from "../app-flags"; + import { useFeatureFlags } from "../feature-flags"; import { getFileHref } from "../../layout/navigation/editor-routing"; export let exploreName: string; @@ -37,7 +38,7 @@ ); $: rillYamlPolicyCheck = useRillYamlPolicyCheck(runtimeClient); - const { readOnly, dashboardChat } = featureFlags; + const { dashboardChat } = useFeatureFlags();
diff --git a/web-common/src/features/exports/ExportMenu.svelte b/web-common/src/features/exports/ExportMenu.svelte index e3dcd52499e..bc494dffbda 100644 --- a/web-common/src/features/exports/ExportMenu.svelte +++ b/web-common/src/features/exports/ExportMenu.svelte @@ -5,7 +5,8 @@ import Export from "@rilldata/web-common/components/icons/Export.svelte"; import Tooltip from "@rilldata/web-common/components/tooltip/Tooltip.svelte"; import TooltipContent from "@rilldata/web-common/components/tooltip/TooltipContent.svelte"; - import { featureFlags } from "@rilldata/web-common/features/feature-flags"; + import { adminServer } from "@rilldata/web-common/features/app-flags"; + import { useFeatureFlags } from "@rilldata/web-common/features/feature-flags"; import { createQueryServiceExportMutation, V1ExportFormat, @@ -41,7 +42,7 @@ } const exportDash = createQueryServiceExportMutation(runtimeClient); - const { reports, adminServer, exportHeader } = featureFlags; + const { reports, exportHeader } = useFeatureFlags(); async function handleExport(options: { format: V1ExportFormat; diff --git a/web-common/src/features/feature-flags.ts b/web-common/src/features/feature-flags.ts index 02e4dcc2a83..6e4dc0be301 100644 --- a/web-common/src/features/feature-flags.ts +++ b/web-common/src/features/feature-flags.ts @@ -1,137 +1,87 @@ -import { queryClient } from "@rilldata/web-common/lib/svelte-query/globalQueryClient"; -import { writable } from "svelte/store"; +import { useQueryClient } from "@tanstack/svelte-query"; +import { derived, type Readable } from "svelte/store"; import { createRuntimeServiceGetInstance, runtimeServiceGetInstance, type V1InstanceFeatureFlags, } from "../runtime-client"; import type { RuntimeClient } from "../runtime-client/v2"; - -class FeatureFlag { - private _internal = false; - private _default: boolean; - private state = writable(false); - subscribe = this.state.subscribe; - - constructor(scope: "user" | "rill", defaultValue: boolean) { - this._internal = scope === "rill"; - this._default = defaultValue; - this.set(defaultValue); - } - - get internalOnly() { - return this._internal; - } - - get defaultValue() { - return this._default; - } - - toggle = () => this.state.update((n) => !n); - set = (n: boolean) => this.state.set(n); - resetToDefault = () => this.set(this._default); -} - -type FeatureFlagKey = keyof Omit; - -class FeatureFlags { - ready: Promise; - private _resolveReady!: () => void; - - adminServer = new FeatureFlag("rill", false); - readOnly = new FeatureFlag("rill", false); - // Until we figure out a good way to test managed github we need to use the legacy archive method. - // Right now this is true only in an E2E environment. - legacyArchiveDeploy = new FeatureFlag( - "rill", - !!import.meta.env.VITE_PLAYWRIGHT_TEST, +import { useRuntimeClient } from "../runtime-client/v2/context"; + +// ── Runtime feature flags (per-deployment) ───────────────────────────── +// +// These flags are hydrated from `instance.featureFlags` (sourced from the +// project's `rill.yaml`). Each `` owns a `RuntimeClient`, +// and `useFeatureFlags()` derives reactive stores from a `GetInstance` query +// against that client. Different runtimes have independent flag values, and +// switching runtimes (e.g. branch swap) updates flags without page refresh. +// +// Defaults below act as a fallback when a key is missing from the response. +// Source-of-truth defaults live in `runtime/drivers/registry.go`. + +const RUNTIME_FLAG_DEFAULTS = { + ai: !import.meta.env.VITE_PLAYWRIGHT_TEST, + exports: true, + cloudDataViewer: false, + dimensionSearch: false, + twoTieredNavigation: false, + rillTime: true, + hidePublicUrl: false, + exportHeader: false, + alerts: true, + reports: true, + chat: true, + dashboardChat: false, + developerChat: false, + deploy: true, + stickyDashboardState: false, + cloudEditing: false, + customCharts: false, +} as const satisfies Record; + +export type RuntimeFeatureFlagKey = keyof typeof RUNTIME_FLAG_DEFAULTS; + +export type RuntimeFeatureFlags = { + [K in RuntimeFeatureFlagKey]: Readable; +}; + +const RUNTIME_FLAG_KEYS = Object.keys( + RUNTIME_FLAG_DEFAULTS, +) as RuntimeFeatureFlagKey[]; + +/** + * Returns reactive stores for the runtime feature flags of the nearest + * `` ancestor's `RuntimeClient`. Must be called during + * component initialization (top-level ` diff --git a/web-common/src/features/models/workspace/ModelWorkspaceCTAs.svelte b/web-common/src/features/models/workspace/ModelWorkspaceCTAs.svelte index a7707aacb36..40362802f17 100644 --- a/web-common/src/features/models/workspace/ModelWorkspaceCTAs.svelte +++ b/web-common/src/features/models/workspace/ModelWorkspaceCTAs.svelte @@ -13,6 +13,7 @@ import { useRuntimeClient } from "../../../runtime-client/v2"; import { useGetMetricsViewsForModel } from "../../dashboards/selectors"; import ExportMenu from "../../exports/ExportMenu.svelte"; + import { useFeatureFlags } from "../../feature-flags"; import { useCreateMetricsViewFromTableUIAction } from "../../metrics-views/ai-generation/generateMetricsView"; import NavigateOrDropdown from "../../metrics-views/NavigateOrDropdown.svelte"; import ModelRefreshButton from "../incremental/ModelRefreshButton.svelte"; @@ -26,6 +27,7 @@ export let connector: string; const runtimeClient = useRuntimeClient(); + const { ai } = useFeatureFlags(); $: ({ instanceId } = runtimeClient); $: isModelIdle = @@ -45,6 +47,7 @@ false, BehaviourEventMedium.Menu, MetricsEventSpace.LeftPanel, + $ai, ); diff --git a/web-common/src/features/project/RemoteProjectManager.svelte b/web-common/src/features/project/RemoteProjectManager.svelte index c3d04e9132b..d057b9b6806 100644 --- a/web-common/src/features/project/RemoteProjectManager.svelte +++ b/web-common/src/features/project/RemoteProjectManager.svelte @@ -1,6 +1,7 @@ - - - +{#if $deploy} + + + +{/if} diff --git a/web-common/src/features/project/deploy/route-utils.ts b/web-common/src/features/project/deploy/route-utils.ts index b5ee1875fd0..85c8fc2af04 100644 --- a/web-common/src/features/project/deploy/route-utils.ts +++ b/web-common/src/features/project/deploy/route-utils.ts @@ -10,7 +10,7 @@ import type { Page } from "@sveltejs/kit"; import { derived, readable } from "svelte/store"; import { getLocalGitRepoStatus } from "../selectors"; import { page } from "$app/stores"; -import { featureFlags } from "../../feature-flags"; +import { legacyArchiveDeploy } from "../../app-flags"; import type { V1ResourceName } from "@rilldata/web-common/runtime-client"; /** @@ -113,13 +113,13 @@ export function getDeployingPageUrl(frontendUrl: string, isInvite: boolean) { */ export function getDeployOrGithubRouteGetter() { return derived( - [createLocalServiceGitStatus(), featureFlags.legacyArchiveDeploy], - ([$gitStatus, legacyArchiveDeploy]) => { + [createLocalServiceGitStatus(), legacyArchiveDeploy], + ([$gitStatus, $legacyArchiveDeploy]) => { const hasLocalGitRepo = Boolean( $gitStatus.data?.githubUrl && !$gitStatus.data?.managedGit, ); // For E2E we cannot use github just yet. So do not show the git path for that case. - const shouldUseGit = !legacyArchiveDeploy && hasLocalGitRepo; + const shouldUseGit = !$legacyArchiveDeploy && hasLocalGitRepo; return { isLoading: $gitStatus.isPending, getter: shouldUseGit diff --git a/web-common/src/features/sample-data/GenerateSampleData.svelte b/web-common/src/features/sample-data/GenerateSampleData.svelte index 67821f63abf..64626870db9 100644 --- a/web-common/src/features/sample-data/GenerateSampleData.svelte +++ b/web-common/src/features/sample-data/GenerateSampleData.svelte @@ -8,14 +8,14 @@ import { object, string } from "yup"; import IconButton from "../../components/button/IconButton.svelte"; import SendIcon from "@rilldata/web-common/components/icons/SendIcon.svelte"; - import { featureFlags } from "@rilldata/web-common/features/feature-flags.ts"; + import { useFeatureFlags } from "@rilldata/web-common/features/feature-flags"; export let type: "home" | "modal"; export let open = false; const runtimeClient = useRuntimeClient(); - const { developerChat } = featureFlags; + const { developerChat } = useFeatureFlags(); const FORM_ID = "generate-sample-data-form"; diff --git a/web-common/src/features/sources/modal/SourceImportedModal.svelte b/web-common/src/features/sources/modal/SourceImportedModal.svelte index 757551aa669..08aacdcb6ac 100644 --- a/web-common/src/features/sources/modal/SourceImportedModal.svelte +++ b/web-common/src/features/sources/modal/SourceImportedModal.svelte @@ -13,13 +13,13 @@ import { MetricsEventSpace } from "../../../metrics/service/MetricsTypes"; import type { V1Resource } from "../../../runtime-client"; import { extractFileName } from "../../entity-management/file-path-utils"; - import { featureFlags } from "../../feature-flags"; + import { useFeatureFlags } from "../../feature-flags"; import { createCanvasDashboardFromTableWithAgent, useCreateMetricsViewWithCanvasAndExploreUIAction, } from "../../metrics-views/ai-generation/generateMetricsView"; - const { ai, developerChat } = featureFlags; + const { ai, developerChat } = useFeatureFlags(); export let sourcePath: string | null; @@ -46,6 +46,7 @@ sourceName, BehaviourEventMedium.Button, MetricsEventSpace.Modal, + $ai, ) : null; @@ -73,6 +74,7 @@ "", "", sourceName, + $ai, ); } else { await createDashboardFromTable(); diff --git a/web-common/src/features/sources/navigation/SourceMenuItems.svelte b/web-common/src/features/sources/navigation/SourceMenuItems.svelte index 9568a718e7e..9e58463d12d 100644 --- a/web-common/src/features/sources/navigation/SourceMenuItems.svelte +++ b/web-common/src/features/sources/navigation/SourceMenuItems.svelte @@ -5,7 +5,7 @@ import Model from "@rilldata/web-common/components/icons/Model.svelte"; import RefreshIcon from "@rilldata/web-common/components/icons/RefreshIcon.svelte"; import { fileArtifacts } from "@rilldata/web-common/features/entity-management/file-artifacts"; - import { featureFlags } from "@rilldata/web-common/features/feature-flags"; + import { useFeatureFlags } from "@rilldata/web-common/features/feature-flags"; import { navigateToFile } from "@rilldata/web-common/layout/navigation/editor-routing"; import { getScreenNameFromPage } from "@rilldata/web-common/features/file-explorer/telemetry"; import { openResourceGraphQuickView } from "@rilldata/web-common/features/resource-graph/quick-view/quick-view-store"; @@ -48,7 +48,7 @@ $: ({ instanceId } = runtimeClient); - const { ai, developerChat } = featureFlags; + const { ai, developerChat } = useFeatureFlags(); $: sourceQuery = fileArtifact.getResource(queryClient); let source: V1Source | undefined; @@ -88,6 +88,7 @@ false, BehaviourEventMedium.Menu, MetricsEventSpace.LeftPanel, + $ai, ); $: createExploreFromTable = useCreateMetricsViewFromTableUIAction( @@ -100,6 +101,7 @@ true, BehaviourEventMedium.Menu, MetricsEventSpace.LeftPanel, + $ai, ); $: createCanvasDashboardFromTable = useCreateMetricsViewWithCanvasUIAction( @@ -111,6 +113,7 @@ tableName, BehaviourEventMedium.Menu, MetricsEventSpace.LeftPanel, + $ai, ); const handleCreateModel = async () => { @@ -179,6 +182,7 @@ database, databaseSchema, tableName, + $ai, ); } else { await createCanvasDashboardFromTable(); diff --git a/web-common/src/layout/ApplicationHeader.svelte b/web-common/src/layout/ApplicationHeader.svelte index ab60858a1ca..acce7b835f4 100644 --- a/web-common/src/layout/ApplicationHeader.svelte +++ b/web-common/src/layout/ApplicationHeader.svelte @@ -15,7 +15,7 @@ } from "@rilldata/web-common/features/dashboards/selectors.js"; import DeployProjectCTA from "@rilldata/web-common/features/dashboards/workspace/DeployProjectCTA.svelte"; import ExplorePreviewCTAs from "@rilldata/web-common/features/explores/ExplorePreviewCTAs.svelte"; - import { featureFlags } from "@rilldata/web-common/features/feature-flags.ts"; + import { useFeatureFlags } from "@rilldata/web-common/features/feature-flags"; import { useProjectTitle } from "@rilldata/web-common/features/project/selectors"; import Header from "@rilldata/web-common/layout/header/Header.svelte"; import HeaderLogo from "@rilldata/web-common/layout/header/HeaderLogo.svelte"; @@ -27,7 +27,7 @@ import Tag from "../components/tag/Tag.svelte"; import { fileArtifacts } from "../features/entity-management/file-artifacts"; - const { deploy, developerChat, stickyDashboardState } = featureFlags; + const { deploy, developerChat, stickyDashboardState } = useFeatureFlags(); const runtimeClient = useRuntimeClient(); export let mode: string; diff --git a/web-common/src/runtime-client/v2/RuntimeProvider.svelte b/web-common/src/runtime-client/v2/RuntimeProvider.svelte index 1b9d1006f9f..3a69732caf9 100644 --- a/web-common/src/runtime-client/v2/RuntimeProvider.svelte +++ b/web-common/src/runtime-client/v2/RuntimeProvider.svelte @@ -1,7 +1,6 @@