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

Use vue-query for offers #2560

Merged
merged 25 commits into from Jul 18, 2022
Merged

Use vue-query for offers #2560

merged 25 commits into from Jul 18, 2022

Conversation

nicksellen
Copy link
Member

@nicksellen nicksellen commented Jul 8, 2022

Switch to using vue-query for offers, as a first scenario of using it for other modules.

Notable points:

  • <ProfilePicture> now accepts a user object or just a user id (so we can use non-enriched offer objects)
    • UPDATE: I reverted that work, so now it only accepts a user object again, but there is a getUserRef utility that can be used
  • it handled the cursor pagination nicely, and knows how to refresh it too (get the first page, and go from there)
  • it automatically handles refreshing after returning to page after being away for a bit
  • I went full-in for composition api and <script setup> - see offers/pages/*.vue files...
  • it's quite easy to bridge data to existing vuex data, see my useCurrentGroupId() thing

TODO:

  • the offers form accepts a status object, but I only implemented the validationErrors bit of it... need to decide whether to map the vue-query status to our existing form, or switch the code to use vue-query-style status... DONE: I mapped it to our existing status object, which was quite seamless
  • think a bit about the query client refetching/invalidating ... DONE: for offers I set staleTime: Infinity, so it relies on websockets or mutation calls to know something has changed, and I avoided duplicate refetches by keeping track of which offers a mutation is working on
  • websocket updates DONE: implemented a new composable to receive websocket events
  • fixup tests
  • move useCurrentGroupId function to group/queries.js
  • rename composables that return refs, e.g. useCurrentUserId -> useCurrentUserIdRef
  • remove TODO comments and offers/delete store commit from boot/socket.js
  • check for other TODOs

Links to related issues

Checklist

  • added a test, or explain why one is not needed/possible...
  • no unrelated changes
  • asked someone for a code review
  • joined #karrot:matrix.org
  • added an entry to CHANGELOG.md (description, pull request link, username(s))
  • tried out on a mobile device (does everything work as expected on a smaller screen?)

@codecov
Copy link

codecov bot commented Jul 12, 2022

Codecov Report

Merging #2560 (6506e6c) into master (0908a6b) will decrease coverage by 1.42%.
The diff coverage is 43.72%.

@@            Coverage Diff             @@
##           master    #2560      +/-   ##
==========================================
- Coverage   52.47%   51.04%   -1.43%     
==========================================
  Files         181      193      +12     
  Lines        4877     5244     +367     
  Branches      822      912      +90     
==========================================
+ Hits         2559     2677     +118     
- Misses       2318     2567     +249     
Impacted Files Coverage Δ
src/activities/api/activities.js 28.84% <0.00%> (-2.41%) ⬇️
src/activities/components/ActivityList.vue 100.00% <ø> (ø)
src/base/routes/main.js 98.30% <ø> (ø)
src/group/datastore/currentGroup.js 57.62% <ø> (ø)
src/locales/index.js 7.21% <0.00%> (-0.65%) ⬇️
src/messages/datastore/latestMessages.js 17.69% <0.00%> (+0.65%) ⬆️
src/offers/datastore/currentOffer.js 23.80% <0.00%> (+13.17%) ⬆️
src/topbar/datastore/breadcrumbs.js 84.37% <0.00%> (+4.96%) ⬆️
src/utils/components/LocaleSelect.vue 100.00% <ø> (ø)
src/utils/composables.js 0.00% <0.00%> (ø)
... and 22 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 641693c...6506e6c. Read the comment docs.

@nicksellen nicksellen requested a review from tiltec July 13, 2022 00:29
@nicksellen nicksellen marked this pull request as ready for review July 13, 2022 10:01
Copy link
Member

@tiltec tiltec left a comment

Choose a reason for hiding this comment

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

Nice, this is a serious change in direction for frontend data handling!

I wonder where to draw the line between local state (to be handled with vue-query) and global state, e.g. currentOffer seems to be somehow global as it also affects the topbar. Is it reasonable to keep this kind of state in vuex (maybe later pinia) instead of the topbar/breadcrumb component having to know about all kinds of queries across Karrot?

src/offers/components/OfferForm.vue Outdated Show resolved Hide resolved
src/offers/components/OfferDetailHeader.vue Show resolved Hide resolved
src/offers/queries.js Outdated Show resolved Hide resolved
src/App.vue Show resolved Hide resolved
src/utils/queryHelpers.js Outdated Show resolved Hide resolved
import { useCurrentGroupIdRef } from '@/group/queries'

// Store the ids we are currently mutating, so we can better decide when to refresh from websocket
const mutatingOfferIds = new Set()
Copy link
Member

Choose a reason for hiding this comment

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

Not sure I fully understand - I guess it shouldn't invalidate the offer while the user is editing it? Or is it about some data race when clicking the "save"/"create" button?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's to avoid extra unneeded queries when receiving websocket updates. Without this logic the websocket update will invalidate the offers query and reload the data, and then the response to the mutation request will also do that, and two requests to the backend will go out. I think some situations like that would get debounced, but in this case it would make two separate requests.

Another option is to rely on the websocket update alone, but I tend to not like to rely on that approach, although I think currently we do in places and not others (depending on who wrote the code :), so maybe we should actually decide on a policy there).

I also looked at just updating the specific offer that is saved/edited/archived in the query (using setQueryData), but for the query it's not always obvious how a given edit might impact all the queries (e.g. when you archive it, it needs to be added to the status=archived query and removed from the status=active one), so I think just invalidating the lot is better.

@nicksellen
Copy link
Member Author

I wonder where to draw the line between local state (to be handled with vue-query) and global state, e.g. currentOffer seems to be somehow global as it also affects the topbar.

a composable (useBlah) could obtain it's data from vue-query data, or vuex/pinia (or other places), so that part is kind of abstracted behind a "composable-interface" - and in that case, it's using the global data from vuex, and using it to make a vue-query query... could also get the offer id from the route params, or have them separated with something to get the current offer id, and then pass it into a plain useOfferQuery in the component...

my sense is that a lot of the global data (from server) could be put into vue-query...

maybe there is still some need for global local state (i.e. not from serve), if it's only a little bit maybe just standalone reactive() objects are fine, with functions to update it...

Is it reasonable to keep this kind of state in vuex (maybe later pinia) instead of the topbar/breadcrumb component having to know about all kinds of queries across Karrot?

at the moment something has to know how to get all the breadcrumb values from somewhere, currently in the breadcrumb datastore... another idea could be that page-level components set the breadcrumbs, so there stops being a single place that has to pull together all the sources, I think that might work quite nicely.

@nicksellen nicksellen merged commit b3fb6b7 into master Jul 18, 2022
@tiltec tiltec deleted the add/vue-query branch August 29, 2022 21:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants