Problem/Motivation
The Media Library field widget has no way of creating media inline. Currently, the widget suggests that users open a new tab or window, create media, then come back to the view to select it. This is not an ideal user experience.
Proposed resolution
We should add the ability to upload media in the media library modal, and use that media for the widget.
The upload functionality will need to validate the cardinality of the field, as well handle uploads that apply to multiple media types. For instance, if a field accepts "Image" and "Animated GIF" media, and you upload a .gif file, the upload form will need to prompt the user to see what type they want to create. This won't be common on most sites, but we need to support the flow.
The current patch handles file validation and media type resolution already, yay!
For a recent recording of the upload form's functionality, please watch https://www.youtube.com/watch?v=AYL0ujucjtY
Remaining tasks
Review the patch, from a code and UX perspective.
User interface changes
The Media Library modal now has an "Add media" link, if the current user has access to create media of a type that the field allows.
API changes
None.
Data model changes
None.
| Comment | File | Size | Author |
|---|---|---|---|
| #116 | interdiff-2938116-115-116.txt | 6.22 KB | samuel.mortenson |
| #116 | 2938116-116.patch | 55.56 KB | samuel.mortenson |
| #89 | media-library-mockup-upload.png | 119.15 KB | samuel.mortenson |
Comments
Comment #2
phenaproximaOh, let the trumpets ring out a major +1 for this! What brilliant work. Thank you, @samuel.mortenson!
In my experience, this kind of thing tends to cause a lot of weird political bikeshedding. I suggest we remove the local action from the patch for now, then re-add it in a follow-up.
Other than that...
This feature will form the basis for integration between media entities and content which references media entities, as outlined in #2831940-151: Create file field widget on top of media entity. So this bulk upload form partially supersedes #2831940: Create file field widget on top of media entity.
Let's also open a follow-up to integrate this with a field widget (i.e., the other half of the code in #2831940-144: Create file field widget on top of media entity.)
I'd also like to add this issue (plus the aforementioned follow-up) to #2825215: Media initiative: Roadmap as official blockers before Media can be included in Standard.
To keep this patch simple and easier to review, that might also be worth moving to a follow-up.
Comment #3
phenaproximaAlso, for easier review, let's add some screenshots to the IS.
Comment #4
phenaproximaAdded #2938123: [PP-1] Streamline media creation form presented during bulk upload to address the creation of a "minimal" form mode for media items. So that task is now out of this patch's scope.
Also added #2938121: Expose a local action to bulk upload media items to add the local action for bulk upload. So this patch will no longer introduce any UI changes (although it does introduce a new, isolated UI; not sure if that counts).
Comment #5
samuel.mortensonRemoved the action per #2, added screenshots.
Comment #6
samuel.mortensonComment #7
phenaproximaGave the patch a read-through. Overall this code is clean, well-organized, and exceptionally clear when you consider what it's accomplishing.
Bravo!
The doc comment should probably mention that the media entities can only be created from uploaded files.
Nice idea!
This seems a bit heavy for a constructor. Let's move this to a helper method so that $this->types is populated on-demand.
'case NULL' seems a bit odd. Maybe this should simply be the default case instead?
Nit: We can remove all these break statements in favor of directly returning the result of the helper method.
s/process/progress. And maybe this should be rephrased to something like "...the current progress of the bulk upload."
This logic is a bit opaque, can there be a comment explaining it a little?
Nit: You can use
$this->elementInfo->getInfoProperty('managed_file', '#process'), rather than retrieve the whole element info array. :)The remove button has no point in this form and never should, so I suggest we simply unset it.
I think we can unset all of these as well, rather than disable them. I see no reason to keep them around.
Can we say "Select which media type to create..." (just add the word 'which')?
Clever repurposing of the #name property!
Should we handle things like #after_build callbacks as well? Also, let's expand the comment to explain more fully what's going on (and more importantly, why).
It doesn't look like the method ever actually returns FALSE...?
I've noticed that callers of prepareForNextFile() call $form_state->setRebuild() anyway. We can probably remove those calls.
Is it possible that this could break media forms which have widgets that depend on storing stuff in $form_state storage? I'm not sure (and therefore a little worried) about any possible side effects this could have.
!!!
We'll need a test of this for authenticated users as well. We should probably test a few different cases.
I think instanceof is preferred to is_a(), but I could be wrong about that. Also, is there any reason for this method not to use array_filter()?
This should account for the possibility of file_validate_size and file_validate_extensions not being set in $validators.
Nit: This can be a single line.
Nit: This can also be a single line.
Supernit: "Media Type" should be lowercase.
Is there any way we can avoid hardcoding the FileItem class?
This seems like a perfect candidate for array_filter().
Comment #8
samuel.mortensonThanks for the review in #7 @phenaproxima!
are no longer in use. The method is never called while a form is "in process", if that makes sense.
Comment #9
chr.fritschThis is really awesome. Kudos!
One thing about the UX. I think it would be helpful if the creation form provides somehow from which media type the current item will be.
Also I just found some minor issues.
In #2670730: Provide a delete action for each content entity type we are introducing a delete-multiple-form, maybe this could be a add-multiple-form link relation and then add the route by the DefaultHtmlRouteProvider.
This should be $entity_type_manager
getInfoProperty returns a string, but array_merge expects an array
Comment #10
phenaproximaThat's an interesting idea, but because this add-multiple stuff is a new pattern in core, I think we should discuss/implement that in a follow-up.
In my experience, getInfoProperty() returns mixed. Whatever type the property is, is what is returned. This may be an example of an inaccurate doc comment, in which case we should open a follow-up to change it.
Comment #11
chr.fritschI am fine with moving that into a follow-up. But at least we should consider giving the route a future-proof name. Something like entity.media.add_multiple_form
Comment #12
phenaproxima+1 for that.
Comment #13
mmbkComment #14
dawehnerThis looks like a really nice patch! Thank you @samuel.mortenson for this feature!
Nitpick: This isn't really a getter. I like using build() when you build a render array. Thoughts?
Comment #15
mmbkSounds reasonable, I would refactor this function, if it's consensus
Comment #16
phenaproxima@mmbk, go for it.
Comment #17
mahalingam_cs commentedApplied the path and it worked fine. Have not checked the code. The functionality worked.I was able to upload multiple images together.
PFA - gif
Comment #18
mmbkThe method is called by 'buildForm', and builds the progressbar, so I'll name it 'buildProgressbar'
Starting nickpicking as well:
While examining the progressbar, I noticed, that it displays a very short bar when it got a #percentage of 0 (see screenshot)
I was a bit confused, but this seems to be the normal behavior of the progressbar.
Maybe it's less confusing when the progressbar displays 25% when entering for the first of four entites, and 100% when editing the last entity.
Saying this while knowing that progressbars normally display the percentage of finished tasks
Comment #19
phenaproximaThat is normal progress bar behavior, indeed. It's not great, but it's not in scope of this patch to address it. So no worries -- we can just rename the method and leave it at that. :)
Comment #20
mmbkComment #21
mmbkComment #24
samuel.mortenson@mmbk You'll need to change the bulk upload route name in the
::buildFinishedFormmethod as well, to fix tests.Comment #25
starshapedFixed failing tests.
Comment #26
mmbkYes I know - and i fixed it already - but i wanted to test it locally before I do the upload.
Should have written a notice earlier that I'm still working on this issue. To avoid doubled work.
Comment #27
ltrainApplied https://www.drupal.org/files/issues/2938116-24.patch
Clear drupal cache
Bulk upload form is at
/admin/content/media/upload
Bulk upload works.
Note: there is no bulk upload button at /admin/content/media
Comment #28
afoster commentedI've tested #25 and it works for me.
Also tested use cases attempting to break it.
- Where more than 1 media type matches file extension and it presents a "select media type" dialogue.
- Tested No file extension (throws an error and rejects upload)
- Uploading a word doc renamed extension to jpg (Error is a bit cryptic, "This value should be of the correct primitive type." but that's outside the scope of this issue
Looks good to me. Great work.
Comment #29
mmbkAs I learned here on the sprint, this should not be part of this issue, but of new following issue.
Comment #30
phenaproximaSorry to be "that guy", but this needs further review (not least from the usability team) before it's ready for RTBC :) However, thanks to everyone who has manually tested this and confirmed it works! That is much appreciated and will surely help "grease the wheels" to get this into core.
Comment #31
mmbkComment #32
samuel.mortensonIf anyone wants to help out more - the UX suggestion in #9 hasn't been added yet, and I think it's a good idea:
So maybe just a title or note above the form "Add [media type label]", the same thing that normally shows up at /media/add/%.
Comment #33
sjerdoComment #34
sjerdoAdded label for the creation form which shows which media type will be added.
Comment #35
sjerdoComment #36
jefuri commentedThe refactoring to the use of html_tag is great, totally agree. But you should probably rewrite this as well:
line 278, MediaBulkUploadForm.php
to
Because % add the tag automatically.
Comment #37
samuel.mortensonWhy has this been changed to use the html_tag element? p tags should be fine to use within t().
Comment #38
sjerdo@samuel.mortenson #37
In my opinion this makes the translation of the string cleaner. If for some reason the tag changes from 'p' to 'span', than its not in your translatable string, so your translatable would still be valid.
Comment #39
samuel.mortenson@sjerdo Ah, totally didn't think of that. Thanks for reminding me of a bad habit I have... :)
Comment #40
sjerdoImplemented the change suggested in #36.
Also noticed a bug regarding the validation of file uploads. When uploading multiple files of which one has validation errors, the correctly uploaded files were hidden but still in the field values. When uploading the valid files again, they occurred twice in the values of the field.
Discussed this issue with @seanB and @Mirnaxvb. This implementation will unset these files and remove them from the file storage. Not really happy about the current unsetting of the element values yet, so open for any suggestions.
Comment #41
samuel.mortensonI believe the File entities are already loaded in
$element['#files']at this point - may want to check that to avoid some complexity.I think for our use case this is fine, but it does look funny. We could avoid this logic and all our managed file process methods if users had to confirm uploaded files before moving to the next step - so we show a completely "vanilla" managed file element and have a "Use these files" button or something. I like the way the form currently works (feels more seamless), but it's worth bringing up as an alternative.
Comment #42
sjerdoUnfortunately #files is not yet set in that processor. The next processor adds the #files attribute, but we have to unset it before that step.
Discussed this with @seanB. Showing a completely "vanilla" managed file elements makes this field too complex for users. The current implementation is more seamless.
Comment #44
sjerdoFixed tests. A text was changed in #34.
Comment #45
mycw1991 commented@sjerdo
Patch in #44 looks good.
Comment #46
seanbYeah, I think showing the uploaded files could lead to confusion. When you see an error for 1 of the files, what happens if I start uploading again? Does it overwrite the previous set, or add to it? Especially if you made a complex selection. How can a user find out which of the files were already added or not?
Comparing those lists is not very user-friendly. Erasing all files and letting the user start over is also not very user-friendly, but to me that is at least a little better.
Comment #47
phenaproximaMy understanding is that the file which caused the error is kicked out of the list, and ignored. If you upload again, it will add to the list, not overwrite the previous set. However, @samuel.mortenson should be able to confirm or deny that understanding.
Still, it'd be real nice to have a test of that. AFAICT it is impossible to test multiple file uploads in an automated test, so a manual test may need to suffice for this one.
Comment #48
seanbThat is correct, but it's not very clear what you should do next and what will happen when you start uploading more files (does it overwrite files or just add to the list?). That's why removing the "partial" set seems like the best action. You get an error, your previous uploaded set failed and you should try again. When showing the list of uploaded files users might also get the idea that they are already done. These might all be solvable issues but my general feeling is we save ourselves a whole bunch of trouble just removing the partial list.
Comment #49
jefuri commented@sjerdo, this needs a bit more work dude.
This is big issue in the making. If for some reason there are any errors but no fids are in the form state values, all file entity ids will be loaded.
These will then be deleted, every single one.
Comment #50
phenaproximaWe should probably defer this question to the UX team.
Oh lord...that's a great catch! Let's fix that by checking that $fids is not NULL.
Comment #51
samuel.mortensonWe could make this extra-safer by only deleting temporary files, which is what the Managed File element normally does when you click "Remove". This is from
file_managed_file_submit():Comment #52
samuel.mortensonHere's an attempt to implement my idea in #41 - to just use the normal managed_file element and remove all of our #process logic. This has the added benefit of avoiding the data loss issues discussed recently, and letting users upload files from multiple folders (now you can drag+drop from one OS window, then click to upload a few more, then start the bulk creation process). I've attached a screenshot of the behavior when multiple files are uploaded and one of them is invalid.
Comment #53
phenaproximaA quick note to others who are working on this patch -- please do not iterate on @samuel.mortenson's work in #52. We're intending to demo both solutions to the UX team on Tuesday during the UX meeting, to decide which option is better to proceed with. So rather than having two "forks" of this same patch in this one issue, continue any work based on #44.
Comment #54
jefuri commentedAdded checks to the fids to make sure that only non temporary files and files from the submit are deleted.
Iterated these changes on top of #44.
Comment #55
jefuri commentedSomething went wrong in my IDE, auto formatting changed to much.
Comment #56
jefuri commentedComment #57
jefuri commentedFixed it, implemented the correct code this time and interdiff.
Based it (again) on #44 and also used the suggestion to check through ->isTemporary() from @samuel.mortenson.
Comment #58
sjerdoSome review comments for #57:
$upload_value['fids'] can be an empty array when eg. uploading only files with an incorrect file extension. You can add an empty check for an early return.
You could use array_filter for filtering the array.
If you still prefer filtering using foreach, you should add a space between
foreachand(Comment #59
yogeshmpawarUpdated patch with interdiff as mentioned in #58
Comment #60
tstoecklerStarted reviewing this but only scratched the surface so far. Have to jump now, though, so.... here goes.
Nitpick: I guess in theory the class description should start with a verb. Not sure how to rephrase it so that it stays under 80 characters.
Nitpick: Maybe: "A list of media types..."
Would it make sense to split this up into separate form classes analogously to #2918761: Break up MigrateUpgradeForm into smaller forms? I would say, yes, but not sure if e.g. the fact that we are heavily using Ajax here would be a reason against it.
Does the "if possible" part refer to the chance of no types being returned at all? If so, I think that could be solved by checking
!isset($this->types)Super nitpick: s/Gets/Builds/ ?
I think this could/should use
\Drupal\Core\Batch\Percentage::format()I don't think we support setting
#processto a string?! But I guess we should pass$default = []just in case there are no#processcallbacks are predefined.Comment #61
chr.fritschI fixed everything from #60 except 3. because I am not sure of it. It would be nice if it could be done, it would make the code much more readable.
I would like to get @samuel.mortenson opinion on it.
Comment #62
kay_v commentedbased on #61, marking as 'needs work'
Comment #63
phenaproximaSetting #2834729: [META] Roadmap to stabilize Media Library as the parent issue, and postponing it on #2962110: Add the Media Library module to Drupal core and the as-yet-uncreated issue to create a field widget that integrates with the media library.
Comment #64
xjmComment #76
webchickDon't mind me; just the friendly neighbourhood credit fairy, pulling things over from #2962110: Add the Media Library module to Drupal core.
Comment #80
webchick...aaaaand done.
Back to your regularly scheduled issue. ;)
Comment #87
webchickOh, crap. I meant to do that from #2831940: Create file field widget on top of media entity.
Credit fairy: FIRED. :P
Comment #88
plachIf I understood correctly the dependency chain, this is now blocked only on #2962525: Create a field widget for the Media library module.
Comment #89
samuel.mortensonAlthough this patch is becoming increasingly functional, I think we need to stop the re-rolls and review until the usability team has a chance to review it and decide if this is the direction core wants to go for uploads. Going way back to the original Media library mockups, uploading files was supposed to bring up a screen like this:
I ended up implementing a multi-step AJAX form because, at the time, we were running into some very serious issues with showing multiple entity forms on one page. But the UX/design of the library shouldn't be driven by technical problems, so it may be worth re-visiting the original mockups and trying to implement them again, instead of pushing forward on the current patch.
Comment #90
jackbravo commentedAnd now that the media library is in core, this is no longer postponed right? But sill, like said on #2938116-89: Allow media to be uploaded with the Media Library field widget the direction of this ticket should be reviewed.
Comment #91
samuel.mortensonThis is still waiting on #2962525: Create a field widget for the Media library module, but assigning to myself to prevent cross-work. Hoping to start early on this ASAP.
Comment #92
samuel.mortensonHere's a in-progress patch based on #61 which follows the mockups more closely, and is a lot easier to use than the multi-step form. I made a demo video a few days ago that's a little outdated, but the flow is basically the same as the patch: https://www.youtube.com/watch?v=AYL0ujucjtY
Please hold off on code review until the issue is unpostponed and put into "Needs review", but UX review and bug-hunting is more than welcome. The "combined" patch includes the latest field widget and the code for this issue.
Comment #93
samuel.mortensonComment #95
samuel.mortensonAdded what I think is extensive test coverage for this functionality.
Comment #96
phenaproximaThanks! Nice freaking work. Removing the tag.
Comment #97
samuel.mortensonUpdated the issue summary which was really out of date. Also removing the "Needs followup" tag as we don't have any active follow ups, at least not yet.
Comment #98
samuel.mortensonComment #99
geek-merlinAwesome work! Hope this can sneak into 8.6❣
Comment #100
plachParent issue was committed and pushed to 8.7.x (and will be backported to 8.6.x). Let's try to get this in 8.6.x as well :)
Comment #102
phenaproximaComment #103
phenaproximaIsn't the padding directive missing a value?
Also, can we get some comments in this file explaining what these selectors are targeting?
I think this is okay for the time being, what with this being an experimental module, but eventually we should find a way to suppress this on the server side.
It's too bad there's no area plugin for this. Can we open a follow-up to move this link into the actual widget itself, as per the mockups?
We need to add additional coverage to this test -- for example, some more required metadata fields on some of the uploads, including complex AJAX-ey ones like images, to prove that sort of functionality works (and also that they reject invalid input correctly).
This seems prone to random failures. Is there any way we can guarantee a PNG and a JPEG? Maybe an infinite while loop until both $png_image and $jpg_image are set?
Let's use $this->container->get() instead of \Drupal::service().
If we use
$modal_element = $assert_session->elementExists('css', '#drupal-modal'), we can press buttons and assert things in the context of the modal element, rather than the entire page. This might be useful to prevent weirdness if things are refactored or changed here.Let's use the existing $file_system object we got above.
Should be assertSame().
assertSame() for strings.
Why not
$file_storage->load($file->id())?assertSame()
I think these are buttons, so we should be using $assert_session->buttonExists('Type Three')->press().
assertSame()
Maybe we should assert that the modal is no longer visible instead.
This probably shouldn't be here :)
What's this do?
Why does this media type show its source field, but the others don't?
No need for this; Media already depends on File and Image.
Form classes are internal by policy, but let's mark this explicitly internal to cover our asses.
Although the trait provides useful methods, I'm not sure we should have a trait for this stuff yet. It's an invitation for people to use this module as an API, which is not something we want at this stage. Let's remove the trait for now, and open a follow-up to move useful upload-related methods into a trait or service.
Why make this a boolean? Let's just load the image style entirely.
Why is this needed?
We know that ManagedFile's #process is an array, so I don't know if we need this check.
I'm surprised that a method named 'validate' is going into the #process group. Perhaps we should take advantage of #element_validate here?
The fact that we've hard-coded the medium style is...kinda icky. Can we make that a route default or something? (This is fine for a follow-up if that's easier.) Also, if there is no thumbnail, or the image style doesn't exist, $element['preview']['#access'] should probably be false.
Nit -- this can be one line.
EntityFormDisplay::collectRenderDisplay($media, 'media_library')->buildForm().We're going to need a more robust way of dealing with this kind of detritus, but we can defer that to a follow-up.
Nit: Can be one line.
Need some spaces in that list() call :) Also, getting the type and index from the name of the element feels brittle; maybe just set properties on the element itself and use those?
We can use $this->getRequest().
Can we make this a required route parameter, rather than DIY'ing it here?
We should use formatPlural() here.
Nit: Let's call reset($types) inline with createMediaEntity().
Eventually it'd be nice to move these methods to the storage handler for media types -- let's open a follow-up to discuss.
Let's type hint $type as MediaTypeInterface.
I think we should just filter on the source field's class being an instance of FileItem, rather than a concrete media source plugin class. However, this is okay for the moment; let's open a follow-up if changing this now is too complicated.
Comment #104
samuel.mortensonThanks as always Adam. Addressing #103:
1. Fixed.
2. Opened #2987921: Media Library add form should suppress extraneous components of image fields using a form alter, not CSS as a follow up and added comment.
3. The mockups also show the button in the view, and an inline file upload widget in the field. I don't think we've reached a consensus on all the different ways we want to get to upload, but having one clear way in the view makes sense to me right now.
4. This test already has coverage for form validation via AJAX, and we can't test images because of our CSS-hiding-styles.
5. The test files aren't randomly generated and have been consistent for a long time (no deletions since ~2014), many tests rely on specific sizes/extensions to be present.
6. Done.
7. Done.
8. Done.
9. Done.
10. Done.
11. We don't have the new file ID yet - we just know it was the last uploaded file.
12. Done.
13. Done.
14. Done.
15. This is how the widget test asserts that the modal was closed, I feel like it's adequate.
16. Good catch! Fixed.
17. I dunno, but core exports it by default. The other config we provide also includes it.
18. We need to allow users to set image alt/title attributes, which is in the image widget.
19. Removed.
20. Added.
21. I moved all the trait methods out and opened #2987924: Define an API for finding media types based on an arbitrary value
22. This is the logic used by the media list builder, I was following the same naming and logic convention. We also don't need anything from the loaded image style.
23. It was used by the trait, removed.
24. This was added from previous testing, it appears that process is not always an array (for example if the service was overriden or if there was an alter).
25. For the life of me I could not get #element_validate to work, which is why this is in #process. If anyone can move the logic and retain the functionality please do. :-)
26. See 22 - also the preview container has a minimum width, so we don't want to conditionally hide it, even if it's empty.
27. Fixed.
28. I'm not sure I understand - what would the follow up be? The problem to me is that the revision log isn't configurable in "form display", but that issue would be a huge undertaking. This logic seems OK to me.
29. Fixed.
30. I moved to using element properties, good call.
31. Fixed.
32. No, and this is how the widget works as well. That said, I think the query params will change or improve in #2983179: [META] Implement stricter access checking for the media library, which will make this look better (or remove it, we haven't decided which is why there's no @todo).
33. We don't need to handle the single upload case - the validation at the element level prevents multiple uploads if the field cardinality is 1.
34. Done.
35. Done, and I've done this in all the other callbacks as well.
36. This was tricky, but it's done now.
Interdiff is broken because of re-roll, sorry!
Comment #105
samuel.mortensonPer Adam's request I added explicit test coverage for an AJAX-y element (Image widget) inside the upload form.
Comment #106
phenaproximaAwww yeah. Very few things to complain about now.
This shouldn't be @inheritdoc.
No need to change this here, but pro-tip: if you cast a string to array, you get [$string] :)
Let's open a follow-up, and put a @todo here, to separate validation logic from #process (we might have to do it by overriding the #value_callback, but that's a potentially infinite pain train so let's not do it right now).
Can we move the contents of this foreach loop into a helper method?
If the medium style doesn't exist, there will be no preview image. That's kind of unfortunate; let's at least open a follow-up to address this later or make it configurable.
Let's also move the contents of this foreach loop into a helper method.
Why wouldn't $file be an instance of FileInterface? This could use a comment.
Let's throw exceptions if either of these properties are empty.
Should we use $this->getTypes()[$type] instead?
Can this be renamed to processUploadElement, for clarity?
Both of these functions will return FALSE on error, so we should account for those cases by throwing exceptions.
We don't need the @throws tags, since this method never explicitly throws.
Supernit: "A file entity"
Nit: There's a superfluous pair of parentheses here.
Comment #107
phenaproximaOops, forgot to change status.
Comment #108
samuel.mortensonAddressed #106:
1. Fixed. Also found another method with a wrong doc.
2. Smart! Changed to use casting.
3. I opened #2988215: Use #element_validate for the upload element in the MediaLibraryUploadForm.
4. Done.
5. I opened #2988223: Make the MediaLibraryUploadForm's image style configurable
6. Done.
7. I removed the if check - it should always be a file.
8. Done.
9. Sure, done.
10. Yep, done.
11. Done.
12. Removed all @throws tags that weren't documenting things we do.
13. Fixed.
14. Removed.
Comment #109
phenaproximaAh -- sorry for the miscommunication!! The logic I wanted moved into helper methods is the stuff that builds all of the preview/metadata fields for each media item or uploaded file. Sorry about that! #phenaisanidiot
Comment #110
samuel.mortensonAfter discussing refactoring with @phenaproxima we decided to revert the new methods from #108 and keep the buildForm loops the same.
Comment #111
phenaproximaAll my code feedback is addressed. We're awaiting some testing and input from @DyanneNova for UX, and then we're RTBC once green on all backends.
Comment #113
lauriiiIn my opinion double underscore should only appear once in a class name. BEM doesn't really specify this kind of rule but in my opinion it is something we should choose to not do in Drupal.
The naming convention is there to help you identify relationships with the top level component block. If we were to use the double underscore multiple times the class names would quickly get out of control making the class names hideous and unreadable.
Comment #114
samuel.mortensonAddressed #113.
Comment #115
samuel.mortensonMeant to use dashes...
Comment #116
samuel.mortensonPer a call with @webchick, changing the button labels and adding the "Add media" button directly on the widget.
Comment #117
phenaproximaInterdiff looks good to me.
@samuel.mortenson and I demoed this patch to @webchick. She was, I'm pleased to say, pretty blown away. There were only two commit-blocking points of concern, both addressed in #116. We also looked over the code, and found nothing untoward.
So, given:
...I think it's time to land this.
Comment #118
jibranWhy not use local action for this and attributes in media_librar_template_preprocess_menu_local_action?
This can be wrapper
'#type' => 'container',with'#id'. See https://github.com/drupal/drupal/blob/8.6.x/core/modules/system/tests/mo...This is not needed media save will save the file.
Comment #119
berdir2. Nope, it can't. ajax wrapper ID's *must* put there like that because #id will be uniqified on ajax requests and then it will be ...--hash and then the replacement will not work anymore. That said, I have no clue why we aren't using our very own drupal-identifier things instead and also enforce that an ajax identifier must be an ID instead of a that or a class.
Comment #120
phenaproximaBecause they are not local actions; they are arbitrary buttons and must be rendered as such. It's not our fault that local actions and primary buttons have similar styling, and that's way out of scope for us to address here. Trying to make that button into a local action will likely remove it from the modal, and cause more problems than it solves (routing + modal = migraine). We can explore that path in a follow-up, if you like, but it should not block commit.
That's news to me; can you point out where that happens in Media?
Comment #121
jibranThis is simply not correct. A lot of people think the container #id will be uniqified that's why I linked the example also please have a look at
template_preprocess_containerDrupal doesn't touch that id it is passes as is everytime.
Comment #122
phenaproximaIt is much more important to land this functionality in 8.6 before beta than it is to make sure that the wrapper ID is set in a specific way. Especially given that this module is experimental.
Please, let's open a follow-up issue to fix that in beta. There is no reason why that cannot change during beta, but unless we land this now, we cannot get this much-needed feature into core.
Comment #123
jibranThis is not mdia magic this is ER field magic. See
\Drupal\Tests\field\Kernel\EntityReference\EntityReferenceItemTest::testEntityAutoCreateIMO
$form['#prefix']and$form['#suffix']should never be used to add html becaue it breaks stuff all the time.Comment #124
berdirCan't find anything right now, but I know I've had problems with setting id through #id in the past.
prefix.+id=".+wrapper"finds 26 matches in core, so if you think it should work with #id, maybe open an issue to change all of them?Comment #125
phenaproximaThe media item is what's being referenced by the ER field; the file is being referenced by the media item's source field. I'm still not clear on how EntityReferenceItemList is be smart enough to know to save both; the test does not make it clear. I would be quite surprised to learn that it knows to save references-within-references.
Additionally, the logic of this form is rather unlike any other form or entity reference widget in core. It's best, for now, to stick with what is working. If we want to delegate the save logic to Entity Reference, we should explore it in a follow-up (which I'm sure could land in beta). It should not block commit of this patch.
Comment #126
jibranI understand that. We shouldn't be adding link to views header like that. This should be converted to view area plugin so that user can remove the block if needs be. This makes customization of the this view harder for non-dev site builder user.
Comment #127
phenaproxima100% agreed, and I in fact mentioned that in an earlier round of review. However, it's out of scope for now; I think we filed a follow-up. If not, I'll make sure we have one :)
Comment #128
phenaproximaFollow-up filed: #2988451: Add an area plugin to render a link
Comment #132
webchick@phenaproxima and @samuel.mortenson sat and walked me through the patch and its functionality a bit earlier today. I have no idea how you guys pulled this off, but it looks and works AMAZINGLY!! Exactly what was in the mocks, in terms of embedding multiple media entry forms in the same place. (The required alt text is definitely a friction point, but I understand its importance and why we force that on default installs.) The tests are comprehensive, as is the validation for various edge cases (such as upload a file covered by multiple media types).
The patch is entirely UI-facing, and entirely contained in experimental code, so relatively low risk of commit. Given the enormous end-user impact this patch has on 8.6's release, and given that the unresolved feedback in #118 and below seems like it can be solved in follow-up issues (if it's deemed valid; sounds like there's some disagreement there), I'm going to go ahead and commit this so we can get it in for 8.6's beta.
Committed and pushed to 8.7.x, cherry-picked to 8.6.x. YEAH!!!!! :D
Comment #133
marcoscanoThis is an amazing work, thanks for everyone that worked on this!
As a follow-up, I've discovered #2988617: Creating media with the media library upload is broken for unlimited cardinality while testing this today.
Thanks again!