Implement File block#6805
Conversation
|
Tried to check this out and run it. VERY cool work! Very very nice, definitely getting there. A few niggles: Can we make it so you can drag and drop a PDF file directly into the canvas, in addition to on the file block placeholder? It would be nice if the Download button text were editable. Perhaps even that you could toggle off the download button entirely in the sidebar. If you remove the actual link from the button inside the editor, so you can't download from inside the editor but only on the published front-end, then you could make the button clickable to edit, just like the normal Button block. Given that you can edit the text of the link, right now the "Edit" button taking you back to the placeholder feels a little bit jarring. Could you make it so instead of having the layout alignment buttons and an edit button, it has instead text-block-like editing tools? Instead of: You'd have: This would essentially be like a text field with a button. You could write your own text, link, unlink, bold, italic, etc. You'd never be able to go back to the placeholder block from the final state, but that's fine too, and the button would always hold the link. What do you think? I notice by the way that if you edit the link, you're typing in reverse :) — but I'll bet that's what you refer to in the remaining bullet.
We probably don't need these, but nice idea otherwise! Very cool work, thanks for working on this, and keep up he good work! |
|
Thanks for the review, @jasmussen!
If so, it is already supposed to be working. You might be seeing a bug. Could you give me some more details so I can reproduce it?
Sure! We could do that.
Hmm, I thought about this too. At one point I even considered a hybrid approach:
My main concern is that we’d confuse the user’s mental model of where the “source of truth” for the file link is. Since choosing a file from the placeholder sets both links, you can reasonably assume that both links will change if you choose another file from the same interface: But when you introduce a second way to change the link, it’s harder to tell what’s going to happen. If only the text link were to change, it would become hard to tell that the text link and button link are out of sync. On the other hand, if both links were to change, it would break the expectation of the standard rich text UI: Is this a tradeoff we are willing to take? Let me know what you think 🙂 |
Those are the wide and full-width alignment options, which do not show unless your theme declares support for them, since those kinds of alignments extend out of the standard content width and may not look right depending on the theme. Since Gutenberg is so new, there are very few themes that have declared support for those alignment types, so most of the time you will only see those options if you use a custom child theme which has declared support for them. |
|
@SuperGeniusZeb Oh I see, that makes sense now. Thank you! |
Placeholder text state was not properly updating when uploading a file from the media placeholder.
|
Very nice work! Here's a GIF of it: Experience wise, this seems to behave as we've discussed, and given the paradigms Gutenberg works with, this seems like it solves the task at hand:
For the scope of this task, 👍 👍, I think this is cool! Nice work. Did you include/merge the work from master that unifies the placeholder block? At some point in the future, as a separate project to this, I imagine that we'll want to take a look at the media library in WordPress in general. In doing so, there will likely also be an opportunity to look at how the placeholder block can work. For example it would be nice if we could show part of the media library itself inside the placeholder block, and allow you to simply drag into it there, and then insert as file block or insert as plaintext link. But that's something to consider for the future. |
|
@jasmussen Thank you for all your guidance, and the cool gif! There are so many possibilities with the Gutenberg framework, and I'm excited to see how the UX will evolve. Hope I'll have a chance to contribute more.
Yes. The code is a lot cleaner thanks to that. And there's another modification in the works (#6957), so if that gets merged in first I'll get to delete a few more lines 🙂 |
| // the document.activeElement at the moment when the copy event fires. | ||
| // This causes documentHasSelection() in the copy-handler component to | ||
| // mistakenly override the ClipboardButton, and copy a serialized string | ||
| // of the current block instead. |
There was a problem hiding this comment.
Thanks for the detailed comment, explaining why do we have the workaround.
There was a problem hiding this comment.
One problem in Safari, though, is that the while block (<!-- wp:file {"href":…) ends up in the clipboard.
There was a problem hiding this comment.
Ok, it looks like this workaround hadn't fixed the Safari bug completely. I did some testing and narrowed down the repro condition a bit. My workaround seems to be effective for pre-existing posts (i.e. posts that were already saved when the page loaded), but not for new posts. Not sure what's going on, but that's a start... I'll have to look into it further.
| getBlobByURL( href ) | ||
| .then( ( file ) => { | ||
| editorMediaUpload( { | ||
| allowedType: '*', |
There was a problem hiding this comment.
Just to make sure I understand correctly, once #6968 gets in we will feed the list if types here?
There was a problem hiding this comment.
No, that allowedType is being used for limiting the files to a suggested file type, similar to the accept attribute of an <input type="file">. The naming is very confusing right now. I want to rename that to accept (and maybe enhance it to take comma-separated and file extension arguments like the actual <input accept>) in a separate PR once this and #6968 are merged in.
There was a problem hiding this comment.
From #5462:
WordPress also supports a number of filetypes that aren't media, such as pdf, doc, and others. See full list here: https://codex.wordpress.org/Uploading_Files
I don't think that editorMediaUpload in the current shape is what we really want to use in here, because non-media files can be uploaded, too. It seems like we need to refactor the existing method or add a more generic one which editorMediaUpload uses behind the scenes.
There was a problem hiding this comment.
Hmm, I was under the impression that the "media" in editorMediaUpload and mediaUpload is being used in the broader sense of the word, and not to mean "images, audio, and video". This is in line with how WordPress uses the term — every kind of uploadable file, including pdf and other documents, are uploaded to the "Media Library", and are retrieved via the media endpoint.
Even /edit-post/hooks/blocks/media-upload, which includes specific logic for when gallery == true, seems generic enough for any kind of file. Is there a reason we want to keep editorMediaUpload specifically for image/audio/video files?
There was a problem hiding this comment.
I posted a separate issue for the allowedType problem: #7155
| } | ||
| } | ||
|
|
||
| isBlobURL( url = '' ) { |
There was a problem hiding this comment.
Would it make sense to move this one to utils, like the other blob functions? At which point would you split out utils/blob?
There was a problem hiding this comment.
Yes, I think so. But in a separate PR, because I think I saw a couple of other places in the codebase where we’re doing blob url detection, and I’d want to change them all at once.
| <a | ||
| href={ textLinkHref } | ||
| target={ openInNewWindow } | ||
| rel={ openInNewWindow ? 'noreferrer noopener' : false } |
There was a problem hiding this comment.
I think it’s because noopener doesn’t work in IE/Edge. (see also: #6186)
|
|
||
| // edit component has its own attributes in the state so it can be edited | ||
| // without setting the actual values outside of the edit UI | ||
| this.state = { |
There was a problem hiding this comment.
I am not sure I follow the reason we keep the attributes in the state, too. What do we gain?
There was a problem hiding this comment.
You're right, I've cleaned them out.
core-blocks/file/edit.js
Outdated
|
|
||
| if ( id !== undefined ) { | ||
| // Get Attachment Page URL | ||
| wp.apiRequest( { |
There was a problem hiding this comment.
I didn't realize we had that! Cool. I put that in place, however it turns out that the snapshot test helper for our components (blockEditRender()) isn't equipped to inject context in order for it to work. I've made a patch for it and I'll propose it in a separate PR, but not sure if my implementation is good. Anyway, I'm going to remove the snapshot test for this temporarily.
core-blocks/file/edit.js
Outdated
| } ) | ||
| .then( | ||
| ( result ) => { | ||
| this.setState( { attachmentPage: result.link } ); |
There was a problem hiding this comment.
Would the setState work correctly if the component hasn't been rendered yet?
There was a problem hiding this comment.
Good point. Should've been in componentDidMount().
|
|
||
| componentDidUpdate( prevProps ) { | ||
| // Reset copy confirmation state when block is deselected | ||
| if ( prevProps.isSelected && ! this.props.isSelected ) { |
|
|
||
| componentDidUpdate( prevProps ) { | ||
| if ( prevProps.text !== this.props.text ) { | ||
| this.setState( { showPlaceholder: ! this.props.text } ); |
There was a problem hiding this comment.
What are the trade-offs of using state here vs. just using the text prop for rendering logic?
There was a problem hiding this comment.
Since I'm resorting to use a content-editable here, this is not a "controlled" component and therefore the text prop isn't updated on each keystroke.
Requires a modification in the `blockEditRender()` test helper to inject context, or else the withAPIData HOC won’t work.
…file-block # Conflicts: # utils/mediaupload.js
core-blocks/file/edit.js
Outdated
| this.setState( { | ||
| attachmentPage: media.link, | ||
| } ); | ||
| }, this.props.media.get /* refetch attachment page url */ ); |
There was a problem hiding this comment.
Does setAttributes accept a second argument? When is this.props.media.get called?
There was a problem hiding this comment.
Totally assumed setAttributes took the same arguments as setState! I meant it as a callback. Thank you.
core-blocks/file/edit.js
Outdated
|
|
||
| export default compose( [ | ||
| withAPIData( ( props ) => ( { | ||
| media: `/wp/v2/media/${ props.attributes.id }`, |
There was a problem hiding this comment.
export default compose( [
withSelect( ( select, props ) => {
const { getMedia } = select( 'core' );
return {
image: getMedia( props.attributes.id ), // not sure if getMedia handles undefined values
};
} ),
withNotices,
] )( FileEdit );There was a problem hiding this comment.
Thank you, I wasn't aware of this. I'll look into it.
| }; | ||
| const isAllowedType = ( fileType ) => startsWith( fileType, `${ allowedType }/` ); | ||
| const isAllowedType = ( fileType ) => { | ||
| return ( allowedType === '*' ) || startsWith( fileType, `${ allowedType }/` ); |
There was a problem hiding this comment.
Should it rather list all allowed file types by allowing the array format?
There was a problem hiding this comment.
Yes, I think it should accept arrays, as well as have a more predictable syntax. More on that here: #7155
I opted for a wildcard here as a stop-gap measure, or else we'd have something like ['audio', 'application', 'video', 'text', 'image', 'font'] which I think is more error-prone for consumers.
|
By the way, here are some of the RichText issues that caused me to resort to a Now that I've sorted through the repro conditions and workarounds for them, I feel like #7591 is the only "blocker" for using a RichText here. If that is addressed, I think we could safely replace the contenteditable. |









Closes #5462
Description
Implements a File block with the following features:
both Media Library files and external URLsonly Media Library files(?) Background Color and Text Color options in sidebarHow has this been tested?
Try the features above.
Screenshots
Things I don't plan on including in this PR (but should be done eventually)
Integrate error messaging using Fix max upload size error message #4203done, thanks to Try unifying all the media blocks placeholder under a unique component #6820Add allowed mime type checking to Fix max upload size error message #4203submitted separately as Check allowed mime types before uploading media #6968Refactor the misplaced CSS in core-blocks/image/editor.scssdone, thanks to Try unifying all the media blocks placeholder under a unique component #6820Copy URL button may not work correctly in Safarisubmitted separately as Make ClipboardButton inside a block work correctly in Safari #7106