Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions runtime/feature_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ var defaultFeatureFlags = map[string]string{
"developer_agent": "true",
// Controls if the dashboard state is persisted when navigating to a different dashboard.
"sticky_dashboard_state": "false",
// Controls if the dashboard state is persisted when user revisits the same dashboard.
"disable_persistent_dashboard_state": "false",
// Controls visibility of the cloud editing feature (Edit button and edit routes)
"cloud_editing": "true",
// Controls visibility of the custom chart option in canvas dashboards
Expand Down
148 changes: 76 additions & 72 deletions runtime/feature_flags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,25 @@ func Test_ResolveFeatureFlags(t *testing.T) {
"domain": "rilldata.com",
},
featureFlags: map[string]bool{
"exports": true,
"cloudDataViewer": false,
"dimensionSearch": true,
"twoTieredNavigation": false,
"rillTime": true,
"hidePublicUrl": false,
"exportHeader": false,
"alerts": true,
"reports": true,
"chat": true,
"dashboardChat": false,
"developerChat": true,
"chatCharts": true,
"deploy": true,
"developerAgent": true,
"stickyDashboardState": false,
"cloudEditing": true,
"customCharts": false,
"exports": true,
"cloudDataViewer": false,
"dimensionSearch": true,
"twoTieredNavigation": false,
"rillTime": true,
"hidePublicUrl": false,
"exportHeader": false,
"alerts": true,
"reports": true,
"chat": true,
"dashboardChat": false,
"developerChat": true,
"chatCharts": true,
"deploy": true,
"developerAgent": true,
"stickyDashboardState": false,
"cloudEditing": true,
"customCharts": false,
"disablePersistentDashboardState": false,
},
},
{
Expand All @@ -53,24 +54,25 @@ func Test_ResolveFeatureFlags(t *testing.T) {
"domain": "gmail.com",
},
featureFlags: map[string]bool{
"exports": true,
"cloudDataViewer": false,
"dimensionSearch": false,
"twoTieredNavigation": false,
"rillTime": true,
"hidePublicUrl": false,
"exportHeader": false,
"alerts": false,
"reports": true,
"chat": true,
"dashboardChat": false,
"developerChat": true,
"chatCharts": true,
"deploy": true,
"developerAgent": true,
"stickyDashboardState": false,
"cloudEditing": true,
"customCharts": false,
"exports": true,
"cloudDataViewer": false,
"dimensionSearch": false,
"twoTieredNavigation": false,
"rillTime": true,
"hidePublicUrl": false,
"exportHeader": false,
"alerts": false,
"reports": true,
"chat": true,
"dashboardChat": false,
"developerChat": true,
"chatCharts": true,
"deploy": true,
"developerAgent": true,
"stickyDashboardState": false,
"cloudEditing": true,
"customCharts": false,
"disablePersistentDashboardState": false,
},
},
{
Expand All @@ -79,24 +81,25 @@ func Test_ResolveFeatureFlags(t *testing.T) {
"domain": "yahoo.com",
},
featureFlags: map[string]bool{
"exports": true,
"cloudDataViewer": false,
"dimensionSearch": false,
"twoTieredNavigation": false,
"rillTime": true,
"hidePublicUrl": false,
"exportHeader": false,
"alerts": false,
"reports": false,
"chat": true,
"dashboardChat": false,
"developerChat": true,
"chatCharts": true,
"deploy": true,
"developerAgent": true,
"stickyDashboardState": false,
"cloudEditing": true,
"customCharts": false,
"exports": true,
"cloudDataViewer": false,
"dimensionSearch": false,
"twoTieredNavigation": false,
"rillTime": true,
"hidePublicUrl": false,
"exportHeader": false,
"alerts": false,
"reports": false,
"chat": true,
"dashboardChat": false,
"developerChat": true,
"chatCharts": true,
"deploy": true,
"developerAgent": true,
"stickyDashboardState": false,
"cloudEditing": true,
"customCharts": false,
"disablePersistentDashboardState": false,
},
},
{
Expand All @@ -105,24 +108,25 @@ func Test_ResolveFeatureFlags(t *testing.T) {
"embed": true,
},
featureFlags: map[string]bool{
"exports": true,
"cloudDataViewer": false,
"dimensionSearch": false,
"twoTieredNavigation": false,
"rillTime": true,
"hidePublicUrl": true,
"exportHeader": false,
"alerts": false,
"reports": false,
"chat": false,
"dashboardChat": false, // forced false because chat is false
"developerChat": true,
"chatCharts": true,
"deploy": true,
"developerAgent": true,
"stickyDashboardState": false,
"cloudEditing": true,
"customCharts": false,
"exports": true,
"cloudDataViewer": false,
"dimensionSearch": false,
"twoTieredNavigation": false,
"rillTime": true,
"hidePublicUrl": true,
"exportHeader": false,
"alerts": false,
"reports": false,
"chat": false,
"dashboardChat": false, // forced false because chat is false
"developerChat": true,
"chatCharts": true,
"deploy": true,
"developerAgent": true,
"stickyDashboardState": false,
"cloudEditing": true,
"customCharts": false,
"disablePersistentDashboardState": false,
},
},
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@
import { isNotFoundError } from "@rilldata/web-common/lib/errors";
import { useRuntimeClient } from "@rilldata/web-common/runtime-client/v2";
import type { PageData } from "./$types";
import { featureFlags } from "@rilldata/web-common/features/feature-flags.ts";

export let data: PageData;
$: ({ project } = data);

const { disablePersistentDashboardState } = featureFlags;

const runtimeClient = useRuntimeClient();
$: ({
organization: orgName,
Expand Down Expand Up @@ -115,6 +118,8 @@
{exploreName}
storageNamespacePrefix={`${orgName}__${projectName}__`}
bookmarkOrTokenExploreState={bookmarkExploreStateQuery}
disableMostRecentDashboardState={$disablePersistentDashboardState}
disableInitSessionDashboardState={$disablePersistentDashboardState}
>
<Dashboard {metricsViewName} {exploreName} />
</DashboardStateManager>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export class DashboardStateDataLoader {
| CompoundQueryResult<Partial<ExploreState> | null>
| undefined,
public readonly disableMostRecentDashboardState: boolean,
public readonly disableInitSessionDashboardState: boolean,
) {
this.validSpecQuery = useExploreValidSpec(client, exploreName);
this.fullTimeRangeQuery = this.useFullTimeRangeQuery(
Expand Down Expand Up @@ -153,6 +154,7 @@ export class DashboardStateDataLoader {
exploreStateFromYAMLConfig,
rillDefaultExploreState,
backButtonUsed: false,
skipSessionStorage: this.disableInitSessionDashboardState,
});
},
);
Expand Down Expand Up @@ -191,6 +193,9 @@ export class DashboardStateDataLoader {
exploreStateFromYAMLConfig,
rillDefaultExploreState,
backButtonUsed,
// This should not be disabled when disableInitSessionDashboardState is set.
// While going between views, we still need session storage to save the state.
skipSessionStorage: false,
});
}

Expand Down Expand Up @@ -297,6 +302,7 @@ export class DashboardStateDataLoader {
exploreStateFromYAMLConfig,
rillDefaultExploreState,
backButtonUsed,
skipSessionStorage,
}: {
metricsViewSpec: V1MetricsViewSpec;
exploreSpec: V1ExploreSpec;
Expand All @@ -305,10 +311,11 @@ export class DashboardStateDataLoader {
exploreStateFromYAMLConfig: Partial<ExploreState>;
rillDefaultExploreState: ExploreState;
backButtonUsed: boolean;
skipSessionStorage: boolean;
}) {
urlSearchParams = cleanEmbedUrlParams(urlSearchParams);

const skipSessionStorage = backButtonUsed;
skipSessionStorage ||= backButtonUsed;
const exploreStateFromSessionStorage = skipSessionStorage
? null
: getPartialExploreStateFromSessionStorage(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,33 @@ describe("DashboardStateManager", () => {
// only 2 urls should in history
expect(pageMock.urlSearchHistory).toEqual([initUrlSearch, ""]);
});

it("Should not load local storage or session storage when disabled", async () => {
setMostRecentExploreStateInLocalStorage(AD_BIDS_EXPLORE_NAME, undefined, {
visibleMeasures: [AD_BIDS_BID_PRICE_MEASURE],
allMeasuresVisible: false,
visibleDimensions: [AD_BIDS_DOMAIN_DIMENSION],
allDimensionsVisible: false,

leaderboardSortByMeasureName: AD_BIDS_BID_PRICE_MEASURE,
leaderboardMeasureNames: [AD_BIDS_BID_PRICE_MEASURE],
sortDirection: DashboardState_LeaderboardSortDirection.ASCENDING,
dashboardSortType: DashboardState_LeaderboardSortType.VALUE,
});
setExploreStateForWebView(
AD_BIDS_EXPLORE_NAME,
undefined,
ExploreUrlWebView.Explore,
"view=explore&tr=P14D&compare_tr=rill-PW&grain=day&measures=bid_price&dims=domain&sort_by=bid_price&sort_type=delta_abs&sort_dir=DESC&leaderboard_measures=bid_price",
);
renderDashboardStateManager(undefined, true, true);
await waitFor(() => expect(screen.getByText("Dashboard loaded!")));

assertExploreStateSubset({
...ExploreStateSubsetForRillDefaultState,
...ExploreStateSubsetForYAMLState,
});
});
});

describe("Dashboards without timeseries", () => {
Expand Down Expand Up @@ -481,11 +508,15 @@ function renderDashboardStateManager(
bookmarkOrTokenExploreState:
| CompoundQueryResult<Partial<ExploreState> | undefined>
| undefined = undefined,
disableMostRecentDashboardState: boolean = false,
disableInitSessionDashboardState: boolean = false,
) {
const renderResults = render(DashboardStateManagerTest, {
props: {
exploreName: AD_BIDS_EXPLORE_NAME,
bookmarkOrTokenExploreState,
disableMostRecentDashboardState,
disableInitSessionDashboardState,
},
// TODO: we need to make sure every single query uses an explicit queryClient instead of the global one
// only then we can use a fresh client here.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@
} from "@rilldata/web-common/lib/errors";
import { useRuntimeClient } from "@rilldata/web-common/runtime-client/v2";
import { onDestroy } from "svelte";
import { clearExploreSessionStore } from "@rilldata/web-common/features/dashboards/state-managers/loaders/explore-web-view-store.ts";

export let exploreName: string;
export let storageNamespacePrefix: string | undefined = undefined;
export let bookmarkOrTokenExploreState:
| CompoundQueryResult<Partial<ExploreState> | null>
| undefined = undefined;
export let disableMostRecentDashboardState: boolean = false;
export let disableInitSessionDashboardState: boolean = false;

const client = useRuntimeClient();

Expand All @@ -42,6 +44,7 @@
storageNamespacePrefix,
bookmarkOrTokenExploreState,
disableMostRecentDashboardState,
disableInitSessionDashboardState,
);

let stateSync: DashboardStateSync | undefined;
Expand Down Expand Up @@ -94,11 +97,17 @@

onNavigate(({ from, to }) => {
const changedDashboard =
!from || !to || from.params?.dashboard !== to.params?.dashboard;
!from ||
!to ||
from.params?.dashboard !== to.params?.dashboard ||
from.params?.name !== to.params?.name;
// Clear out any dashboard banners
// Note: we still have this on top of the above reactive statement to handle cases where navigation is to a non-dashboard route.
if (changedDashboard) {
eventBus.emit("remove-banner", ExploreUrlLimitWarningBannerID);
if (disableInitSessionDashboardState) {
clearExploreSessionStore(exploreName, storageNamespacePrefix);
}
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,15 @@
export let bookmarkOrTokenExploreState:
| CompoundQueryResult<Partial<ExploreState> | null>
| undefined = undefined;
export let disableMostRecentDashboardState: boolean = false;
export let disableInitSessionDashboardState: boolean = false;
</script>

<DashboardStateManager {exploreName} {bookmarkOrTokenExploreState}>
<DashboardStateManager
{exploreName}
{bookmarkOrTokenExploreState}
{disableMostRecentDashboardState}
{disableInitSessionDashboardState}
>
<div>Dashboard loaded!</div>
</DashboardStateManager>
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 @@ -66,6 +66,7 @@ class FeatureFlags {
stickyDashboardState = new FeatureFlag("user", false);
cloudEditing = new FeatureFlag("user", false);
customCharts = new FeatureFlag("user", false);
disablePersistentDashboardState = new FeatureFlag("user", false);

private flagsUnsub?: () => void;

Expand Down
Loading
Loading