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

fix: upload list pagination headers #1739

Merged
merged 20 commits into from
Aug 30, 2022
Merged

Conversation

alanshaw
Copy link
Member

@alanshaw alanshaw commented Aug 15, 2022

  1. Fixes Link headers to include required pagination variables.
  2. Adds "first" and "last" URLs to link header so pagination can operate properly.
  3. Catches DB range error and re-throws it with the appropriate HTTP status 416.
  4. Adds indexes on the uploads table for list items.
  5. Fixes website to allow pagination above 1,000. Only loads the current page instead of everything.
  6. Removes the search box - it only filters the current page so is almost useless. Needs proper integration with server side API.

Visual preview:

Screenshot 2022-08-17 at 17 32 36

Note new "Request ID" column for pinned items:

Screenshot 2022-08-17 at 17 32 29

resolves #1610
resolves #1501
resolves #1362
resolves #1737

@alanshaw alanshaw marked this pull request as ready for review August 15, 2022 15:52
@github-actions
Copy link
Contributor

github-actions bot commented Aug 16, 2022

@joshJarr
Copy link
Contributor

joshJarr commented Aug 16, 2022

Nice! Code looks good and the BE changes are ace, I found a few issues with the FE code:

  1. I can not unselect uploads if I navigate to a new page, and upon navigating back the upload does not appear selected, but If I click delete, it's removed.
    Steps to replicate:

    • On the uploads table the delete button is disabled until something is selected
    • Select a (or many) uploads (checkbox), the delete button becomes enabled
    • Navigate to the next page, the delete button remains enabled
    • Navigate back to the previous page, the delete button is enabled but the upload is not visually selected.

    Expected:

    • Either selection is wiped upon navigating to a new page, or the selection is persisted when navigating back
    • If selection is wiped, the delete button should become disabled.

    Actual

    • Selection is not visually persisted on the table
    • Delete button is active, and clicking will delete the previously selected item.

    Aug-16-2022 10-50-40 (can't upload MP4, give me a shout if you want a higher res or a quick demo!)

We could just wipe the selection upon navigating away.


  1. Total amounts of uploads/pins are incorrect on the tabs, only the selected result length is shown.
    A quick win here could be as simple as removing the total number?

Screenshot 2022-08-16 at 11 17 41


  1. Pins and Uploads are broken and appear on the same table with table columns also breaking.
    • Hopping between the two tables I find they sometimes stack together resulting in the screenshot below
      Screenshot 2022-08-16 at 11 19 47

There's a few more minor issues here:
- Sorting is also persisted through the upload & pin tabs.
- When I hit the http://localhost:4000/account/?table=pinned URL I am directed to the uploads table no pin, despite having pings

I think the table and pagination components are tightly coupled and need a bit of refactoring in order to separate pins and uploads, but reuse the same components. @flea89 has worked on decoupling them from the table here: #1700 and in https://github.com/web3-storage/web3.storage/pull/1699/files

I think the FE code here may require a bit more work, but the BE aspect is perfect! Would it make sense to split this into two PRs so that the Link URL, error handling changes & indexes aren't blocked by the UI?

Thanks!

Copy link
Contributor

@joshJarr joshJarr left a comment

Choose a reason for hiding this comment

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

Couple of questions on the API/DB side, but besides these all look good.
A few FE issues, is the plan to split these out into a separate ticket or to tackle 'em all here?

@@ -109,7 +109,6 @@ const FileUploader = ({ className = '', content, uploadModalState, background })
}}
icon={<FolderIcon />}
dragAreaText={content.drop_prompt}
maxFiles={3}
Copy link
Contributor

Choose a reason for hiding this comment

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

Has this been dropped for testing purposes? Or is it cool to no longer restrict file uploads?

Copy link
Member Author

Choose a reason for hiding this comment

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

There's no error feedback in the UI and nothing that says only 3 files at a time. I don't know why we'd restrict files here...

Copy link
Contributor

@joshJarr joshJarr Aug 16, 2022

Choose a reason for hiding this comment

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

Yep, that's a great point - was just double checking

getUploads();
}
}, [fetchDate, getUploads, isFetchingUploads]);
getUploads({ size: itemsPerPage, page, sortBy, sortOrder });
Copy link
Contributor

Choose a reason for hiding this comment

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

Might be good to reset the selectedFiles here too, so that hidden selections aren't stored in that state.

query = query.gte('inserted_at', opts.after)
async listUploads (userId, pageRequest) {
let query
if (pageRequest.type === DATE_TIME_PAGE_REQUEST) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I find the Date time pagination a little tricky,
Say I had two or more records with the exact same date time, wouldn't this break pagination & it would miss some results?
Super edge-casey, but am keen to understand why filtering by datetime is necessary, is it purely for the existing UI?

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 required by the pinning service API https://ipfs.github.io/pinning-services-api-spec/#section/Pagination-and-filtering and that's what was originally implemented.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ahh ok, in which case should this also be replicated in listPsaPinRequests?

Copy link
Member Author

Choose a reason for hiding this comment

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

listPsaPinRequests serves the PSA (GET /pins) primarily. It's now date ordered explicitly (and you can't change the sort field or direction from the UI). So, I've left it mostly as is and dealt with the "page number pagination" at the API handler level instead. If we want to enable that UX for the PSA table then yes we can probably refactor to use this pattern also.

try {
data = await env.db.listUploads(request.auth.user._id, pageRequest)
} catch (err) {
if (err.code === 'RANGE_NOT_SATISFIABLE_ERROR_DB') {
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe reuse RangeNotSatisfiableDBError.CODE here

console.error(e)
throw new HTTPError('No pinning resources found for user', 404)
} catch (err) {
if (err.code === 'RANGE_NOT_SATISFIABLE_ERROR_DB') {
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe reuse RangeNotSatisfiableDBError.CODE here

Copy link
Contributor

Choose a reason for hiding this comment

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

Great point! I could make a constant in the API package so that there's less dependancy on the db package, or import it over from the db package. am struggling to weight up which would be best!

*/
export async function deletePinRequest(requestid) {
const tokens = await getTokens();
if (!tokens[0]) {
Copy link
Contributor

Choose a reason for hiding this comment

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

A bit confusing; could we use tokens.length > 0?

Copy link
Contributor

Choose a reason for hiding this comment

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

Possibly, but with this we're checking if tokens[0] is truthy, as it could be null.
Tokens could be [null, null] and .length would be 2

@joshJarr
Copy link
Contributor

LGTM now conflicts are resolved, lots of changes here so would be great to get a second approval, @orvn @olizilla @vasco-santos are either you guys available to take a look?
@e-schneid would be good if you could take a quick look too, just to ensure I've not caused havoc merging the upload table changes.
Thanks!

@joshJarr
Copy link
Contributor

Merging this since it resolves a fair few issues that are currently live, but if anyone else has any feedback feel free to leave it and will address in a separate PR.
Thanks!

@alanshaw
Copy link
Member Author

alanshaw commented Sep 5, 2022

@joshJarr thanks for finishing this!

Did the indexes get applied in prod? I just realised I should have written a migration for applying them.

ref https://github.com/web3-storage/web3.storage/pull/1739/files#diff-c387c1cfe9b20b289a2e4b668a020d576f0c3acda4c9379bef0a7c04718ecc11

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants