Issue #3023797 by seanB, webchick, lauriii, ckrina, phenaproxima, andrewmacpherson, rainbreaw, Gábor Hojtsy, jhodgdon, jrockowitz, worldlinemine, benjifisher: Let users choose what to do after selecting and/or adding items in the media library
parent
9d96532b79
commit
c91f236591
|
@ -24,6 +24,7 @@
|
|||
|
||||
.media-library-views-form,
|
||||
.media-library-selection,
|
||||
.media-library-add-form__selected-media .details-wrapper,
|
||||
.media-library-views-form__bulk_form,
|
||||
.media-library-view .form--inline {
|
||||
display: flex;
|
||||
|
@ -81,7 +82,8 @@
|
|||
|
||||
/* @todo Remove or re-work in https://www.drupal.org/node/2985168 */
|
||||
.media-library-widget .media-library-item__name a,
|
||||
.media-library-view--widget .media-library-item__name a {
|
||||
.media-library-view--widget .media-library-item__name a,
|
||||
.media-library-add-form__selected-media .media-library-item__name a {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
|
|
@ -116,6 +116,10 @@
|
|||
margin: 8px 0 0;
|
||||
}
|
||||
|
||||
.media-library-add-form__description {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Style the media add oEmbed form. */
|
||||
.media-library-add-form--oembed .media-library-add-form__input-wrapper {
|
||||
display: flex;
|
||||
|
@ -143,6 +147,20 @@
|
|||
align-self: center;
|
||||
}
|
||||
|
||||
/* Media add form selection styles. */
|
||||
.media-library-add-form__selected-media {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
/* Change to padding to account for the negative margin for flex grid. */
|
||||
.media-library-add-form__selected-media .details-wrapper {
|
||||
padding: 0 10px 1em 10px;
|
||||
}
|
||||
|
||||
.media-library-add-form__selected-media .media-library-item .field--name-thumbnail img {
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
/* Generic media library view styles. */
|
||||
.media-library-select-all {
|
||||
margin: 10px 0 10px 0;
|
||||
|
@ -290,16 +308,26 @@
|
|||
border: 1px solid #dbdbdb;
|
||||
}
|
||||
|
||||
/* The selected items in the add form should be shown a bit smaller. */
|
||||
.media-library-add-form__selected-media .media-library-item--small {
|
||||
width: 33.3%;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 45em) {
|
||||
.media-library-item--grid {
|
||||
width: 33%;
|
||||
width: 33.3%;
|
||||
}
|
||||
|
||||
/* Use a smaller width for the modal and widget since there is less space. */
|
||||
/* Change the width for the modal and widget since there is less space. */
|
||||
.media-library-widget-modal .media-library-item--grid,
|
||||
.media-library-selection .media-library-item--grid {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
/* The selected items in the add form should be shown a bit smaller. */
|
||||
.media-library-add-form__selected-media .media-library-item--small {
|
||||
width: 25%;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 60em) {
|
||||
|
@ -307,23 +335,33 @@
|
|||
width: 25%;
|
||||
}
|
||||
|
||||
/* Use a smaller width for the modal and widget since there is less space. */
|
||||
/* Change the width for the modal and widget since there is less space. */
|
||||
.media-library-widget-modal .media-library-item--grid,
|
||||
.media-library-selection .media-library-item--grid {
|
||||
width: 33%;
|
||||
width: 33.3%;
|
||||
}
|
||||
|
||||
/* The selected items in the add form should be shown a bit smaller. */
|
||||
.media-library-add-form__selected-media .media-library-item--small {
|
||||
width: 16.6%;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 77em) {
|
||||
.media-library-item--grid {
|
||||
width: 16%;
|
||||
width: 16.6%;
|
||||
}
|
||||
|
||||
/* Use a smaller width for the modal and widget since there is less space. */
|
||||
/* Change the width for the modal and widget since there is less space. */
|
||||
.media-library-widget-modal .media-library-item--grid,
|
||||
.media-library-selection .media-library-item--grid {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
/* The selected items in the add form should be shown a bit smaller. */
|
||||
.media-library-add-form__selected-media .media-library-item--small {
|
||||
width: 16.6%;
|
||||
}
|
||||
}
|
||||
|
||||
.media-library-item--grid .field--name-thumbnail {
|
||||
|
@ -348,7 +386,7 @@
|
|||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.media-library-item--grid.checked {
|
||||
.media-library-item--grid.checked:before {
|
||||
border-color: #0076c0;
|
||||
}
|
||||
|
||||
|
@ -504,7 +542,7 @@
|
|||
.media-library-add-form__media {
|
||||
position: relative;
|
||||
display: flex;
|
||||
padding: 20px 0 20px 0;
|
||||
padding: 1em 0;
|
||||
border-bottom: 1px solid #c0c0c0;
|
||||
outline: none;
|
||||
}
|
||||
|
@ -607,7 +645,8 @@
|
|||
|
||||
/* @todo Remove or re-work in https://www.drupal.org/node/2985168 */
|
||||
.media-library-widget .media-library-item__name a,
|
||||
.media-library-view--widget .media-library-item__name a {
|
||||
.media-library-view--widget .media-library-item__name a,
|
||||
.media-library-add-form__selected-media .media-library-item__name a {
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
}
|
||||
|
|
|
@ -24,12 +24,29 @@
|
|||
.find('.js-click-to-select-checkbox input');
|
||||
$input.prop('checked', !$input.prop('checked')).trigger('change');
|
||||
});
|
||||
|
||||
$('.js-click-to-select-checkbox input', context)
|
||||
.once('media-library-click-to-select')
|
||||
// Adds checked class to the click-to-select element.
|
||||
.on('change', ({ currentTarget }) => {
|
||||
$(currentTarget)
|
||||
.closest('.js-click-to-select')
|
||||
.toggleClass('checked', $(currentTarget).prop('checked'));
|
||||
})
|
||||
// Adds is-focus class to the click-to-select element.
|
||||
.on('focus blur', ({ currentTarget, type }) => {
|
||||
$(currentTarget)
|
||||
.closest('.js-click-to-select')
|
||||
.toggleClass('is-focus', type === 'focus');
|
||||
});
|
||||
|
||||
// Adds hover class to the click-to-select element.
|
||||
$('.js-click-to-select-trigger, .js-click-to-select-checkbox', context)
|
||||
.once('media-library-click-to-select-hover')
|
||||
.on('mouseover mouseout', ({ currentTarget, type }) => {
|
||||
$(currentTarget)
|
||||
.closest('.js-click-to-select')
|
||||
.toggleClass('is-hover', type === 'mouseover');
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
|
@ -14,10 +14,23 @@
|
|||
var $input = $(event.currentTarget).closest('.js-click-to-select').find('.js-click-to-select-checkbox input');
|
||||
$input.prop('checked', !$input.prop('checked')).trigger('change');
|
||||
});
|
||||
|
||||
$('.js-click-to-select-checkbox input', context).once('media-library-click-to-select').on('change', function (_ref) {
|
||||
var currentTarget = _ref.currentTarget;
|
||||
|
||||
$(currentTarget).closest('.js-click-to-select').toggleClass('checked', $(currentTarget).prop('checked'));
|
||||
}).on('focus blur', function (_ref2) {
|
||||
var currentTarget = _ref2.currentTarget,
|
||||
type = _ref2.type;
|
||||
|
||||
$(currentTarget).closest('.js-click-to-select').toggleClass('is-focus', type === 'focus');
|
||||
});
|
||||
|
||||
$('.js-click-to-select-trigger, .js-click-to-select-checkbox', context).once('media-library-click-to-select-hover').on('mouseover mouseout', function (_ref3) {
|
||||
var currentTarget = _ref3.currentTarget,
|
||||
type = _ref3.type;
|
||||
|
||||
$(currentTarget).closest('.js-click-to-select').toggleClass('is-hover', type === 'mouseover');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -251,7 +251,10 @@
|
|||
*/
|
||||
Drupal.behaviors.MediaLibraryItemSelection = {
|
||||
attach(context, settings) {
|
||||
const $form = $('.js-media-library-views-form', context);
|
||||
const $form = $(
|
||||
'.js-media-library-views-form, .js-media-library-add-form',
|
||||
context,
|
||||
);
|
||||
const currentSelection = Drupal.MediaLibrary.currentSelection;
|
||||
|
||||
if (!$form.length) {
|
||||
|
@ -263,30 +266,6 @@
|
|||
$form,
|
||||
);
|
||||
|
||||
// Update the selection array and the hidden form field when a media item
|
||||
// is selected.
|
||||
$mediaItems.once('media-item-change').on('change', e => {
|
||||
const id = e.currentTarget.value;
|
||||
|
||||
// Update the selection.
|
||||
const position = currentSelection.indexOf(id);
|
||||
if (e.currentTarget.checked) {
|
||||
// Check if the ID is not already in the selection and add if needed.
|
||||
if (position === -1) {
|
||||
currentSelection.push(id);
|
||||
}
|
||||
} else if (position !== -1) {
|
||||
// Remove the ID when it is in the current selection.
|
||||
currentSelection.splice(position, 1);
|
||||
}
|
||||
|
||||
// Set the selection in the hidden form element.
|
||||
$form
|
||||
.find('#media-library-modal-selection')
|
||||
.val(currentSelection.join())
|
||||
.trigger('change');
|
||||
});
|
||||
|
||||
/**
|
||||
* Disable media items.
|
||||
*
|
||||
|
@ -343,23 +322,49 @@
|
|||
}
|
||||
}
|
||||
|
||||
// The hidden selection form field changes when the selection is updated.
|
||||
$('#media-library-modal-selection', $form)
|
||||
.once('media-library-selection-change')
|
||||
.on('change', e => {
|
||||
updateSelectionInfo(settings.media_library.selection_remaining);
|
||||
// Update the selection array and the hidden form field when a media item
|
||||
// is selected.
|
||||
$mediaItems.once('media-item-change').on('change', e => {
|
||||
const id = e.currentTarget.value;
|
||||
|
||||
// Prevent users from selecting more items than allowed.
|
||||
if (
|
||||
currentSelection.length ===
|
||||
settings.media_library.selection_remaining
|
||||
) {
|
||||
disableItems($mediaItems.not(':checked'));
|
||||
enableItems($mediaItems.filter(':checked'));
|
||||
} else {
|
||||
enableItems($mediaItems);
|
||||
// Update the selection.
|
||||
const position = currentSelection.indexOf(id);
|
||||
if (e.currentTarget.checked) {
|
||||
// Check if the ID is not already in the selection and add if needed.
|
||||
if (position === -1) {
|
||||
currentSelection.push(id);
|
||||
}
|
||||
});
|
||||
} else if (position !== -1) {
|
||||
// Remove the ID when it is in the current selection.
|
||||
currentSelection.splice(position, 1);
|
||||
}
|
||||
|
||||
// Set the selection in the hidden form element.
|
||||
$form
|
||||
.find('#media-library-modal-selection')
|
||||
.val(currentSelection.join())
|
||||
.trigger('change');
|
||||
|
||||
// Set the selection in the media library add form. Since the form is
|
||||
// not necessarily loaded within the same context, we can't use the
|
||||
// context here.
|
||||
$('.js-media-library-add-form-current-selection').val(
|
||||
currentSelection.join(),
|
||||
);
|
||||
|
||||
// Update the number of selected items in the button pane.
|
||||
updateSelectionInfo(settings.media_library.selection_remaining);
|
||||
|
||||
// Prevent users from selecting more items than allowed.
|
||||
if (
|
||||
currentSelection.length === settings.media_library.selection_remaining
|
||||
) {
|
||||
disableItems($mediaItems.not(':checked'));
|
||||
enableItems($mediaItems.filter(':checked'));
|
||||
} else {
|
||||
enableItems($mediaItems);
|
||||
}
|
||||
});
|
||||
|
||||
// Apply the current selection to the media library view. Changing the
|
||||
// checkbox values triggers the change event for the media items. The
|
||||
|
|
|
@ -136,7 +136,7 @@
|
|||
|
||||
Drupal.behaviors.MediaLibraryItemSelection = {
|
||||
attach: function attach(context, settings) {
|
||||
var $form = $('.js-media-library-views-form', context);
|
||||
var $form = $('.js-media-library-views-form, .js-media-library-add-form', context);
|
||||
var currentSelection = Drupal.MediaLibrary.currentSelection;
|
||||
|
||||
if (!$form.length) {
|
||||
|
@ -145,21 +145,6 @@
|
|||
|
||||
var $mediaItems = $('.js-media-library-item input[type="checkbox"]', $form);
|
||||
|
||||
$mediaItems.once('media-item-change').on('change', function (e) {
|
||||
var id = e.currentTarget.value;
|
||||
|
||||
var position = currentSelection.indexOf(id);
|
||||
if (e.currentTarget.checked) {
|
||||
if (position === -1) {
|
||||
currentSelection.push(id);
|
||||
}
|
||||
} else if (position !== -1) {
|
||||
currentSelection.splice(position, 1);
|
||||
}
|
||||
|
||||
$form.find('#media-library-modal-selection').val(currentSelection.join()).trigger('change');
|
||||
});
|
||||
|
||||
function disableItems($items) {
|
||||
$items.prop('disabled', true).closest('.js-media-library-item').addClass('media-library-item--disabled');
|
||||
}
|
||||
|
@ -183,7 +168,22 @@
|
|||
}
|
||||
}
|
||||
|
||||
$('#media-library-modal-selection', $form).once('media-library-selection-change').on('change', function (e) {
|
||||
$mediaItems.once('media-item-change').on('change', function (e) {
|
||||
var id = e.currentTarget.value;
|
||||
|
||||
var position = currentSelection.indexOf(id);
|
||||
if (e.currentTarget.checked) {
|
||||
if (position === -1) {
|
||||
currentSelection.push(id);
|
||||
}
|
||||
} else if (position !== -1) {
|
||||
currentSelection.splice(position, 1);
|
||||
}
|
||||
|
||||
$form.find('#media-library-modal-selection').val(currentSelection.join()).trigger('change');
|
||||
|
||||
$('.js-media-library-add-form-current-selection').val(currentSelection.join());
|
||||
|
||||
updateSelectionInfo(settings.media_library.selection_remaining);
|
||||
|
||||
if (currentSelection.length === settings.media_library.selection_remaining) {
|
||||
|
|
|
@ -2,46 +2,6 @@
|
|||
* @file media_library.view.es6.js
|
||||
*/
|
||||
(($, Drupal) => {
|
||||
/**
|
||||
* Adds hover effect to media items.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches behavior to add a class when hovering over media items.
|
||||
*/
|
||||
Drupal.behaviors.MediaLibraryHover = {
|
||||
attach(context) {
|
||||
$('.js-click-to-select-trigger, .js-click-to-select-checkbox', context)
|
||||
.once('media-library-item-hover')
|
||||
.on('mouseover mouseout', ({ currentTarget, type }) => {
|
||||
$(currentTarget)
|
||||
.closest('.js-media-library-item')
|
||||
.toggleClass('is-hover', type === 'mouseover');
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds focus effect to media items.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches behavior to add a focus effect to media items.
|
||||
*/
|
||||
Drupal.behaviors.MediaLibraryFocus = {
|
||||
attach(context) {
|
||||
$('.js-click-to-select-checkbox input', context)
|
||||
.once('media-library-item-focus')
|
||||
.on('focus blur', ({ currentTarget, type }) => {
|
||||
$(currentTarget)
|
||||
.closest('.js-media-library-item')
|
||||
.toggleClass('is-focus', type === 'focus');
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds checkbox to select all items in the library.
|
||||
*
|
||||
|
|
|
@ -6,34 +6,12 @@
|
|||
**/
|
||||
|
||||
(function ($, Drupal) {
|
||||
Drupal.behaviors.MediaLibraryHover = {
|
||||
attach: function attach(context) {
|
||||
$('.js-click-to-select-trigger, .js-click-to-select-checkbox', context).once('media-library-item-hover').on('mouseover mouseout', function (_ref) {
|
||||
var currentTarget = _ref.currentTarget,
|
||||
type = _ref.type;
|
||||
|
||||
$(currentTarget).closest('.js-media-library-item').toggleClass('is-hover', type === 'mouseover');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Drupal.behaviors.MediaLibraryFocus = {
|
||||
attach: function attach(context) {
|
||||
$('.js-click-to-select-checkbox input', context).once('media-library-item-focus').on('focus blur', function (_ref2) {
|
||||
var currentTarget = _ref2.currentTarget,
|
||||
type = _ref2.type;
|
||||
|
||||
$(currentTarget).closest('.js-media-library-item').toggleClass('is-focus', type === 'focus');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Drupal.behaviors.MediaLibrarySelectAll = {
|
||||
attach: function attach(context) {
|
||||
var $view = $('.js-media-library-view', context).once('media-library-select-all');
|
||||
if ($view.length && $view.find('.js-media-library-item').length) {
|
||||
var $checkbox = $('<input type="checkbox" class="form-checkbox" />').on('click', function (_ref3) {
|
||||
var currentTarget = _ref3.currentTarget;
|
||||
var $checkbox = $('<input type="checkbox" class="form-checkbox" />').on('click', function (_ref) {
|
||||
var currentTarget = _ref.currentTarget;
|
||||
|
||||
var $checkboxes = $(currentTarget).closest('.media-library-view').find('.js-media-library-item input[type="checkbox"]');
|
||||
$checkboxes.prop('checked', $(currentTarget).prop('checked')).trigger('change');
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace Drupal\media_library\Form;
|
||||
|
||||
use Drupal\Core\Ajax\AjaxResponse;
|
||||
use Drupal\Core\Ajax\CloseDialogCommand;
|
||||
use Drupal\Core\Ajax\InvokeCommand;
|
||||
use Drupal\Core\Ajax\ReplaceCommand;
|
||||
use Drupal\Core\Entity\Entity\EntityFormDisplay;
|
||||
|
@ -15,6 +16,7 @@ use Drupal\media\MediaInterface;
|
|||
use Drupal\media\MediaTypeInterface;
|
||||
use Drupal\media_library\Ajax\UpdateSelectionCommand;
|
||||
use Drupal\media_library\MediaLibraryUiBuilder;
|
||||
use Drupal\media_library\Plugin\Field\FieldWidget\MediaLibraryWidget;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
|
@ -48,6 +50,13 @@ abstract class AddFormBase extends FormBase {
|
|||
*/
|
||||
protected $mediaType;
|
||||
|
||||
/**
|
||||
* The media view builder.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityViewBuilderInterface
|
||||
*/
|
||||
protected $viewBuilder;
|
||||
|
||||
/**
|
||||
* Constructs a AddFormBase object.
|
||||
*
|
||||
|
@ -59,6 +68,7 @@ abstract class AddFormBase extends FormBase {
|
|||
public function __construct(EntityTypeManagerInterface $entity_type_manager, MediaLibraryUiBuilder $library_ui_builder) {
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
$this->libraryUiBuilder = $library_ui_builder;
|
||||
$this->viewBuilder = $this->entityTypeManager->getViewBuilder('media');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -131,8 +141,12 @@ abstract class AddFormBase extends FormBase {
|
|||
'#type' => 'status_messages',
|
||||
];
|
||||
|
||||
$form['#attributes']['class'][] = 'media-library-add-form';
|
||||
$added_media = $form_state->get('media');
|
||||
$form['#attributes']['class'] = [
|
||||
'media-library-add-form',
|
||||
'js-media-library-add-form',
|
||||
];
|
||||
|
||||
$added_media = $this->getAddedMediaItems($form_state);
|
||||
if (empty($added_media)) {
|
||||
$form['#attributes']['class'][] = 'media-library-add-form--without-input';
|
||||
$form = $this->buildInputElement($form, $form_state);
|
||||
|
@ -157,12 +171,39 @@ abstract class AddFormBase extends FormBase {
|
|||
],
|
||||
];
|
||||
|
||||
$form['media']['description'] = [
|
||||
'#type' => 'html_tag',
|
||||
'#tag' => 'p',
|
||||
'#value' => $this->formatPlural(count($added_media), 'The media item has been created but has not yet been saved. Fill in any required fields and save to add it to the media library.', 'The media items have been created but have not yet been saved. Fill in any required fields and save to add them to the media library.'),
|
||||
'#attributes' => [
|
||||
'class' => [
|
||||
'media-library-add-form__description',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($added_media as $delta => $media) {
|
||||
$form['media'][$delta] = $this->buildEntityFormElement($media, $form, $form_state, $delta);
|
||||
}
|
||||
|
||||
$form['selection'] = $this->buildCurrentSelectionArea($form, $form_state);
|
||||
$form['actions'] = $this->buildActions($form, $form_state);
|
||||
}
|
||||
|
||||
// Allow the current selection to be set in a hidden field so the selection
|
||||
// can be passed between different states of the form. This field is filled
|
||||
// via JavaScript so the default value should be empty.
|
||||
// @see Drupal.behaviors.MediaLibraryItemSelection
|
||||
$form['current_selection'] = [
|
||||
'#type' => 'hidden',
|
||||
'#default_value' => '',
|
||||
'#attributes' => [
|
||||
'class' => [
|
||||
'js-media-library-add-form-current-selection',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
|
@ -309,6 +350,90 @@ abstract class AddFormBase extends FormBase {
|
|||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a render array containing the current selection.
|
||||
*
|
||||
* @param array $form
|
||||
* The complete form.
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
* The current form state.
|
||||
*
|
||||
* @return array
|
||||
* A render array containing the current selection.
|
||||
*/
|
||||
protected function buildCurrentSelectionArea(array $form, FormStateInterface $form_state) {
|
||||
$pre_selected_items = $this->getPreSelectedMediaItems($form_state);
|
||||
|
||||
if (!$pre_selected_items) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$selection = [
|
||||
'#type' => 'details',
|
||||
'#open' => FALSE,
|
||||
'#title' => $this->t('Additional selected media'),
|
||||
'#attributes' => [
|
||||
'class' => [
|
||||
'media-library-add-form__selected-media',
|
||||
],
|
||||
],
|
||||
];
|
||||
foreach ($pre_selected_items as $media_id => $media) {
|
||||
$selection[$media_id] = $this->buildSelectedItemElement($media, $form, $form_state);
|
||||
}
|
||||
|
||||
return $selection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a render array for a single pre-selected media item.
|
||||
*
|
||||
* @param \Drupal\media\MediaInterface $media
|
||||
* The media item.
|
||||
* @param array $form
|
||||
* The complete form.
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
* The current form state.
|
||||
*
|
||||
* @return array
|
||||
* A render array of a pre-selected media item.
|
||||
*/
|
||||
protected function buildSelectedItemElement(MediaInterface $media, array $form, FormStateInterface $form_state) {
|
||||
return [
|
||||
'#type' => 'container',
|
||||
'#attributes' => [
|
||||
'class' => [
|
||||
'media-library-item',
|
||||
'media-library-item--grid',
|
||||
'media-library-item--small',
|
||||
'js-media-library-item',
|
||||
'js-click-to-select',
|
||||
],
|
||||
],
|
||||
'select' => [
|
||||
'#type' => 'container',
|
||||
'#attributes' => [
|
||||
'class' => [
|
||||
'js-click-to-select-checkbox',
|
||||
],
|
||||
],
|
||||
'select_checkbox' => [
|
||||
'#type' => 'checkbox',
|
||||
'#title' => $this->t('Select @name', ['@name' => $media->label()]),
|
||||
'#title_display' => 'invisible',
|
||||
'#return_value' => $media->id(),
|
||||
// The checkbox's value is never processed by this form. It is present
|
||||
// for usability and accessibility reasons, and only used by
|
||||
// JavaScript to track whether or not this media item is selected. The
|
||||
// hidden 'current_selection' field is used to store the actual IDs of
|
||||
// selected media items.
|
||||
'#value' => FALSE,
|
||||
],
|
||||
],
|
||||
'rendered_entity' => $this->viewBuilder->view($media, 'media_library'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of supported actions for the form.
|
||||
*
|
||||
|
@ -323,9 +448,18 @@ abstract class AddFormBase extends FormBase {
|
|||
protected function buildActions(array $form, FormStateInterface $form_state) {
|
||||
return [
|
||||
'#type' => 'actions',
|
||||
'submit' => [
|
||||
'save_select' => [
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Save'),
|
||||
'#button_type' => 'primary',
|
||||
'#value' => $this->t('Save and select'),
|
||||
'#ajax' => [
|
||||
'callback' => '::updateLibrary',
|
||||
'wrapper' => 'media-library-add-form-wrapper',
|
||||
],
|
||||
],
|
||||
'save_insert' => [
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Save and insert'),
|
||||
'#ajax' => [
|
||||
'callback' => '::updateWidget',
|
||||
'wrapper' => 'media-library-add-form-wrapper',
|
||||
|
@ -352,7 +486,11 @@ abstract class AddFormBase extends FormBase {
|
|||
return $this->createMediaFromValue($media_type, $media_storage, $source_field_name, $source_field_value);
|
||||
}, $source_field_values);
|
||||
// Re-key the media items before setting them in the form state.
|
||||
$form_state->set('media', array_values($media))->setRebuild();
|
||||
$form_state->set('media', array_values($media));
|
||||
// Save the selected items in the form state so they are remembered when an
|
||||
// item is removed.
|
||||
$form_state->set('current_selection', array_filter(explode(',', $form_state->getValue('current_selection'))));
|
||||
$form_state->setRebuild();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -485,8 +623,7 @@ abstract class AddFormBase extends FormBase {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateForm(array &$form, FormStateInterface $form_state) {
|
||||
$added_media = $form_state->get('media') ?: [];
|
||||
foreach ($added_media as $delta => $media) {
|
||||
foreach ($this->getAddedMediaItems($form_state) as $delta => $media) {
|
||||
$this->validateMediaEntity($media, $form, $form_state, $delta);
|
||||
}
|
||||
}
|
||||
|
@ -513,8 +650,7 @@ abstract class AddFormBase extends FormBase {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$added_media = $form_state->get('media') ?: [];
|
||||
foreach ($added_media as $delta => $media) {
|
||||
foreach ($this->getAddedMediaItems($form_state) as $delta => $media) {
|
||||
EntityFormDisplay::collectRenderDisplay($media, 'media_library')
|
||||
->extractFormValues($media, $form['media'][$delta]['fields'], $form_state);
|
||||
$this->prepareMediaEntityForSave($media);
|
||||
|
@ -523,7 +659,7 @@ abstract class AddFormBase extends FormBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* AJAX callback to send the new media item(s) to the calling code.
|
||||
* AJAX callback to send the new media item(s) to the media library.
|
||||
*
|
||||
* @param array $form
|
||||
* The complete form.
|
||||
|
@ -531,18 +667,17 @@ abstract class AddFormBase extends FormBase {
|
|||
* The current form state.
|
||||
*
|
||||
* @return array|\Drupal\Core\Ajax\AjaxResponse
|
||||
* The form array when there are form errors or a AJAX response to select
|
||||
* the created items in the media library.
|
||||
* The form array if there are validation errors, or an AJAX response to add
|
||||
* the created items to the current selection.
|
||||
*/
|
||||
public function updateWidget(array &$form, FormStateInterface $form_state) {
|
||||
public function updateLibrary(array &$form, FormStateInterface $form_state) {
|
||||
if ($form_state::hasAnyErrors()) {
|
||||
return $form;
|
||||
}
|
||||
|
||||
$added_media = $form_state->get('media') ?: [];
|
||||
$media_ids = array_map(function (MediaInterface $media) {
|
||||
return $media->id();
|
||||
}, $added_media);
|
||||
}, $this->getAddedMediaItems($form_state));
|
||||
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new UpdateSelectionCommand($media_ids));
|
||||
|
@ -572,6 +707,39 @@ abstract class AddFormBase extends FormBase {
|
|||
return $this->libraryUiBuilder->buildUi($state);
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX callback to send the new media item(s) to the calling code.
|
||||
*
|
||||
* @param array $form
|
||||
* The complete form.
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
* The current form state.
|
||||
*
|
||||
* @return array|\Drupal\Core\Ajax\AjaxResponse
|
||||
* The form array when there are form errors or a AJAX response to select
|
||||
* the created items in the media library.
|
||||
*/
|
||||
public function updateWidget(array &$form, FormStateInterface $form_state) {
|
||||
if ($form_state::hasAnyErrors()) {
|
||||
return $form;
|
||||
}
|
||||
|
||||
// Pass the selection to the field widget based on the current widget ID.
|
||||
$opener_id = $this->getMediaLibraryState($form_state)->getOpenerId();
|
||||
if ($field_id = MediaLibraryWidget::getOpenerFieldId($opener_id)) {
|
||||
// The added media items get an ID when they are saved in ::submitForm().
|
||||
// For that reason the added media items are keyed by delta in the form
|
||||
// state and we have to do an array map to get each media ID.
|
||||
$current_media_ids = array_map(function (MediaInterface $media) {
|
||||
return $media->id();
|
||||
}, $this->getCurrentMediaItems($form_state));
|
||||
return (new AjaxResponse())
|
||||
->addCommand(new InvokeCommand("[data-media-library-widget-value=\"$field_id\"]", 'val', [implode(',', $current_media_ids)]))
|
||||
->addCommand(new InvokeCommand("[data-media-library-widget-update=\"$field_id\"]", 'trigger', ['mousedown']))
|
||||
->addCommand(new CloseDialogCommand());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the media library state from the form state.
|
||||
*
|
||||
|
@ -607,4 +775,54 @@ abstract class AddFormBase extends FormBase {
|
|||
->getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all pre-selected media items from the form state.
|
||||
*
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
* The current form state.
|
||||
*
|
||||
* @return \Drupal\media\MediaInterface[]
|
||||
* An array containing the pre-selected media items keyed by ID.
|
||||
*/
|
||||
protected function getPreSelectedMediaItems(FormStateInterface $form_state) {
|
||||
// Get the current selection from the form state.
|
||||
// @see ::processInputValues()
|
||||
$media_ids = $form_state->get('current_selection');
|
||||
if (!$media_ids) {
|
||||
return [];
|
||||
}
|
||||
return $this->entityTypeManager->getStorage('media')->loadMultiple($media_ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all added media items from the form state.
|
||||
*
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
* The current form state.
|
||||
*
|
||||
* @return \Drupal\media\MediaInterface[]
|
||||
* An array containing the added media items keyed by delta. The media items
|
||||
* won't have an ID untill they are saved in ::submitForm().
|
||||
*/
|
||||
protected function getAddedMediaItems(FormStateInterface $form_state) {
|
||||
return $form_state->get('media') ?: [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all pre-selected and added media items from the form state.
|
||||
*
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
* The current form state.
|
||||
*
|
||||
* @return \Drupal\media\MediaInterface[]
|
||||
* An array containing all pre-selected and added media items with
|
||||
* renumbered numeric keys.
|
||||
*/
|
||||
protected function getCurrentMediaItems(FormStateInterface $form_state) {
|
||||
$pre_selected_media = $this->getPreSelectedMediaItems($form_state);
|
||||
$added_media = $this->getAddedMediaItems($form_state);
|
||||
// Using array_merge will renumber the numeric keys.
|
||||
return array_merge($pre_selected_media, $added_media);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -199,6 +199,14 @@ class FileUploadForm extends AddFormBase {
|
|||
*/
|
||||
public function processUploadElement(array $element, FormStateInterface $form_state) {
|
||||
$element['upload_button']['#submit'] = ['::uploadButtonSubmit'];
|
||||
// Limit the validation errors to make sure
|
||||
// FormValidator::handleErrorsWithLimitedValidation doesn't remove the
|
||||
// current selection from the form state.
|
||||
// @see Drupal\Core\Form\FormValidator::handleErrorsWithLimitedValidation()
|
||||
$element['upload_button']['#limit_validation_errors'] = [
|
||||
['upload'],
|
||||
['current_selection'],
|
||||
];
|
||||
$element['upload_button']['#ajax'] = [
|
||||
'callback' => '::updateFormCallback',
|
||||
'wrapper' => 'media-library-wrapper',
|
||||
|
|
|
@ -97,7 +97,8 @@ class MediaLibrarySelectForm extends FieldPluginBase {
|
|||
'callback' => [static::class, 'updateWidget'],
|
||||
];
|
||||
|
||||
$form['actions']['submit']['#value'] = $this->t('Select media');
|
||||
$form['actions']['submit']['#value'] = $this->t('Insert selected');
|
||||
$form['actions']['submit']['#button_type'] = 'primary';
|
||||
$form['actions']['submit']['#field_id'] = $selection_field_id;
|
||||
// By default, the AJAX system tries to move the focus back to the element
|
||||
// that triggered the AJAX request. Since the media library is closed after
|
||||
|
|
|
@ -317,7 +317,7 @@ class MediaLibraryTest extends WebDriverTestBase {
|
|||
$assert_session->elementNotExists('css', '.media-library-view .media-library-item--table');
|
||||
// Assert the 'Apply filter' button is not moved to the button pane.
|
||||
$button_pane = $assert_session->elementExists('css', '.ui-dialog-buttonpane');
|
||||
$assert_session->buttonExists('Select media', $button_pane);
|
||||
$assert_session->buttonExists('Insert selected', $button_pane);
|
||||
$assert_session->buttonNotExists('Apply filters', $button_pane);
|
||||
$assert_session->linkExists('Grid');
|
||||
$page->clickLink('Table');
|
||||
|
@ -327,7 +327,7 @@ class MediaLibraryTest extends WebDriverTestBase {
|
|||
$this->assertNotEmpty($assert_session->waitForElementVisible('css', '.media-library-view .media-library-item--table'));
|
||||
$assert_session->elementNotExists('css', '.media-library-view .media-library-item--grid');
|
||||
// Assert the 'Apply filter' button is not moved to the button pane.
|
||||
$assert_session->buttonExists('Select media', $button_pane);
|
||||
$assert_session->buttonExists('Insert selected', $button_pane);
|
||||
$assert_session->buttonNotExists('Apply filters', $button_pane);
|
||||
$assert_session->pageTextContains('Dog');
|
||||
$assert_session->pageTextContains('Bear');
|
||||
|
@ -355,7 +355,7 @@ class MediaLibraryTest extends WebDriverTestBase {
|
|||
$assert_session->linkExists('Grid');
|
||||
$assert_session->linkExists('Table');
|
||||
// Select the item.
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Select media');
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Insert selected');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
// Ensure that the selection completed successfully.
|
||||
$assert_session->pageTextNotContains('Add or select media');
|
||||
|
@ -373,7 +373,7 @@ class MediaLibraryTest extends WebDriverTestBase {
|
|||
$checkboxes = $page->findAll('css', '.media-library-view .js-click-to-select-checkbox input');
|
||||
$this->assertGreaterThanOrEqual(1, count($checkboxes));
|
||||
$checkboxes[0]->click();
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Select media');
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Insert selected');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
// Assert the focus is set back on the open button of the media field.
|
||||
$this->assertJsCondition('jQuery("#field_twin_media-media-library-wrapper .js-media-library-open-button").is(":focus")');
|
||||
|
@ -453,7 +453,7 @@ class MediaLibraryTest extends WebDriverTestBase {
|
|||
$this->assertTrue($checkboxes[2]->hasAttribute('disabled'));
|
||||
$this->assertTrue($checkboxes[3]->hasAttribute('disabled'));
|
||||
// Select the items.
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Select media');
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Insert selected');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
// Assert the open button is disabled.
|
||||
$open_button = $assert_session->elementExists('css', '.media-library-open-button[name^="field_twin_media"]');
|
||||
|
@ -488,7 +488,7 @@ class MediaLibraryTest extends WebDriverTestBase {
|
|||
$checkboxes = $page->findAll('css', '.media-library-view .js-click-to-select-checkbox input');
|
||||
$this->assertGreaterThanOrEqual(1, count($checkboxes));
|
||||
$checkboxes[0]->click();
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Select media');
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Insert selected');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$assert_session->pageTextContains('Dog');
|
||||
$assert_session->pageTextNotContains('Cat');
|
||||
|
@ -566,7 +566,7 @@ class MediaLibraryTest extends WebDriverTestBase {
|
|||
$checkboxes[1]->click();
|
||||
$checkboxes[2]->click();
|
||||
$checkboxes[3]->click();
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Select media');
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Insert selected');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$assert_session->pageTextContains('Dog');
|
||||
$assert_session->pageTextContains('Cat');
|
||||
|
@ -609,7 +609,7 @@ class MediaLibraryTest extends WebDriverTestBase {
|
|||
|
||||
// Select the first media item (should be Dog).
|
||||
$page->find('css', '.media-library-view .js-click-to-select-checkbox input')->click();
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Select media');
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Insert selected');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
|
||||
// Ensure that the selection completed successfully.
|
||||
|
@ -712,38 +712,37 @@ class MediaLibraryTest extends WebDriverTestBase {
|
|||
$assert_session->elementNotExists('css', '.media-library-add-form--with-input');
|
||||
$page->attachFileToField('Add files', $this->container->get('file_system')->realpath($png_image->uri));
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$this->assertJsCondition('jQuery(".media-library-add-form__added-media").is(":focus")');
|
||||
$assert_session->pageTextContains('The media item has been created but has not yet been saved. Fill in any required fields and save to add it to the media library.');
|
||||
$assert_session->elementAttributeContains('css', '.media-library-add-form__added-media', 'aria-label', 'Added media items');
|
||||
$assert_session->elementExists('css', '.media-library-add-form--with-input');
|
||||
$assert_session->elementNotExists('css', '.media-library-add-form--without-input');
|
||||
|
||||
// We do not have a pre-selected items, so the container should not be added
|
||||
// to the form.
|
||||
$assert_session->elementNotExists('css', '.media-library-add-form__selected-media');
|
||||
// Files are temporary until the form is saved.
|
||||
$files = $file_storage->loadMultiple();
|
||||
$file = array_pop($files);
|
||||
$this->assertSame('public://type-three-dir', $file_system->dirname($file->getFileUri()));
|
||||
$this->assertTrue($file->isTemporary());
|
||||
|
||||
// Assert the revision_log_message field is not shown.
|
||||
$upload_form = $assert_session->elementExists('css', '.media-library-add-form');
|
||||
$assert_session->fieldNotExists('Revision log message', $upload_form);
|
||||
|
||||
// Assert the name field contains the filename and the alt text is required.
|
||||
$assert_session->fieldValueEquals('Name', $png_image->filename);
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Save');
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Save and select');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$assert_session->pageTextContains('Alternative text field is required');
|
||||
$page->fillField('Alternative text', $this->randomString());
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Save');
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Save and select');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
|
||||
// The file should be permanent now.
|
||||
$files = $file_storage->loadMultiple();
|
||||
$file = array_pop($files);
|
||||
$this->assertFalse($file->isTemporary());
|
||||
|
||||
// Load the created media item.
|
||||
$media_storage = $this->container->get('entity_type.manager')->getStorage('media');
|
||||
$media_items = $media_storage->loadMultiple();
|
||||
$media_items = Media::loadMultiple();
|
||||
$added_media = array_pop($media_items);
|
||||
|
||||
// Ensure the media item was saved to the library and automatically
|
||||
// selected. The added media items should be in the first position of the
|
||||
// add form.
|
||||
|
@ -752,37 +751,60 @@ class MediaLibraryTest extends WebDriverTestBase {
|
|||
$assert_session->fieldValueEquals('media_library_select_form[0]', $added_media->id());
|
||||
$assert_session->checkboxChecked('media_library_select_form[0]');
|
||||
$assert_session->pageTextContains('1 of 2 items selected');
|
||||
|
||||
$assert_session->hiddenFieldValueEquals('current_selection', $added_media->id());
|
||||
// Ensure the created item is added in the widget.
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Select media');
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Insert selected');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$assert_session->pageTextNotContains('Add or select media');
|
||||
$assert_session->pageTextContains($png_image->filename);
|
||||
|
||||
// Remove the item.
|
||||
$assert_session->elementExists('css', '.media-library-item__remove')->click();
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$assert_session->pageTextNotContains($png_image->filename);
|
||||
|
||||
// Assert we can also directly insert uploaded files in the widget.
|
||||
$assert_session->elementExists('css', '.media-library-open-button[name^="field_twin_media"]')->click();
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$assert_session->pageTextContains('Add or select media');
|
||||
$page->clickLink('Type Three');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$png_uri_2 = $file_system->copy($png_image->uri);
|
||||
$page->attachFileToField('Add files', $this->container->get('file_system')->realpath($png_uri_2));
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$page->fillField('Alternative text', $this->randomString());
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Save and insert');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$assert_session->pageTextNotContains('Add or select media');
|
||||
$assert_session->pageTextContains($file_system->basename($png_uri_2));
|
||||
|
||||
// Also make sure that we can upload to the unlimited cardinality field.
|
||||
$assert_session->elementExists('css', '.media-library-open-button[name^="field_unlimited_media"]')->click();
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$assert_session->pageTextContains('Add or select media');
|
||||
|
||||
// Navigate to the media type three tab first.
|
||||
$page->clickLink('Type Three');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
|
||||
// Select a media item.
|
||||
$page->find('css', '.media-library-view .js-click-to-select-checkbox input')->click();
|
||||
// Select a media item to check if the selection is persisted when adding
|
||||
// new items.
|
||||
$existing_media_name = $file_system->basename($png_uri_2);
|
||||
$checkbox = $page->findField("Select $existing_media_name");
|
||||
$selected_item_id = $checkbox->getAttribute('value');
|
||||
$checkbox->click();
|
||||
$assert_session->pageTextContains('1 item selected');
|
||||
$page->attachFileToField('Add files', $this->container->get('file_system')->realpath($png_image->uri));
|
||||
$assert_session->hiddenFieldValueEquals('current_selection', $selected_item_id);
|
||||
$png_uri_3 = $file_system->copy($png_image->uri);
|
||||
$page->attachFileToField('Add files', $this->container->get('file_system')->realpath($png_uri_3));
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$assert_session->checkboxChecked("Select $existing_media_name");
|
||||
$page->fillField('Name', 'Unlimited Cardinality Image');
|
||||
$page->fillField('Alternative text', $this->randomString());
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Save');
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Save and select');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
|
||||
// Load the created media item.
|
||||
$media_storage = $this->container->get('entity_type.manager')->getStorage('media');
|
||||
$media_items = $media_storage->loadMultiple();
|
||||
$media_items = Media::loadMultiple();
|
||||
$added_media = array_pop($media_items);
|
||||
|
||||
$added_media_name = $added_media->label();
|
||||
// Ensure the media item was saved to the library and automatically
|
||||
// selected. The added media items should be in the first position of the
|
||||
// add form.
|
||||
|
@ -790,69 +812,102 @@ class MediaLibraryTest extends WebDriverTestBase {
|
|||
$assert_session->pageTextContains('Unlimited Cardinality Image');
|
||||
$assert_session->fieldValueEquals('media_library_select_form[0]', $added_media->id());
|
||||
$assert_session->checkboxChecked('media_library_select_form[0]');
|
||||
|
||||
// Assert the item that was selected before uploading the file is still
|
||||
// selected.
|
||||
$assert_session->pageTextContains('2 items selected');
|
||||
$assert_session->checkboxChecked("Select $added_media_name");
|
||||
$assert_session->checkboxChecked("Select $existing_media_name");
|
||||
$assert_session->hiddenFieldValueEquals('current_selection', implode(',', [$selected_item_id, $added_media->id()]));
|
||||
$checkboxes = $page->findAll('css', '.media-library-view .js-click-to-select-checkbox input');
|
||||
$selected_checkboxes = [];
|
||||
foreach ($checkboxes as $checkbox) {
|
||||
if ($checkbox->isChecked()) {
|
||||
$selected_checkboxes[] = $checkbox->getValue();
|
||||
$selected_checkboxes[] = $checkbox->getAttribute('value');
|
||||
}
|
||||
}
|
||||
$this->assertCount(2, $selected_checkboxes);
|
||||
|
||||
// Ensure the created item is added in the widget.
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Select media');
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Insert selected');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$assert_session->pageTextNotContains('Add or select media');
|
||||
$assert_session->pageTextContains('Unlimited Cardinality Image');
|
||||
|
||||
// Verify we can only upload the files allowed by the media type.
|
||||
// Assert we can now only upload one more media item.
|
||||
$assert_session->elementExists('css', '.media-library-open-button[name^="field_twin_media"]')->click();
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$assert_session->pageTextContains('Add or select media');
|
||||
$page->clickLink('Type Four');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
|
||||
// Assert we can now only upload one more media item.
|
||||
$this->assertFalse($assert_session->fieldExists('Add file')->hasAttribute('multiple'));
|
||||
$assert_session->pageTextContains('One file only.');
|
||||
|
||||
// Assert media type four should only allow jpg files by trying a png file
|
||||
// first.
|
||||
$page->attachFileToField('Add file', $file_system->realpath($png_image->uri));
|
||||
$png_uri_4 = $file_system->copy($png_image->uri);
|
||||
$page->attachFileToField('Add file', $file_system->realpath($png_uri_4));
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$assert_session->pageTextContains('Only files with the following extensions are allowed');
|
||||
|
||||
// Assert that jpg files are accepted by type four.
|
||||
$page->attachFileToField('Add file', $file_system->realpath($jpg_image->uri));
|
||||
$jpg_uri_2 = $file_system->copy($jpg_image->uri);
|
||||
$page->attachFileToField('Add file', $file_system->realpath($jpg_uri_2));
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$page->fillField('Alternative text', $this->randomString());
|
||||
|
||||
// The type_four media type has another optional image field.
|
||||
$assert_session->pageTextContains('Extra Image');
|
||||
$page->attachFileToField('Extra Image', $this->container->get('file_system')->realpath($jpg_image->uri));
|
||||
$jpg_uri_3 = $file_system->copy($jpg_image->uri);
|
||||
$page->attachFileToField('Extra Image', $this->container->get('file_system')->realpath($jpg_uri_3));
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
// Ensure that the extra image was uploaded to the correct directory.
|
||||
$files = $file_storage->loadMultiple();
|
||||
$file = array_pop($files);
|
||||
$this->assertSame('public://type-four-extra-dir', $file_system->dirname($file->getFileUri()));
|
||||
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Save');
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Save and select');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
|
||||
// Ensure the media item was saved to the library and automatically
|
||||
// selected.
|
||||
$assert_session->pageTextContains('Add or select media');
|
||||
$assert_session->pageTextContains($jpg_image->filename);
|
||||
|
||||
$assert_session->pageTextContains($file_system->basename($jpg_uri_2));
|
||||
// Ensure the created item is added in the widget.
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Select media');
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Insert selected');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$assert_session->pageTextNotContains('Add or select media');
|
||||
$assert_session->pageTextContains($jpg_image->filename);
|
||||
$assert_session->pageTextContains($file_system->basename($jpg_uri_2));
|
||||
|
||||
// Assert we can also remove selected items from the selection area in the
|
||||
// upload form.
|
||||
$assert_session->elementExists('css', '.media-library-open-button[name^="field_unlimited_media"]')->click();
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$assert_session->pageTextContains('Add or select media');
|
||||
$page->clickLink('Type Three');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$checkbox = $page->findField("Select $existing_media_name");
|
||||
$selected_item_id = $checkbox->getAttribute('value');
|
||||
$checkbox->click();
|
||||
$assert_session->hiddenFieldValueEquals('current_selection', $selected_item_id);
|
||||
$this->assertTrue($assert_session->fieldExists('Add files')->hasAttribute('multiple'));
|
||||
$png_uri_5 = $file_system->copy($png_image->uri);
|
||||
$page->attachFileToField('Add files', $this->container->get('file_system')->realpath($png_uri_5));
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
// Assert the pre-selected items are shown.
|
||||
$selection_area = $assert_session->elementExists('css', '.media-library-add-form__selected-media');
|
||||
$assert_session->elementExists('css', 'summary', $selection_area)->click();
|
||||
$assert_session->checkboxChecked("Select $existing_media_name", $selection_area);
|
||||
$page->uncheckField("Select $existing_media_name");
|
||||
$page->fillField('Alternative text', $this->randomString());
|
||||
$assert_session->hiddenFieldValueEquals('current_selection', '');
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Save and select');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$media_items = Media::loadMultiple();
|
||||
$added_media = array_pop($media_items);
|
||||
$added_media_name = $added_media->label();
|
||||
$assert_session->pageTextContains('1 item selected');
|
||||
$assert_session->checkboxChecked("Select $added_media_name");
|
||||
$assert_session->checkboxNotChecked("Select $existing_media_name");
|
||||
$assert_session->hiddenFieldValueEquals('current_selection', $added_media->id());
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Insert selected');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$assert_session->pageTextNotContains('Add or select media');
|
||||
$assert_session->pageTextContains($file_system->basename($png_uri_5));
|
||||
|
||||
// Assert removing an uploaded media item before save works as expected.
|
||||
$assert_session->elementExists('css', '.media-library-open-button[name^="field_unlimited_media"]')->click();
|
||||
|
@ -887,6 +942,10 @@ class MediaLibraryTest extends WebDriverTestBase {
|
|||
$assert_session->pageTextContains('Add or select media');
|
||||
$page->clickLink('Type Three');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
// Assert the existing items are remembered when adding and removing media.
|
||||
$checkbox = $page->findField("Select $existing_media_name");
|
||||
$checkbox->click();
|
||||
// Assert we can add multiple files.
|
||||
$this->assertTrue($assert_session->fieldExists('Add files')->hasAttribute('multiple'));
|
||||
// Create a list of new files to upload.
|
||||
$filenames = [];
|
||||
|
@ -906,6 +965,10 @@ class MediaLibraryTest extends WebDriverTestBase {
|
|||
$assert_session->fieldValueEquals('media[0][fields][name][0][value]', $filenames[0]);
|
||||
$assert_session->fieldValueEquals('media[1][fields][name][0][value]', $filenames[1]);
|
||||
$assert_session->fieldValueEquals('media[2][fields][name][0][value]', $filenames[2]);
|
||||
// Assert the pre-selected items are shown.
|
||||
$selection_area = $assert_session->elementExists('css', '.media-library-add-form__selected-media');
|
||||
$assert_session->elementExists('css', 'summary', $selection_area)->click();
|
||||
$assert_session->checkboxChecked("Select $existing_media_name", $selection_area);
|
||||
// Set alt texts for items 1 and 2, leave the alt text empty for item 3 to
|
||||
// assert the field validation does not stop users from removing items.
|
||||
$page->fillField('media[0][fields][field_media_test_image][0][alt]', $filenames[0]);
|
||||
|
@ -924,6 +987,10 @@ class MediaLibraryTest extends WebDriverTestBase {
|
|||
$media_item_three = $assert_session->elementExists('css', '.media-library-add-form__media[data-media-library-added-delta=2]');
|
||||
$assert_session->fieldValueEquals('Name', $filenames[2], $media_item_three);
|
||||
$assert_session->fieldValueEquals('Alternative text', '', $media_item_three);
|
||||
// Assert the pre-selected items are still shown.
|
||||
$selection_area = $assert_session->elementExists('css', '.media-library-add-form__selected-media');
|
||||
$assert_session->elementExists('css', 'summary', $selection_area)->click();
|
||||
$assert_session->checkboxChecked("Select $existing_media_name", $selection_area);
|
||||
// Remove the last file and assert the focus is shifted to the container
|
||||
// of the first media item and field values are still correct.
|
||||
$page->pressButton('media-2-remove-button');
|
||||
|
@ -943,9 +1010,11 @@ class MediaLibraryTest extends WebDriverTestBase {
|
|||
$assert_session = $this->assertSession();
|
||||
$page = $this->getSession()->getPage();
|
||||
|
||||
$video_title = "Everyday I'm Drupalin' Drupal Rap (Rick Ross - Hustlin)";
|
||||
$video_url = 'https://www.youtube.com/watch?v=PWjcqE3QKBg';
|
||||
ResourceController::setResourceUrl($video_url, $this->getFixturesDirectory() . '/video_youtube.json');
|
||||
$youtube_title = "Everyday I'm Drupalin' Drupal Rap (Rick Ross - Hustlin)";
|
||||
$youtube_url = 'https://www.youtube.com/watch?v=PWjcqE3QKBg';
|
||||
$vimeo_title = "Drupal Rap Video - Schipulcon09";
|
||||
$vimeo_url = 'https://vimeo.com/7073899';
|
||||
ResourceController::setResourceUrl($youtube_url, $this->getFixturesDirectory() . '/video_youtube.json');
|
||||
|
||||
// Visit a node create page.
|
||||
$this->drupalGet('node/add/basic_page');
|
||||
|
@ -966,33 +1035,32 @@ class MediaLibraryTest extends WebDriverTestBase {
|
|||
// Assert we can add an oEmbed video to media type five.
|
||||
$page->clickLink('Type Five');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$page->fillField('Add Type Five via URL', $video_url);
|
||||
$page->fillField('Add Type Five via URL', $youtube_url);
|
||||
$assert_session->pageTextContains('Allowed providers: YouTube, Vimeo.');
|
||||
$page->pressButton('Add');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
// Assert the name field contains the remote video title.
|
||||
$assert_session->fieldValueEquals('Name', $video_title);
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Save');
|
||||
$assert_session->fieldValueEquals('Name', $youtube_title);
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Save and select');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
|
||||
// Load the created media item.
|
||||
$media_storage = $this->container->get('entity_type.manager')->getStorage('media');
|
||||
$media_items = $media_storage->loadMultiple();
|
||||
$media_items = Media::loadMultiple();
|
||||
$added_media = array_pop($media_items);
|
||||
|
||||
// Ensure the media item was saved to the library and automatically
|
||||
// selected. The added media items should be in the first position of the
|
||||
// add form.
|
||||
$assert_session->pageTextContains('Add or select media');
|
||||
$assert_session->pageTextContains($video_title);
|
||||
$assert_session->pageTextContains($youtube_title);
|
||||
$assert_session->fieldValueEquals('media_library_select_form[0]', $added_media->id());
|
||||
$assert_session->checkboxChecked('media_library_select_form[0]');
|
||||
|
||||
// Assert the created oEmbed video is correctly added to the widget.
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Select media');
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Insert selected');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$assert_session->pageTextNotContains('Add or select media');
|
||||
$assert_session->pageTextContains($video_title);
|
||||
$assert_session->pageTextContains($youtube_title);
|
||||
|
||||
// Open the media library again for the unlimited field and go to the tab
|
||||
// for media type five.
|
||||
|
@ -1003,7 +1071,7 @@ class MediaLibraryTest extends WebDriverTestBase {
|
|||
$assert_session->assertWaitOnAjaxRequest();
|
||||
|
||||
// Assert the video is available on the tab.
|
||||
$assert_session->pageTextContains($video_title);
|
||||
$assert_session->pageTextContains($youtube_title);
|
||||
|
||||
// Assert we can only add supported URLs.
|
||||
$page->fillField('Add Type Five via URL', 'https://www.youtube.com/');
|
||||
|
@ -1018,29 +1086,108 @@ class MediaLibraryTest extends WebDriverTestBase {
|
|||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$assert_session->pageTextContains('Could not retrieve the oEmbed resource.');
|
||||
|
||||
// Select a media item to check if the selection is persisted when adding
|
||||
// new items.
|
||||
$checkbox = $page->findField("Select $youtube_title");
|
||||
$selected_item_id = $checkbox->getAttribute('value');
|
||||
$checkbox->click();
|
||||
$assert_session->pageTextContains('1 item selected');
|
||||
$assert_session->hiddenFieldValueEquals('current_selection', $selected_item_id);
|
||||
|
||||
// Assert we can add a oEmbed video with a custom name.
|
||||
$page->fillField('Add Type Five via URL', $video_url);
|
||||
$page->fillField('Add Type Five via URL', $youtube_url);
|
||||
$page->pressButton('Add');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$page->fillField('Name', 'Custom video title');
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Save');
|
||||
$selection_area = $assert_session->elementExists('css', '.media-library-add-form__selected-media');
|
||||
$assert_session->checkboxChecked("Select $youtube_title", $selection_area);
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Save and select');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
|
||||
// Load the created media item.
|
||||
$media_items = Media::loadMultiple();
|
||||
$added_media = array_pop($media_items);
|
||||
// Ensure the media item was saved to the library and automatically
|
||||
// selected. The added media items should be in the first position of the
|
||||
// add form.
|
||||
$assert_session->pageTextContains('Add or select media');
|
||||
$assert_session->pageTextContains('Custom video title');
|
||||
|
||||
// Assert the created oEmbed video is correctly added to the widget.
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Select media');
|
||||
$assert_session->fieldValueEquals('media_library_select_form[0]', $added_media->id());
|
||||
$assert_session->checkboxChecked('media_library_select_form[0]');
|
||||
// Assert the item that was selected before uploading the file is still
|
||||
// selected.
|
||||
$assert_session->pageTextContains('2 items selected');
|
||||
$assert_session->checkboxChecked("Select Custom video title");
|
||||
$assert_session->checkboxChecked("Select $youtube_title");
|
||||
$assert_session->hiddenFieldValueEquals('current_selection', implode(',', [$selected_item_id, $added_media->id()]));
|
||||
$checkboxes = $page->findAll('css', '.media-library-view .js-click-to-select-checkbox input');
|
||||
$selected_checkboxes = [];
|
||||
foreach ($checkboxes as $checkbox) {
|
||||
if ($checkbox->isChecked()) {
|
||||
$selected_checkboxes[] = $checkbox->getAttribute('value');
|
||||
}
|
||||
}
|
||||
$this->assertCount(2, $selected_checkboxes);
|
||||
// Ensure the created item is added in the widget.
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Insert selected');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$assert_session->pageTextNotContains('Add or select media');
|
||||
$assert_session->pageTextContains('Custom video title');
|
||||
|
||||
// Assert we can directly insert added oEmbed media in the widget.
|
||||
$assert_session->elementExists('css', '.media-library-open-button[name^="field_unlimited_media"]')->click();
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$assert_session->pageTextContains('Add or select media');
|
||||
$page->clickLink('Type Five');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$page->fillField('Add Type Five via URL', $vimeo_url);
|
||||
$page->pressButton('Add');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Save and insert');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$assert_session->pageTextNotContains('Add or select media');
|
||||
$assert_session->pageTextContains($vimeo_title);
|
||||
|
||||
// Assert we can remove selected items from the selection area in the oEmbed
|
||||
// form.
|
||||
$assert_session->elementExists('css', '.media-library-open-button[name^="field_unlimited_media"]')->click();
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$assert_session->pageTextContains('Add or select media');
|
||||
$page->clickLink('Type Five');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$checkbox = $page->findField("Select $vimeo_title");
|
||||
$selected_item_id = $checkbox->getAttribute('value');
|
||||
$checkbox->click();
|
||||
$assert_session->hiddenFieldValueEquals('current_selection', $selected_item_id);
|
||||
$page->fillField('Add Type Five via URL', $youtube_url);
|
||||
$page->pressButton('Add');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$page->fillField('Name', 'Another video');
|
||||
$selection_area = $assert_session->elementExists('css', '.media-library-add-form__selected-media');
|
||||
$assert_session->elementExists('css', 'summary', $selection_area)->click();
|
||||
$assert_session->checkboxChecked("Select $vimeo_title", $selection_area);
|
||||
$page->uncheckField("Select $vimeo_title");
|
||||
$assert_session->hiddenFieldValueEquals('current_selection', '');
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Save and select');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$media_items = Media::loadMultiple();
|
||||
$added_media = array_pop($media_items);
|
||||
$assert_session->pageTextContains('1 item selected');
|
||||
$assert_session->checkboxChecked('Select Another video');
|
||||
$assert_session->checkboxNotChecked("Select $vimeo_title");
|
||||
$assert_session->hiddenFieldValueEquals('current_selection', $added_media->id());
|
||||
$assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Insert selected');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$assert_session->pageTextNotContains('Add or select media');
|
||||
$assert_session->pageTextContains('Another video');
|
||||
|
||||
// Assert removing an added oEmbed media item before save works as expected.
|
||||
$assert_session->elementExists('css', '.media-library-open-button[name^="field_unlimited_media"]')->click();
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$assert_session->pageTextContains('Add or select media');
|
||||
$page->clickLink('Type Five');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$page->fillField('Add Type Five via URL', $video_url);
|
||||
$page->fillField('Add Type Five via URL', $youtube_url);
|
||||
$page->pressButton('Add');
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
// Assert the focus is shifted to the added media items.
|
||||
|
@ -1054,7 +1201,7 @@ class MediaLibraryTest extends WebDriverTestBase {
|
|||
$assert_session->elementExists('css', '.media-library-add-form__remove-button')->click();
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
// Assert the remove message is shown.
|
||||
$assert_session->pageTextContains("The media item $video_title has been removed.");
|
||||
$assert_session->pageTextContains("The media item $youtube_title has been removed.");
|
||||
// Assert the focus is shifted to the first tabbable element of the add
|
||||
// form, which should be the source field.
|
||||
$this->assertJsCondition('jQuery("#media-library-add-form-wrapper :tabbable").is(":focus")');
|
||||
|
|
Loading…
Reference in New Issue