diff --git a/modules/eb_widget/config/schema/dropzonejs_eb_widget.schema.yml b/modules/eb_widget/config/schema/dropzonejs_eb_widget.schema.yml index 72213db..9c2d609 100644 --- a/modules/eb_widget/config/schema/dropzonejs_eb_widget.schema.yml +++ b/modules/eb_widget/config/schema/dropzonejs_eb_widget.schema.yml @@ -5,6 +5,9 @@ entity_browser.browser.widget.dropzonejs: submit_text: type: string label: 'Submit button text' + auto_select: + type: boolean + label: 'Automatically submit selection' upload_location: type: string label: 'Upload location' @@ -28,6 +31,9 @@ entity_browser.browser.widget.dropzonejs_media_entity: submit_text: type: string label: 'Submit button text' + auto_select: + type: boolean + label: 'Automatically submit selection' upload_location: type: string label: 'Upload location' diff --git a/modules/eb_widget/js/dropzonejs_eb_widget.common.js b/modules/eb_widget/js/dropzonejs_eb_widget.common.js index 5c8bf92..e8245ef 100644 --- a/modules/eb_widget/js/dropzonejs_eb_widget.common.js +++ b/modules/eb_widget/js/dropzonejs_eb_widget.common.js @@ -29,7 +29,41 @@ if (item.instance.getRejectedFiles().length === 0) { $submit.removeAttr('disabled'); } + + // If there are no files in DropZone -> disable Button. + if (item.instance.getAcceptedFiles().length === 0) { + $submit.prop('disabled', true); + } }); + + if (drupalSettings.entity_browser_widget && drupalSettings.entity_browser_widget.auto_select) { + item.instance.on('queuecomplete', function () { + var dzInstance = item.instance; + var filesInQueue = dzInstance.getQueuedFiles(); + var acceptedFiles; + var i; + + if (filesInQueue.length === 0) { + acceptedFiles = dzInstance.getAcceptedFiles(); + + // Ensure that there are some files that should be submitted. + if (acceptedFiles.length > 0 && dzInstance.getUploadingFiles().length === 0) { + // First submit accepted files and clear them from list of + // dropped files afterwards. + jQuery(dzInstance.element) + .parent() + .siblings('[name="auto_select_handler"]') + .trigger('auto_select_enity_browser_widget'); + + // Remove accepted files -> because they are submitted. + for (i = 0; i < acceptedFiles.length; i++) { + dzInstance.removeFile(acceptedFiles[i]); + } + } + } + }); + } + } }); } diff --git a/modules/eb_widget/src/Plugin/EntityBrowser/Widget/DropzoneJsEbWidget.php b/modules/eb_widget/src/Plugin/EntityBrowser/Widget/DropzoneJsEbWidget.php index 0572d15..e2ccf52 100644 --- a/modules/eb_widget/src/Plugin/EntityBrowser/Widget/DropzoneJsEbWidget.php +++ b/modules/eb_widget/src/Plugin/EntityBrowser/Widget/DropzoneJsEbWidget.php @@ -4,6 +4,8 @@ namespace Drupal\dropzonejs_eb_widget\Plugin\EntityBrowser\Widget; use Drupal\Component\Utility\Bytes; use Drupal\Component\Utility\NestedArray; +use Drupal\Core\Ajax\AjaxResponse; +use Drupal\Core\Ajax\InvokeCommand; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Session\AccountProxyInterface; @@ -20,7 +22,8 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface; * @EntityBrowserWidget( * id = "dropzonejs", * label = @Translation("DropzoneJS"), - * description = @Translation("Adds DropzoneJS upload integration.") + * description = @Translation("Adds DropzoneJS upload integration."), + * auto_select = TRUE * ) */ class DropzoneJsEbWidget extends WidgetBase { @@ -131,6 +134,26 @@ class DropzoneJsEbWidget extends WidgetBase { $form['#attached']['library'][] = 'dropzonejs_eb_widget/common'; $original_form['#attributes']['class'][] = 'dropzonejs-disable-submit'; + // Add hidden element used to make execution of auto-select of form. + if (!empty($config['settings']['auto_select'])) { + $form['auto_select_handler'] = [ + '#type' => 'hidden', + '#name' => 'auto_select_handler', + '#id' => 'auto_select_handler', + '#attributes' => ['id' => 'auto_select_handler'], + '#submit' => ['::submitForm'], + '#executes_submit_callback' => TRUE, + '#ajax' => [ + 'wrapper' => 'auto_select_handler', + 'callback' => [get_class($this), 'handleAjaxCommand'], + 'event' => 'auto_select_enity_browser_widget', + 'progress' => [ + 'type' => 'fullscreen', + ], + ], + ]; + } + return $form; } @@ -203,7 +226,7 @@ class DropzoneJsEbWidget extends WidgetBase { // Validate if we are in fact uploading a files and all of them have the // right extensions. Although DropzoneJS should not even upload those files // it's still better not to rely only on client side validation. - if ($trigger['#type'] == 'submit' && $trigger['#name'] == 'op') { + if (($trigger['#type'] == 'submit' && $trigger['#name'] == 'op') || $trigger['#name'] === 'auto_select_handler') { $upload_location = $this->getUploadLocation(); if (!file_prepare_directory($upload_location, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) { $form_state->setError($form['widget']['upload'], t('Files could not be uploaded because the destination directory %destination is not configured correctly.', ['%destination' => $this->getConfiguration()['settings']['upload_location']])); @@ -237,10 +260,23 @@ class DropzoneJsEbWidget extends WidgetBase { $files[] = $file; } - if (!empty(array_filter($files))) { - $this->selectEntities($files, $form_state); - $this->clearFormValues($element, $form_state); + $this->selectEntities($files, $form_state); + $this->clearFormValues($element, $form_state); + } + + /** + * {@inheritdoc} + */ + protected function selectEntities(array $entities, FormStateInterface $form_state) { + if (!empty(array_filter($entities))) { + $config = $this->getConfiguration(); + + if (empty($config['settings']['auto_select'])) { + parent::selectEntities($entities, $form_state); + } } + + $form_state->set(['dropzonejs', 'added_entities'], $entities); } /** @@ -360,4 +396,57 @@ class DropzoneJsEbWidget extends WidgetBase { return array_diff(parent::__sleep(), ['files']); } + /** + * Handling of automated submit of uploaded files. + * + * @param array $form + * Form. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * Form state. + * + * @return \Drupal\Core\Ajax\AjaxResponse|array + * Returns ajax commands that will be executed in front-end. + */ + public static function handleAjaxCommand(array $form, FormStateInterface $form_state) { + // If there are some errors during submitting of form they should be + // displayed, that's why we are returning status message here and generated + // errors will be displayed properly in front-end. + if (count($form_state->getErrors()) > 0) { + return [ + '#type' => 'status_messages', + ]; + } + + // Output correct response if everything passed without any error. + $ajax = new AjaxResponse(); + + if (($triggering_element = $form_state->getTriggeringElement()) && $triggering_element['#name'] === 'auto_select_handler') { + $entity_ids = []; + + $added_entities = $form_state->get(['dropzonejs', 'added_entities']); + /** @var \Drupal\Core\Entity\EntityInterface $entity */ + if (!empty($added_entities)) { + foreach ($added_entities as $entity) { + $entity_ids[] = $entity->getEntityTypeId() . ':' . $entity->id(); + } + } + + // Add command to clear list of uploaded files. It's important to set + // empty string value, in other case it will act as getter. + $ajax->addCommand( + new InvokeCommand('[data-drupal-selector="edit-upload-uploaded-files"]', 'val', ['']) + ); + + // Add Invoke command to select uploaded entities. + $ajax->addCommand( + new InvokeCommand('.entities-list', 'trigger', [ + 'add-entities', + [$entity_ids], + ]) + ); + } + + return $ajax; + } + } diff --git a/modules/eb_widget/src/Plugin/EntityBrowser/Widget/InlineEntityFormMediaWidget.php b/modules/eb_widget/src/Plugin/EntityBrowser/Widget/InlineEntityFormMediaWidget.php index 3b2ecbc..37132a8 100644 --- a/modules/eb_widget/src/Plugin/EntityBrowser/Widget/InlineEntityFormMediaWidget.php +++ b/modules/eb_widget/src/Plugin/EntityBrowser/Widget/InlineEntityFormMediaWidget.php @@ -15,7 +15,8 @@ use Drupal\inline_entity_form\Element\InlineEntityForm; * @EntityBrowserWidget( * id = "dropzonejs_media_entity_inline_entity_form", * label = @Translation("Media Entity DropzoneJS with edit"), - * description = @Translation("Adds DropzoneJS upload integration that saves Media entities and allows to edit them.") + * description = @Translation("Adds DropzoneJS upload integration that saves Media entities and allows to edit them."), + * auto_select = FALSE * ) */ class InlineEntityFormMediaWidget extends MediaEntityDropzoneJsEbWidget { diff --git a/modules/eb_widget/src/Plugin/EntityBrowser/Widget/MediaEntityDropzoneJsEbWidget.php b/modules/eb_widget/src/Plugin/EntityBrowser/Widget/MediaEntityDropzoneJsEbWidget.php index 8453cea..2a99ea0 100644 --- a/modules/eb_widget/src/Plugin/EntityBrowser/Widget/MediaEntityDropzoneJsEbWidget.php +++ b/modules/eb_widget/src/Plugin/EntityBrowser/Widget/MediaEntityDropzoneJsEbWidget.php @@ -24,7 +24,8 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface; * @EntityBrowserWidget( * id = "dropzonejs_media_entity", * label = @Translation("Media Entity DropzoneJS"), - * description = @Translation("Adds DropzoneJS upload integration that saves Media entities.") + * description = @Translation("Adds DropzoneJS upload integration that saves Media entities."), + * auto_select = TRUE * ) */ class MediaEntityDropzoneJsEbWidget extends DropzoneJsEbWidget { @@ -193,10 +194,8 @@ class MediaEntityDropzoneJsEbWidget extends DropzoneJsEbWidget { $media_entity->save(); } - if (!empty(array_filter($media_entities))) { - $this->selectEntities($media_entities, $form_state); - $this->clearFormValues($element, $form_state); - } + $this->selectEntities($media_entities, $form_state); + $this->clearFormValues($element, $form_state); } }