-
Notifications
You must be signed in to change notification settings - Fork 124
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: session storage retrieval for url messes with the url history #6238
Conversation
AdityaHegde
commented
Dec 9, 2024
•
edited
Loading
edited
- Since we were redirecting url when visiting the home page. Any saved state would lead to a redirect loop when back button was pressed. Using history.replaceState instead to update the url to fix this.
- Switching between dashboards using the breadcrumbs would pollute the other dashboard's state. Using exploreName from loader function to keep things consistent.
- Disable TTD for dashboards without timeseries. Earlier the button was clickable but nothing would happen. Now there will not be a button at all.
- Figure out the E2E failure
- Load metrics view schema for bookmarks.
32a414f
to
66d545a
Compare
0f5ee6b
to
30b0075
Compare
I added a filter, pressed the browser's back button, the filter was removed from the URL, but the filter was not actually removed from the dashboard. |
@@ -86,6 +77,7 @@ export function useExploreValidSpec( | |||
export async function fetchExploreSpec( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is confusing as the function does not actually return an explore spec
(or validSpec
). A better name might be fetchExploreResourceAndState
, but then it's clear that this function is doing more than one thing. While a better name would be an improvement, consider if this function should really be split in two.
web-common/src/features/dashboards/stores/persistent-dashboard-state.ts
Outdated
Show resolved
Hide resolved
export let defaultExplorePreset: V1ExplorePreset; | ||
export let initExploreState: Partial<MetricsExplorerEntity>; | ||
export let initUrlSearch: string; | ||
export let partialExploreState: Partial<MetricsExplorerEntity>; | ||
export let urlSearchForPartial: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This confuses me that we're passing state from a subset of sources (defaultExplorePreset
, initUrlSearch
) and passing initExploreState
(which should be a synthesis of the all state sources). We should either:
- Pass all state sources (e.g. including
localStorageExploreState
) and not passinitExploreState
(which would be computed downstream). - Pass no individual state sources (e.g.
defaultExplorePreset
,initUrlSearch
) and instead passinitExploreState
(which would be computed somewhere upstream).
Given this component seems to be in charge of state synthesis, we should do option 1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Passing down all states to DashboardURLStateSync and handling the merging logic there.
web-common/src/features/dashboards/big-number/MeasureBigNumber.svelte
Outdated
Show resolved
Hide resolved
web-admin/src/routes/[organization]/[project]/explore/[dashboard]/+page.ts
Outdated
Show resolved
Hide resolved
web-common/src/features/dashboards/url-state/DashboardURLStateSync.svelte
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
General reminder that this should be a conversion to ExploreState
not to ExplorePreset
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. This PR is not an exhaustive refactor. Lets do that in a separate PR.
Related issue here: #6248 |
676a774
to
3fc4354
Compare
web-common/src/features/dashboards/url-state/convertURLToExplorePreset.ts
Outdated
Show resolved
Hide resolved
web-common/src/features/metrics-views/editor/MetricsEditor.svelte
Outdated
Show resolved
Hide resolved
export let defaultExplorePreset: V1ExplorePreset; | ||
export let partialExploreState: Partial<MetricsExplorerEntity>; | ||
export let exploreStateFromYAMLConfig: Partial<MetricsExplorerEntity>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These props are covering two different state sources: the Rill-opinionated default state (A) and the developer-specified default state (B).
defaultExplorePreset
combines A + B.
exploreStateFromYAMLConfig
is just B.
We should have 1 prop for A and 1 prop for B.
"A" should always be of the type ExploreState
. I think "B" should be converted from ExplorePreset
to ExploreState
as soon as we get it back from the GetResource
API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets take that refactor in a future PR. ExploreState
should inherit from ExplorePreset
to avoid mapping of individual fields.
web-common/src/features/dashboards/url-state/DashboardURLStateSync.svelte
Outdated
Show resolved
Hide resolved
web-admin/src/routes/[organization]/[project]/explore/[dashboard]/+layout.ts
Outdated
Show resolved
Hide resolved
web-admin/src/routes/[organization]/[project]/explore/[dashboard]/+layout.ts
Outdated
Show resolved
Hide resolved
export let defaultExplorePreset: V1ExplorePreset; | ||
export let partialExploreState: Partial<MetricsExplorerEntity>; | ||
export let exploreStateFromYAMLConfig: Partial<MetricsExplorerEntity>; | ||
export let initExploreState: Partial<MetricsExplorerEntity> | undefined = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"initExploreState" doesn't specify which source of state it is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm this is supposed to be bookmark state on cloud explore, token's state for public URLs and undefined for rill-dev. Not sure what a good name would be to capture this. Adding them explicitly like bookmarkExploreState
etc doesnt make sense since it is irrelevant on rill-dev.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think optional props would be most clear:
export let bookmarkExploreState: Partial<ExploreState> | undefined = undefined;
export let tokenExploreState: Partial<ExploreState> | undefined = undefined;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have renamed the variables until the call to DashboardURLStateSync. We should avoid having cloud/dev specific login in common code.
61fc74a
to
9cafbd1
Compare
b25ea0c
to
14d76a9
Compare
a8fbef9
to
273a675
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UXQA:
- Navigate from the project page to a dashboard, add a filter, click the back button, the filter is not removed. Click the back button again, and you're navigated directly to the project page. Jam.
- When I highlight a time range, clicking "back" does not remove it: Jam
- When I move a highlighted time range to the end of the time series, it gets stuck. I'm unable to move it, and clicking
esc
does not remove it. Jam - Go from a small timerange & grain (e.g. Last 14 Days, Daily) to a large one (e.g. All Time, which flips to Monthly by default). The dashboard reflects the new time grain (Monthly), but the URL does not (Daily).
- In the GitHub Analytics example, there are some commit values that can't be filtered on: Jam. (Maybe this fix belongs in a separate PR.)
I found the above issues from playing with this branch for 5-10 minutes. I will stop there, so, after fixing, please do a thorough round of QA yourself.
// TODO: Remove this in favour of just `getBasePreset` | ||
export function getDefaultExploreState( | ||
name: string, | ||
metricsView: V1MetricsViewSpec, | ||
explore: V1ExploreSpec, | ||
fullTimeRange: V1MetricsViewTimeRangeResponse | undefined, | ||
defaultExplorePreset = getDefaultExplorePreset(explore, fullTimeRange), | ||
initState: Partial<MetricsExplorerEntity>, | ||
): MetricsExplorerEntity { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now, can you update this comment and describe the difference between the "default" explore state and the "init" explore state? (Though we should disentangle the defaults in a follow-up PR)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update the variable names. getFullInitExploreState
for the function and partialInitState
for the argument.
@@ -74,6 +74,7 @@ export class FileArtifact { | |||
readonly fileName: string; | |||
readonly disableAutoSave: boolean; | |||
readonly autoSave: Writable<boolean>; | |||
lastSeenResource: V1Resource; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this needed? This seems redundant to resourceName
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to get all explores that are referring to a metrics view exploreResource?.explore?.state?.validSpec?.metricsView
so just the name is not enough.
// Reset local persisted explore state derived from this metrics view | ||
fileArtifacts | ||
.getResourcesForKind(ResourceKind.Explore) | ||
.forEach((exploreResource) => { | ||
const exploreName = exploreResource?.meta?.name?.name; | ||
if ( | ||
!exploreName || | ||
!exploreResource?.explore?.state?.validSpec?.metricsView || | ||
exploreResource?.explore?.state?.validSpec?.metricsView !== | ||
metricsViewName | ||
) | ||
return; | ||
clearExploreSessionStore(exploreName, undefined); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than clearing the session store here, what if we cleared the session store whenever a user navigates away from the dashboard? Similarly, in Cloud, I'm thinking we should clear the session store whenever the user navigates away from the dashboard (say, to the project homepage).
The session store is primarily meant to facilitate navigation between a dashboard's different views. It's not intended to be a "last viewed state" feature when leaving & returning to a dashboard.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll approve and merge, so we can get this progress into the main
branch and take the follow-ups in smaller PRs. Let's please try to work via more focused, smaller-in-scope PRs. Most of the bullet points in the PR's description could've merited its own dedicated PR.
? FromURLParamViewMap[viewFromUrl] | ||
: (defaultExplorePreset.view ?? | ||
V1ExploreWebView.EXPLORE_WEB_VIEW_UNSPECIFIED); | ||
const explorePresetFromSessionStorage = getExplorePresetForWebView( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be getting ExploreState
from session storage, not ExplorePreset
* 2. If only view param is set then load the params from session storage. | ||
* 3. If view=ttd and `measure` is the only other param set load from session storage. | ||
*/ | ||
export function getExploreStateFromSessionStorage( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd expect to see a call to session storage in this function. Perhaps getExplorePresetForWebView
(where I see the call to session storage actually happens) is an unnecessary additional layer.