Skip to content

Commit

Permalink
Apply home bookmark on page load (#4269)
Browse files Browse the repository at this point in the history
* Apply home bookmark on page load

* Fix lint
  • Loading branch information
AdityaHegde authored Mar 11, 2024
1 parent 50a4fb9 commit c9deff2
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 44 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<script lang="ts">
import { page } from "$app/stores";
import { useQueryClient } from "@rilldata/svelte-query";
import { getBookmarks } from "@rilldata/web-admin/features/bookmarks/selectors";
import {
createTimeRangeSummary,
useMetricsView,
useModelHasTimeSeries,
} from "@rilldata/web-common/features/dashboards/selectors/index";
import { getStateManagers } from "@rilldata/web-common/features/dashboards/state-managers/state-managers";
import { metricsExplorerStore } from "@rilldata/web-common/features/dashboards/stores/dashboard-stores";
import { hasPersistentDashboardData } from "@rilldata/web-common/features/dashboards/stores/persistent-dashboard-state";
import { syncDashboardState } from "@rilldata/web-common/features/dashboards/stores/syncDashboardState";
import { initLocalUserPreferenceStore } from "@rilldata/web-common/features/dashboards/user-preferences";
import { createQueryServiceMetricsViewSchema } from "@rilldata/web-common/runtime-client";
import { runtime } from "@rilldata/web-common/runtime-client/runtime-store";
import Spinner from "@rilldata/web-common/features/entity-management/Spinner.svelte";
import { EntityStatus } from "@rilldata/web-common/features/entity-management/types";
export let metricViewName: string;
$: initLocalUserPreferenceStore(metricViewName);
const stateManagers = getStateManagers();
const metricsView = useMetricsView(stateManagers);
const hasTimeSeries = useModelHasTimeSeries(stateManagers);
const timeRangeQuery = createTimeRangeSummary(stateManagers);
const metricsViewSchema = createQueryServiceMetricsViewSchema(
$runtime.instanceId,
metricViewName,
);
const queryClient = useQueryClient();
$: bookmarks = getBookmarks(
queryClient,
$runtime?.instanceId,
$page.params.organization,
$page.params.project,
metricViewName,
);
function syncDashboardStateLocal() {
let stateToLoad = $page.url.searchParams.get("state");
if (
!hasPersistentDashboardData() &&
!stateToLoad &&
$bookmarks.data?.home.resource.data
) {
stateToLoad = $bookmarks.data?.home.resource.data;
}
syncDashboardState(
metricViewName,
$metricsView.data,
$metricsViewSchema.data?.schema,
$timeRangeQuery.data,
stateToLoad,
);
}
$: if (
$metricsView.data &&
$metricsViewSchema.data &&
($timeRangeQuery.data || !$hasTimeSeries.data) &&
!$bookmarks.isFetching
) {
syncDashboardStateLocal();
}
$: ready = metricViewName in $metricsExplorerStore.entities;
</script>

{#if ready}
<slot />
{:else}
<div class="grid place-items-center mt-40">
<Spinner status={EntityStatus.Running} size="40px" />
</div>
{/if}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
createAdminServiceGetProject,
V1DeploymentStatus,
} from "@rilldata/web-admin/client";
import DashboardAdminStateProvider from "@rilldata/web-admin/features/dashboards/DashboardAdminStateProvider.svelte";
import { getDashboardsForProject } from "@rilldata/web-admin/features/dashboards/listing/selectors";
import { invalidateDashboardsQueries } from "@rilldata/web-admin/features/projects/invalidations";
import ProjectErrored from "@rilldata/web-admin/features/projects/ProjectErrored.svelte";
Expand All @@ -13,7 +14,6 @@
import DashboardURLStateProvider from "@rilldata/web-common/features/dashboards/proto-state/DashboardURLStateProvider.svelte";
import { useDashboard } from "@rilldata/web-common/features/dashboards/selectors";
import StateManagersProvider from "@rilldata/web-common/features/dashboards/state-managers/StateManagersProvider.svelte";
import DashboardStateProvider from "@rilldata/web-common/features/dashboards/stores/DashboardStateProvider.svelte";
import { ResourceKind } from "@rilldata/web-common/features/entity-management/resource-selectors";
import { getRuntimeServiceGetResourceQueryKey } from "@rilldata/web-common/runtime-client";
import { runtime } from "@rilldata/web-common/runtime-client/runtime-store";
Expand Down Expand Up @@ -102,13 +102,13 @@
{:else}
{#key dashboardName}
<StateManagersProvider metricsViewName={dashboardName}>
<DashboardStateProvider metricViewName={dashboardName}>
<DashboardAdminStateProvider metricViewName={dashboardName}>
<DashboardURLStateProvider metricViewName={dashboardName}>
<DashboardThemeProvider>
<Dashboard metricViewName={dashboardName} leftMargin={"48px"} />
</DashboardThemeProvider>
</DashboardURLStateProvider>
</DashboardStateProvider>
</DashboardAdminStateProvider>
</StateManagersProvider>
{/key}
{/if}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
}
onDestroy(() => {
if (unsubscribe) unsubscribe();
unsubscribe?.();
});
</script>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,7 @@ export type DashboardUrlStore = Readable<DashboardUrlState>;
*/
export function useDashboardUrlState(ctx: StateManagers): DashboardUrlStore {
return derived(
[
derived(ctx.dashboardStore, (dashboard) => dashboard?.proto),
useDashboardDefaultProto(ctx),
page,
],
[useDashboardProto(ctx), useDashboardDefaultProto(ctx), page],
([proto, defaultProtoState, page]) => {
if (defaultProtoState.isFetching)
return {
Expand Down Expand Up @@ -78,18 +74,9 @@ export function useDashboardUrlSync(ctx: StateManagers, schema: V1StructType) {
const metricsView = useMetricsView(ctx);

let lastKnownProto = get(dashboardUrlState)?.defaultProto;
const unsub = dashboardUrlState.subscribe((state) => {
return dashboardUrlState.subscribe((state) => {
const metricViewName = get(ctx.metricsViewName);
if (state.urlName !== metricViewName) {
// Edge case where the instance of sync doesnt match the active metrics view
// TODO: We really need to rethink the new architecture that leads to this issue.
// Using a single constant store that changes based on name in ctx will lead to stale data.
try {
// Race condition when unsub is not yet initialised
unsub();
} catch (e) {
// no-op
}
return;
}

Expand All @@ -111,8 +98,6 @@ export function useDashboardUrlSync(ctx: StateManagers, schema: V1StructType) {
lastKnownProto = state.urlProto;
}
});

return unsub;
}

function gotoNewDashboardUrl(url: URL, newState: string, defaultState: string) {
Expand All @@ -133,6 +118,16 @@ function gotoNewDashboardUrl(url: URL, newState: string, defaultState: string) {
goto(newUrl.toString());
}

/**
* Pulls data from dashboard to create the url state.
* Any subsections in the future would be added here to build the final url state.
*/
export function useDashboardProto(ctx: StateManagers) {
return derived([ctx.dashboardStore], ([dashboard]) =>
getProtoFromDashboardState(dashboard),
);
}

// NOTE: the data here can be stale when metricsViewName changes in ctx, along with the metricsView.
// but the time range summary is yet to be triggered to change causing it to have data from previous active dashboard
// Above issue is currently fixed in useDashboardUrlSync and DashboardURLStateProvider by create a new instance when the url is changed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
} from "@rilldata/web-common/features/dashboards/selectors/index";
import { getStateManagers } from "@rilldata/web-common/features/dashboards/state-managers/state-managers";
import { metricsExplorerStore } from "@rilldata/web-common/features/dashboards/stores/dashboard-stores";
import { syncDashboardState } from "@rilldata/web-common/features/dashboards/stores/syncDashboardState";
import { initLocalUserPreferenceStore } from "@rilldata/web-common/features/dashboards/user-preferences";
import { createQueryServiceMetricsViewSchema } from "@rilldata/web-common/runtime-client";
import { runtime } from "@rilldata/web-common/runtime-client/runtime-store";
Expand All @@ -25,36 +26,22 @@
metricViewName,
);
function syncDashboardState() {
if (!$metricsView.data || !$metricsViewSchema.data?.schema) return;
if (metricViewName in $metricsExplorerStore.entities) {
metricsExplorerStore.sync(metricViewName, $metricsView.data);
} else {
metricsExplorerStore.init(
metricViewName,
$metricsView.data,
$timeRangeQuery.data,
);
const urlState = $page.url.searchParams.get("state");
if (urlState) {
metricsExplorerStore.syncFromUrl(
metricViewName,
urlState,
$metricsView.data,
$metricsViewSchema.data.schema,
);
// Call sync to make sure changes in dashboard are honoured
metricsExplorerStore.sync(metricViewName, $metricsView.data);
}
}
function syncDashboardStateLocal() {
syncDashboardState(
metricViewName,
$metricsView.data,
$metricsViewSchema.data?.schema,
$timeRangeQuery.data,
$page.url.searchParams.get("state"),
);
}
$: if (
$metricsView.data &&
$metricsViewSchema.data &&
($timeRangeQuery.data || !$hasTimeSeries.data)
) {
syncDashboardState();
syncDashboardStateLocal();
}
$: ready = metricViewName in $metricsExplorerStore.entities;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,8 @@ export function getPersistentDashboardState(): PersistentDashboardState {
if (!persistentDashboardStore) return {};
return get(persistentDashboardStore);
}

export function hasPersistentDashboardData() {
if (!persistentDashboardStore) return false;
return Object.keys(get(persistentDashboardStore)).length > 0;
}
32 changes: 32 additions & 0 deletions web-common/src/features/dashboards/stores/syncDashboardState.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { metricsExplorerStore } from "@rilldata/web-common/features/dashboards/stores/dashboard-stores";
import type {
V1MetricsViewSpec,
V1MetricsViewTimeRangeResponse,
V1StructType,
} from "@rilldata/web-common/runtime-client";
import { get } from "svelte/store";

export function syncDashboardState(
metricViewName: string,
metricsViewSpec: V1MetricsViewSpec | undefined,
metricsViewSchema: V1StructType | undefined,
timeRangeQuery: V1MetricsViewTimeRangeResponse | undefined,
preloadUrlState: string | null,
) {
if (!metricsViewSpec || !metricsViewSchema) return;
if (metricViewName in get(metricsExplorerStore).entities) {
metricsExplorerStore.sync(metricViewName, metricsViewSpec);
} else {
metricsExplorerStore.init(metricViewName, metricsViewSpec, timeRangeQuery);
if (preloadUrlState) {
metricsExplorerStore.syncFromUrl(
metricViewName,
preloadUrlState,
metricsViewSpec,
metricsViewSchema,
);
// Call sync to make sure changes in dashboard are honoured
metricsExplorerStore.sync(metricViewName, metricsViewSpec);
}
}
}

1 comment on commit c9deff2

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.