Skip to content
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

Persist dashboard filters in query params #3406

Merged
merged 26 commits into from
Aug 15, 2023

Conversation

DeNic0la
Copy link
Collaborator

@DeNic0la DeNic0la commented Apr 9, 2023

The task of Dashboard improvements #3155
"Persist the filters in the URL, for sharing filtered lists and so that when navigating to an activity and back, the same filters are restored"

Dashboard component stores Category and Responsible in Url params.

Open Questions:
The filter values are stored in the /categories/330a052f5d2d - format, is that okay or is there a better Key?

What is the filter value period and how is it written read? I found no way to set that in the UI.

@pmattmann
Copy link
Member

pmattmann commented Apr 9, 2023

Dashboard component stores Category and Responsible in Url params.

Open Questions: The filter values are stored in the /categories/330a052f5d2d - format, is that okay or is there a better Key?

What is the filter value period and how is it written read? I found no way to set that in the UI.

Filter values
In the backend it would certainly be your suggested format /categories/330a052f5d2d.
In the frontend, in user-facing URLs (which appear in the browser's address bar), usually we use the ID only.
Example: https://app.ecamp3.ch/camps/882ef43cb421/SoLa/dashboard

Could be something like:

?categories[0]=330a052f5d2d&categories[1]882ef43cb421
?categories[]=330a052f5d2d&categories[]882ef43cb421
?categories=330a052f5d2d,882ef43cb421

Period
The Period-Filter is only displayed, if you have multiple periods (sub-camps, e.g. Vorweekend, Hauptlager, Nach-Tag etc.).
Go to "Admin" and add a second Period.

@DeNic0la DeNic0la marked this pull request as ready for review April 13, 2023 17:30
@DeNic0la
Copy link
Collaborator Author

DeNic0la commented Apr 13, 2023

Filter values In the backend it would certainly be your suggested format /categories/330a052f5d2d. In the frontend, in user-facing URLs (which appear in the browser's address bar), usually we use the ID only.

added Helper as Mixin (frontend/src/mixins/formatHalHelperMixin.js) to convert uri to id
(not sure if a mixin is the way to go)

Could be something like: [...]

I used the Vue-router default implementation, its similar so i hope that's fine

Period [...]

Did that

I added a Test for the functionality I added, doesn't test the entire class tho.

@usu
Copy link
Member

usu commented May 1, 2023

added Helper as Mixin (frontend/src/mixins/formatHalHelperMixin.js) to convert uri to id
(not sure if a mixin is the way to go)

No need for this to be a mixin. You can implement this has a simple helper class and then just export the 2 functions (see frontend/src/helpers/vCalendarDragAndDrop.js for example).

Mixin is only needed, if you need access to the Vue component context.

Copy link
Member

@usu usu left a comment

Choose a reason for hiding this comment

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

Generally, looks good to me.

  • Refactor mixin to helper would be nice (see my other comment)
  • Any chance we can improve the error handling in beforeMount, when invalid/outdated data is presented (e.g. an ID is presented that was deleted in the meantime)? In my opinion we could silently ignore such data. At the moment, the console spits out some errors and the Select is not shown due to the errors.

image

validate query params before writing them to used filter values
update unittests
add jsdoc typing
@DeNic0la DeNic0la requested a review from usu June 5, 2023 03:28
@usu usu added the deploy! Creates a feature branch deployment for this PR label Jun 10, 2023
@github-actions
Copy link

github-actions bot commented Jun 10, 2023

Feature branch deployment currently inactive.

If the PR is still open, you can add the deploy! label to this PR to trigger a feature branch deployment.

Copy link
Member

@usu usu left a comment

Choose a reason for hiding this comment

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

Nice, looks good to me. From my side good to merge.

Don't know why the end-to-end tests fail though. I have triggered a re-run to see if it was just a glitch.

])

this.loggedInUser = loggedInUser
// Once camp data is loaded validate and map values from url param to filter
await Promise.all([
Copy link
Member

Choose a reason for hiding this comment

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

Is there a specific reason we need 2 separate calls for Promise.all? Or could we put all the loading promises into one Promise.all and await this one?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Nope, that's leftover code from when I tried some performance optimisation.

@usu usu requested a review from carlobeltrame June 10, 2023 22:55
@usu
Copy link
Member

usu commented Jun 11, 2023

Don't know why the end-to-end tests fail though. I have triggered a re-run to see if it was just a glitch.

I found the reason for the failing check and could reproduce locally (see screen recording incl. console output). When I open the dashboard and immediately navigate to a different page (e.g. Print as in the e2e-tests), this triggers a $router.push, but navigation is not immediate (depending on which components need to be loaded; print is one of the pages that takes a bit longer to load).

In parallel, Dashboard is loading data and eventually calls persistRouterState which calls $router.replace. This last calls replaces/aborts the previous $router.push. Hence, the user never arrives at the print page.

Don't have an immediate good solution how to resolve this. Ideas very welcome.

Screen.Recording.2023-06-11.at.09.57.29.mov

@DeNic0la
Copy link
Collaborator Author

Sorry i didnt update sooner, i figured it out too but I kinda have some trouble running the project localy. I was working on a way to fix that for some time but I had various problems locally.

@DeNic0la DeNic0la changed the title persist dashboard filters in query params [WIP] persist dashboard filters in query params Jun 11, 2023
* Is True until the Component gets unmounted or there is a Navigation to another page
*/
syncUrlQuerActive() {
return this.isActive && this.$router.currentRoute.name === 'camp/dashboard'
Copy link
Member

Choose a reason for hiding this comment

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

This didn't work for me. this.$router.currentRoute still equals to the camp/dashboard route, even after the Print button was clicked. It seems that currentRoute is only updated, once the navigation is completely finished.

What we probably would need is to query for a pending navigation route. In vue-router there's no built-in capability to do this. It seems to be implementable with Navigation Guards, however, might not be trivial to catch all the edge cases (see vuejs/vue-router#2012 (comment)).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I see your point and used window.history.replaceState - this doesn't overwrite pending navigations.
This could cause problems with mobile devices tho.

# Conflicts:
#	frontend/src/views/camp/Dashboard.vue
@DeNic0la DeNic0la changed the title [WIP] persist dashboard filters in query params Persist dashboard filters in query params Aug 1, 2023
@DeNic0la DeNic0la temporarily deployed to feature-branch August 1, 2023 15:47 — with GitHub Actions Inactive
@DeNic0la DeNic0la temporarily deployed to feature-branch August 2, 2023 20:18 — with GitHub Actions Inactive
@DeNic0la DeNic0la temporarily deployed to feature-branch August 3, 2023 00:14 — with GitHub Actions Inactive
@DeNic0la DeNic0la temporarily deployed to feature-branch August 3, 2023 00:16 — with GitHub Actions Inactive
@DeNic0la DeNic0la temporarily deployed to feature-branch August 3, 2023 00:37 — with GitHub Actions Inactive
@DeNic0la DeNic0la temporarily deployed to feature-branch August 6, 2023 13:59 — with GitHub Actions Inactive
@DeNic0la DeNic0la temporarily deployed to feature-branch August 6, 2023 14:20 — with GitHub Actions Inactive
@DeNic0la DeNic0la temporarily deployed to feature-branch August 6, 2023 14:24 — with GitHub Actions Inactive
@DeNic0la
Copy link
Collaborator Author

DeNic0la commented Aug 6, 2023

It's all done and tested

The failing check is an API Lint - I have no idea why it's failing but it's optional so I should be good?

A Review would be appreciated @carlobeltrame or @pmattmann
Maybe you want to redo your review @usu

@BacLuc
Copy link
Contributor

BacLuc commented Aug 7, 2023

It's all done and tested

The failing check is an API Lint - I have no idea why it's failing but it's optional so I should be good?

A Review would be appreciated @carlobeltrame or @pmattmann Maybe you want to redo your review @usu

Yes, the psalm linter fails since a little more than a week.
The fixes are already here (#3638 and #3672 ), they just need review

Copy link
Member

@usu usu left a comment

Choose a reason for hiding this comment

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

Nice, looks good to me. Thanks for the good test coverage 👍

persistRouterState() {
const query = transformValuesToHalId(this.filter)
if (filterAndQueryAreEqual(query, this.$route.query)) return
this.$router.replace({ query }).catch((err) => console.warn(err))
Copy link
Member

Choose a reason for hiding this comment

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

So you got it running in the end with $router.replace without the need to use window.history?
Cool. What was the secret trick to make it work?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

the fix is on line 394, I implemented an equals check that doesn't trigger as easily. The issue is that the filter contains values such as null or [] which should be equal to undefined in the route.query but the check before did not take that into account. Also the route.query doesn't provide an array if there is only one value. The window.history fix just doesn't refresh navigation. But now it may refresh navigation because it's only called when there is a real value change.

Copy link
Member

Choose a reason for hiding this comment

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

Ah I see. Thanks for clarifying

@usu usu requested a review from manuelmeister August 14, 2023 07:30
@pmattmann pmattmann merged commit 2b22502 into ecamp:devel Aug 15, 2023
20 of 21 checks passed
@carlobeltrame carlobeltrame mentioned this pull request Aug 15, 2023
5 tasks
@pmattmann pmattmann mentioned this pull request Aug 15, 2023
@DeNic0la DeNic0la deleted the dashboard-filters-in-url-#3155 branch August 15, 2023 12:04
@DeNic0la DeNic0la mentioned this pull request Aug 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
deploy! Creates a feature branch deployment for this PR
Projects
Development

Successfully merging this pull request may close these issues.

4 participants