diff --git a/js/dropzone.integration.js b/js/dropzone.integration.js index e81800f..ee5b0c1 100644 --- a/js/dropzone.integration.js +++ b/js/dropzone.integration.js @@ -14,6 +14,8 @@ Drupal.behaviors.dropzonejsIntegraion = { attach: function (context) { Dropzone.autoDiscover = false; + + // TODO: init functionality should support multiple drop zones on page var selector = $(".dropzone-enable"); selector.addClass("dropzone"); var input = selector.siblings('input'); @@ -24,9 +26,20 @@ addRemoveLinks: false }; var instanceConfig = drupalSettings.dropzonejs.instances[selector.attr('id')]; + + // if DropzoneJS instance is already registered on Element. There is no + // need to register it again. + if (selector.once('register-dropzonejs').length !== selector.length) { + return; + } + + // If instance exists for configuration, but it's detached from element + // then destroy detached instance and create new instance. if (instanceConfig.instance !== undefined) { instanceConfig.instance.destroy(); } + + // Initialize DropzoneJS instance for element. var dropzoneInstance = new Dropzone("#" + selector.attr("id"), $.extend({}, instanceConfig, config)); // Other modules might need instances. diff --git a/modules/eb_widget/js/dropzonejs_eb_widget.ief_edit.js b/modules/eb_widget/js/dropzonejs_eb_widget.ief_edit.js index ada3bed..74f601a 100644 --- a/modules/eb_widget/js/dropzonejs_eb_widget.ief_edit.js +++ b/modules/eb_widget/js/dropzonejs_eb_widget.ief_edit.js @@ -20,6 +20,11 @@ var $form = this; $('#edit-edit', $form).trigger('mousedown'); }.bind($form)); + + $form.find('.dropzonejs-remove-icon').click(function () { + var $form = this; + $('#edit-edit', $form).trigger('mousedown'); + }.bind($form)); } }); } diff --git a/modules/eb_widget/src/Plugin/EntityBrowser/Widget/DropzoneJsEbWidget.php b/modules/eb_widget/src/Plugin/EntityBrowser/Widget/DropzoneJsEbWidget.php index 3c622c7..ec10da5 100644 --- a/modules/eb_widget/src/Plugin/EntityBrowser/Widget/DropzoneJsEbWidget.php +++ b/modules/eb_widget/src/Plugin/EntityBrowser/Widget/DropzoneJsEbWidget.php @@ -11,6 +11,7 @@ use Drupal\Core\Utility\Token; use Drupal\dropzonejs\DropzoneJsUploadSaveInterface; use Drupal\entity_browser\WidgetBase; use Drupal\entity_browser\WidgetValidationManager; +use Drupal\file\Entity\File; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -47,13 +48,6 @@ class DropzoneJsEbWidget extends WidgetBase { protected $token; /** - * Uploaded files. - * - * @var \Drupal\file\FileInterface[] - */ - protected $files; - - /** * Constructs widget plugin. * * @param array $configuration @@ -166,17 +160,15 @@ class DropzoneJsEbWidget extends WidgetBase { $config = $this->getConfiguration(); $additional_validators = ['file_validate_size' => [Bytes::toInt($config['settings']['max_filesize']), 0]]; - if (!$this->files) { - $this->files = []; + $files = $form_state->get(['dropzonejs', $this->uuid(), 'files']); - $files = $form_state->get(['dropzonejs', 'files']); - if ($files) { - $this->files = $files; - return $files; - } + if (!$files) { + $files = []; + } - // We do some casting because $form_state->getValue() might return NULL. - foreach ((array) $form_state->getValue(['upload', 'uploaded_files'], []) as $file) { + // We do some casting because $form_state->getValue() might return NULL. + foreach ((array) $form_state->getValue(['upload', 'uploaded_files'], []) as $file) { + if (file_exists($file['path'])) { $entity = $this->dropzoneJsUploadSave->createFile( $file['path'], $this->getUploadLocation(), @@ -184,12 +176,56 @@ class DropzoneJsEbWidget extends WidgetBase { $this->currentUser, $additional_validators ); - $this->files[] = $entity; + $files[] = $entity; } } - $form_state->set(['dropzonejs', 'files'], $this->files); - return $this->files; + $files = $this->filterDropzoneFiles($form_state, $files); + + $form_state->set(['dropzonejs', $this->uuid(), 'files'], $files); + return $files; + } + + /** + * Returns a filtered list of files. + * + * List only contains files that are currently into the dropzone widget. + * + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The current form state. + * @param \Drupal\file\FileInterface[] $files + * An array of files. + * + * @return array + * Filtered array of files + */ + protected function filterDropzoneFiles(FormStateInterface $form_state, $files) { + if (!empty($form_state->getUserInput()['upload']['uploaded_files'])) { + $uploadedFiles = rtrim($form_state->getUserInput()['upload']['uploaded_files'], ';'); + $currentDropzoneFiles = !empty($uploadedFiles) ? explode(';', $uploadedFiles) : []; + + if ($currentDropzoneFiles) { + $dropzoneFiles = []; + foreach ($currentDropzoneFiles as $currentDropzoneFile) { + $dropzoneFiles[] = ['name' => $currentDropzoneFile, 'checked' => FALSE]; + } + // Filter removed files out of files array. + return array_filter($files, function ($file) use (&$dropzoneFiles) { + foreach ($dropzoneFiles as &$dropzoneFile) { + // Cut .txt from the end of the filename. + $currentDropzoneFile = File::create([ + 'filename' => substr($dropzoneFile['name'], 0, -4), + ]); + if (strstr($file->getFilename(), pathinfo($currentDropzoneFile->getFilename())['filename']) !== FALSE && !$dropzoneFile['checked']) { + $dropzoneFile['checked'] = TRUE; + return TRUE; + } + } + return FALSE; + }); + } + } + return []; } /** @@ -264,6 +300,7 @@ class DropzoneJsEbWidget extends WidgetBase { // remove them from our values. $form_state->setValueForElement($element['upload']['uploaded_files'], ''); NestedArray::setValue($form_state->getUserInput(), $element['upload']['uploaded_files']['#parents'], ''); + $form_state->set(['dropzonejs', $this->uuid(), 'files'], []); } /** diff --git a/modules/eb_widget/src/Plugin/EntityBrowser/Widget/InlineEntityFormMediaWidget.php b/modules/eb_widget/src/Plugin/EntityBrowser/Widget/InlineEntityFormMediaWidget.php index 631d314..2cc9496 100644 --- a/modules/eb_widget/src/Plugin/EntityBrowser/Widget/InlineEntityFormMediaWidget.php +++ b/modules/eb_widget/src/Plugin/EntityBrowser/Widget/InlineEntityFormMediaWidget.php @@ -59,15 +59,22 @@ class InlineEntityFormMediaWidget extends MediaEntityDropzoneJsEbWidget { $form += ['entities' => []]; if ($entities = $form_state->get('uploaded_entities')) { + $source_field = $this->getBundle()->getTypeConfiguration()['source_field']; foreach ($entities as $entity) { - /** @var \Drupal\Core\Entity\EntityInterface $entity */ - $form['entities'][$entity->uuid()] = [ - '#type' => 'inline_entity_form', - '#entity_type' => $entity->getEntityTypeId(), - '#bundle' => $entity->bundle(), - '#default_value' => $entity, - '#form_mode' => 'media_browser', - ]; + $file = $entity->$source_field->entity; + /* We have to filter files here, to get the correct form after tab + * switching. + */ + if ($this->filterDropzoneFiles($form_state, [$file])) { + /** @var \Drupal\Core\Entity\EntityInterface $entity */ + $form['entities'][$entity->uuid()] = [ + '#type' => 'inline_entity_form', + '#entity_type' => $entity->getEntityTypeId(), + '#bundle' => $entity->bundle(), + '#default_value' => $entity, + '#form_mode' => 'media_browser', + ]; + } } } @@ -99,9 +106,12 @@ class InlineEntityFormMediaWidget extends MediaEntityDropzoneJsEbWidget { $media_entities = $this->prepareEntities($form, $form_state); $source_field = $this->getBundle()->getTypeConfiguration()['source_field']; foreach ($media_entities as $media_entity) { + /** @var \Drupal\file\Entity\File $file */ $file = $media_entity->$source_field->entity; - $file->save(); - $media_entity->$source_field->target_id = $file->id(); + if ($file->isNew()) { + $file->save(); + $media_entity->$source_field->target_id = $file->id(); + } } $form_state->set('uploaded_entities', $media_entities); @@ -169,6 +179,8 @@ class InlineEntityFormMediaWidget extends MediaEntityDropzoneJsEbWidget { if (!empty(array_filter($media_entities))) { $this->selectEntities($media_entities, $form_state); $this->clearFormValues($element, $form_state); + // Clear uploaded_entities to get a clean form in multi-step selection. + $form_state->set('uploaded_entities', []); } } }