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

Implement upload support #384

Merged
merged 2 commits into from
May 22, 2024
Merged

Implement upload support #384

merged 2 commits into from
May 22, 2024

Conversation

jelly
Copy link
Member

@jelly jelly commented Apr 19, 2024

This implements #378

  • Wait for cockpit release with send-acks support and refreshed images for creating tests
  • Implement conflict dialog mockup design from @garrett
  • Pull cockpit-lib-update for cockpit.format_bytes typescript shenanigans
  • Design tweaks
  • Write tests
    • Test upload success
      • Test upload cancel
      • Test upload permission issues
      • Test upload disk full
      • Test multi upload
      • Test progress popover
      • Test file conflict
        • Skip
          • Replace
          • Cancel
          • Skip all
          • Replace all

image

Conflict handling

image

@jelly
Copy link
Member Author

jelly commented Apr 19, 2024

@garrett for debugging the popover I created this patch which mimmicks an upload scenario:

0001-WiP-debug-popover.txt

@jelly
Copy link
Member Author

jelly commented Apr 19, 2024

Suggestion from @mvollmer:

await Dialogs.show() and let Dialogs.close(arg) take an argument to resolve the promise.

@garrett
Copy link
Member

garrett commented Apr 22, 2024

I have an error trying to build this PR:

✘ [ERROR] Could not resolve "cockpit-upload-helper"

    src/upload-button.tsx:37:23:
      37 │ import { upload } from "cockpit-upload-helper";
         ╵                        ~~~~~~~~~~~~~~~~~~~~~~~

  You can mark the path "cockpit-upload-helper" as external to exclude
  it from the bundle, which will remove this error and leave the
  unresolved path in the bundle.

I'd ping you on Matrix, but it seems down at the moment.

@garrett
Copy link
Member

garrett commented Apr 23, 2024

Replace dialog.

Single file:

Upload, replace file, horizontal, single

When there are multiple files:

Upload, replace file, horizontal, multiple

Notes:

  1. Title should wrap if it's too long
  2. Changes are listed side by side, using the width of the modal
  3. (Not shown) ARIA would have labels "Size" and "Modified" for the respective values for new and original files for screenreader support
  4. Replace is a warning button
  5. Skip is now "Keep original" to make it more explicit and tie in with the "original" language above
  6. New and original and replace and keep original are the consistently the same from left to right (so actions mirror details and vice versa)
  7. Date-Time is in the locale setting
  8. Filename is in the title and is slightly bolder
  9. The "also" action of "Apply this action to all conflicting files" specifically says conflicting files instead of just "all files", as it wouldn't replace files that don't conflict.
  10. There's a little more spacing between the "Apply this action..." opt-in and the details above, as the description and details are considered one section and the actions are another (so there's a little more space to add "breathing room" to separate the sections)
  11. Cancel is a link styled button (as it should be)

@garrett
Copy link
Member

garrett commented Apr 23, 2024

Perhaps we should include the filename in the description like this, complete with monospace ("it's from a computer" <samp>) styling?

image

@jelly jelly force-pushed the upload-support branch 2 times, most recently from 639c615 to 458553e Compare April 24, 2024 09:13
src/app.tsx Fixed Show resolved Hide resolved
src/upload-button.tsx Outdated Show resolved Hide resolved
@jelly jelly force-pushed the upload-support branch 3 times, most recently from 6fbea5a to 869836b Compare May 2, 2024 16:52
@jelly jelly force-pushed the upload-support branch 2 times, most recently from 9de2891 to 150b696 Compare May 3, 2024 09:48
@jelly jelly marked this pull request as ready for review May 7, 2024 09:17
Copy link
Member

@allisonkarlitskaya allisonkarlitskaya left a comment

Choose a reason for hiding this comment

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

Random UI idea: since we compute the "will replace" check based on local information, and since we do it in one go before starting any uploads, I wonder if we'd better show a single dialog with the names of all files that would be replaced, instead of an endless series of "and this?" "and this?" "and this?"

src/app.tsx Fixed Show resolved Hide resolved
src/files-folder-view.tsx Show resolved Hide resolved
src/index.d.ts Show resolved Hide resolved
src/upload-button.tsx Show resolved Hide resolved
Comment on lines 193 to 173
if (resolution && applyToAll && resolution.skip)
break;

if (resolution && applyToAll && resolution.replace)
toUploadFiles.push(inputFile);
Copy link
Member

Choose a reason for hiding this comment

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

I feel like that could be restructured like

if (resolution && applyToAll) {
  if (resolution.skip)
    continue;
  push();
} else {
  ... ask ...
}

or so?

src/upload-button.tsx Outdated Show resolved Hide resolved
Comment on lines 200 to 178
for (const file of files) {
if (file.name === inputFile.name) {
Copy link
Member

Choose a reason for hiding this comment

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

The way fsinfo works is that you get a dictionary mapping file names to their attributes. We should keep that data around so that we can just do a dictionary lookup instead of this quadratic looping business...

Copy link
Member Author

Choose a reason for hiding this comment

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

Agreed!

Copy link
Member Author

Choose a reason for hiding this comment

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

As this requires re-architecting the whole state (which I did in a separate PR, let's do it there). This at the moment has more prio.

src/upload-button.tsx Outdated Show resolved Hide resolved
src/upload-button.tsx Show resolved Hide resolved
src/app.tsx Fixed Show fixed Hide fixed
@garrett
Copy link
Member

garrett commented May 16, 2024

Two things:

  • Adjust the conflict dialog to match the mockups
  • Set a width limiter on the modal and make sure it wraps as expected (we also have mockups)

Otherwise, the functionality looked correct for this first-pass PR when I checked yesterday.

Thanks! Please ping me again when the two things have been implemented. Looking forward to landing this soon; we're getting close!

@garrett
Copy link
Member

garrett commented May 16, 2024

I'm working on the sizing of the popover. It's not as straightforward as one might think. (But you know that. 😉 Just confirming what you said in Matrix.)

Copy link
Member

@martinpitt martinpitt left a comment

Choose a reason for hiding this comment

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

Thanks! Great to see this unblocked 👏 I found a bunch of minor issues.

src/app.tsx Outdated Show resolved Hide resolved
src/upload-button.tsx Outdated Show resolved Hide resolved
Comment on lines +140 to +142
if (ref.current) {
ref.current.click();
}
Copy link
Member

Choose a reason for hiding this comment

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

Completely optional: can be shortened to handleClick = ref.current?.click and thus the helper function eliminated altogether.

src/upload-button.tsx Show resolved Hide resolved
src/upload-button.tsx Show resolved Hide resolved
test/check-application Show resolved Hide resolved
test/check-application Show resolved Hide resolved
test/check-application Show resolved Hide resolved
test/check-application Show resolved Hide resolved
src/upload-button.tsx Outdated Show resolved Hide resolved
@jelly
Copy link
Member Author

jelly commented May 21, 2024

And this is now racy... So maybe we should pass files again.

@jelly jelly force-pushed the upload-support branch 2 times, most recently from c978ce4 to b369e20 Compare May 21, 2024 18:38
@jelly jelly requested a review from martinpitt May 22, 2024 07:05
@jelly
Copy link
Member Author

jelly commented May 22, 2024

Copy link
Member

@allisonkarlitskaya allisonkarlitskaya left a comment

Choose a reason for hiding this comment

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

This is starting to look really great now, thanks!

Please see one comment from me. It's possible that I just don't understand this code properly and an explanation is all that's required.

src/upload-button.tsx Show resolved Hide resolved
src/upload-button.tsx Show resolved Hide resolved
src/upload-button.tsx Show resolved Hide resolved
src/upload-button.tsx Show resolved Hide resolved
src/upload-button.tsx Show resolved Hide resolved
Copy link
Member

@allisonkarlitskaya allisonkarlitskaya left a comment

Choose a reason for hiding this comment

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

LGTM! 🎉

src/upload-button.tsx Show resolved Hide resolved
@jelly jelly mentioned this pull request May 22, 2024
14 tasks
Copy link
Member

@martinpitt martinpitt left a comment

Choose a reason for hiding this comment

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

Thanks! Some new/remaining issues, and my previous review still has a few outstanding issues. All of them except the handleClick() elimination are a blocker for me.

src/upload-button.tsx Outdated Show resolved Hide resolved
src/upload-button.tsx Show resolved Hide resolved
src/upload-button.tsx Outdated Show resolved Hide resolved
test/check-application Outdated Show resolved Hide resolved
test/check-application Outdated Show resolved Hide resolved
test/check-application Show resolved Hide resolved
test/check-application Show resolved Hide resolved
@jelly
Copy link
Member Author

jelly commented May 22, 2024

Thanks! Some new/remaining issues, and my previous review still has a few outstanding issues. All of them except the handleClick() elimination are a blocker for me.

Ah, I fixed those but didn't mark as resolve as you might have expected?

@jelly jelly requested a review from martinpitt May 22, 2024 11:02
martinpitt
martinpitt previously approved these changes May 22, 2024
Copy link
Member

@martinpitt martinpitt left a comment

Choose a reason for hiding this comment

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

Right, thanks for your latest push -- that resolves both of my previous reviews, I closed the threads.

Good enough for me -- if you need to push again (like, for Garrett's review or so?), please strengthen the test as below, but not important.

Cheers! 🎉

test/check-application Outdated Show resolved Hide resolved
Comment on lines +146 to +147
const beforeUnloadHandler = (event: BeforeUnloadEvent) => {
event.preventDefault();
Copy link
Contributor

Choose a reason for hiding this comment

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

These 2 added lines are not executed by any test.

event.preventDefault();

// Included for legacy support, e.g. Chrome/Edge < 119
event.returnValue = true;
Copy link
Contributor

Choose a reason for hiding this comment

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

This added line is not executed by any test.

@jelly jelly merged commit 2edf2d7 into cockpit-project:main May 22, 2024
10 of 12 checks passed
@jelly jelly deleted the upload-support branch May 22, 2024 13:53
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

5 participants