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 file management #2022

Merged
merged 11 commits into from
Jul 5, 2023
Merged

Implement file management #2022

merged 11 commits into from
Jul 5, 2023

Conversation

jonatanklosko
Copy link
Member

@jonatanklosko jonatanklosko commented Jun 29, 2023

First steps towards #1604. There is quite a lot of changes already, so I'm opening the PR early (or perhaps we just break it down into multiple PRs).

Overview

This adds a new sidebar with notebook files, which can either be stored (and managed) alongside the notebook in files/ directory as attachments or point to some global file or URL as links. Information about those is stored in the .livemd file. When importing a notebook from URL we know that we need to download all of its attachments.

We decided to unify this with images, so now inserting an image automatically adds an attachment and the urls are ![](files/image.jpeg) (rather than images/). We keep resolving images/ for backward compatibility for now.

UI

Expand

Sidebar

image

Adding from file

image

Adding from URL

image

Adding other unlisted files from files/

image

Deleting a file

image

Copying link to notebook files

image

Next steps

Primary

  • support multi-part download for large files
  • reading files using Kino API
  • links to files need to be explicitly allowed (as secrets) and we need to sign what they are
  • make sure files work with apps
  • look for image/* image urls on .livemd import and add deprecation warning

Additions

  • adding file via upload
  • global drag and drop
  • option to open/download a file directly from the sidebar
  • indicator for long file operations

@github-actions
Copy link

github-actions bot commented Jun 29, 2023

Uffizzi Preview deployment-30117 was deleted.

Comment on lines +33 to +34
hash = :crypto.hash(:sha256, bucket_url) |> Base.url_encode64(padding: false)
id = "s3-#{hash}"
Copy link
Member Author

Choose a reason for hiding this comment

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

Currently we are using random ids generated when the file system is added, which is fine for settings (local). However, to persist a file link in a notebook, we need a deterministic file system id, so if multiple Livebook users use the same S3 bucket, the file link is exported/imported as expected.

I did the hash so that the id is fixed length and this way it also has a predictable character set. Also, even though buckets generally need authorisation, not listing the URL explicitly sounds like an advantage to me.

I considered a second field/function like :public_id, but having both random :id and the :public_id is confusing, especially that both should be unique anyway. Also, having a deterministic :id is what we do for hubs too, so it's better for consistency. To avoid breaking existing settings I added a migration with more details.

Copy link
Contributor

Choose a reason for hiding this comment

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

Looks good to me. I also wonder if the ID should be the bucket itself but this at least avoids us from leaking bucket information.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, I would still like base64 encode the bucket URL to avoid weird characters in the ID, but not leaking sounds preferable anyway.

Comment on lines +1186 to +1193
options: [
%{
name: "delete_cells",
label: "Delete all cells in this section",
default: first_section?,
disabled: first_section?
}
]
Copy link
Member Author

Choose a reason for hiding this comment

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

When deleting a section we ask the user "Delete all cells in this section" and to do that we used a whole separate URL and modal. Now that we needed a similar option when deleting a file, I added this to the generic confirm we have, and now that it's all in Elixir it was actually very little code :D

@josevalim
Copy link
Contributor

This looks very exciting! Here are some visual nitpicks (since I can't yet do a code review):

  1. Move the icon folder in the sidebar before the deployments or the secrets one (don't separate deployments and runtime) (we are running out of sidebar space and we will at least have one other sidebar icon in the future but that's a separate discussion :D)

  2. I still think the names (create a link / copy to notebook files) are not clear. First we definitely need some brief explanation somewhere: "Files are either links to existing resources or hard copies into the notebook files folder". Another idea is to break the listing by type, keeping all links and all hard copies separate. I also think we can have slightly checkbox names depending on the page:

  • For files, we say: "Store only file location" | "Copy file contents to the notebook files/ folder"
  • For URLs, we say: "Store only URL location" | "Download URL contents to the notebook files/ folder"

Finally, I am not sure if we should use the "link" icon for file links. It is typically associated with URLs/web. I would expect something closer to the icons below (but maybe i am just old :D):

image

@jonatanklosko
Copy link
Member Author

jonatanklosko commented Jun 30, 2023

Updates

image

image

image

@zachallaun
Copy link
Contributor

zachallaun commented Jul 1, 2023

I have some unasked-for UI/description suggestions from the perspective of a user (please feel free to disregard!)

  • Without some kind of formatting, usage of “files/ directory“ in a sentence is a bit confusing and looks sort of like a typo. I would just drop the trailing slash and use “files directory”

  • Files pane tooltip suggestion:

    Manage files used by the notebook. Files are either links to existing resources or hard copies stored in a notebook files directory.

  • When adding a file:

    • Single checkbox with a help tooltip instead of radio buttons
    • For a local file: “Copy”, with tooltip “Store a copy in the notebook files directory”
    • For a URL: “Download”, with tooltip “Download once and store a copy in the notebook files directory”

@josevalim
Copy link
Contributor

I would stick with radio. The issue with checkboxes is that it doesn’t tell you what happens when it is unchecked. Radios make that clear.

agreed on “files/“, we should tag it as code (my preference) or remove the slash. :)

@zachallaun
Copy link
Contributor

I would stick with radio. The issue with checkboxes is that it doesn’t tell you what happens when it is unchecked. Radios make that clear.

True! This may just be me, but I'd still simplify the labels pretty dramatically to something like "Link to file / Copy file" and "Link to URL / Download file" because I think that folks already have good intuition about what those things mean and too much description makes people question that intuition instead of clarifying it.

lib/livebook/migration.ex Outdated Show resolved Hide resolved
end

@impl true
def handle_event("yo", %{}, socket) do
Copy link
Contributor

Choose a reason for hiding this comment

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

Yo!

Copy link
Contributor

@josevalim josevalim left a comment

Choose a reason for hiding this comment

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

LGTM! Just very minor nitpicks. Something else we should add to the TODO-list is the option to open/download a file directly from the sidebar? For URLs it is easy but for files it can be a bit tricky.

@josevalim
Copy link
Contributor

I have also added this issue, which is related to future work: #2027

Just so we don't forget. :)

Co-authored-by: José Valim <jose.valim@dashbit.co>
@jonatanklosko
Copy link
Member Author

Something else we should add to the TODO-list is the option to open/download a file directly from the sidebar

Sounds good, in the future we may also want to have an zip export to download notebook with all the files.

@jonatanklosko
Copy link
Member Author

FTR automatic conversion script that will be useful for people with large notebook collections: convert_notebook_images.exs.

Copy link
Contributor

@josevalim josevalim left a comment

Choose a reason for hiding this comment

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

We are to branch and merge :)

@jonatanklosko jonatanklosko merged commit ede80fc into main Jul 5, 2023
7 checks passed
@jonatanklosko jonatanklosko deleted the jk-files branch July 5, 2023 18:01
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

3 participants