diff --git a/.cspell-project-words.txt b/.cspell-project-words.txt new file mode 100644 index 0000000000000000000000000000000000000000..2e3d675e8aaace255ff5bdecb00ebf47f26c85c5 --- /dev/null +++ b/.cspell-project-words.txt @@ -0,0 +1,7 @@ +acquia +dropzonejs +grih +imagesloaded +mortenson +nldz +pkgd diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..979cd4032ecd4c289c398cc9ba5d80bbb9086bc1 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,64 @@ +################ +# DrupalCI GitLabCI template +# +# Gitlab-ci.yml to replicate DrupalCI testing for Contrib +# +# With thanks to: +# * The GitLab Acceleration Initiative participants +# * DrupalSpoons +################ + +################ +# Guidelines +# +# This template is designed to give any Contrib maintainer everything they need to test, without requiring modification. It is also designed to keep up to date with Core Development automatically through the use of include files that can be centrally maintained. +# +# However, you can modify this template if you have additional needs for your project. +################ + +################ +# Includes +# +# Additional configuration can be provided through includes. +# One advantage of include files is that if they are updated upstream, the changes affect all pipelines using that include. +# +# Includes can be overridden by re-declaring anything provided in an include, here in gitlab-ci.yml +# https://docs.gitlab.com/ee/ci/yaml/includes.html#override-included-configuration-values +################ + +include: + ################ + # DrupalCI includes: + # As long as you include this, any future includes added by the Drupal Association will be accessible to your pipelines automatically. + # View these include files at https://git.drupalcode.org/project/gitlab_templates/ + ################ + - project: $_GITLAB_TEMPLATES_REPO + ref: $_GITLAB_TEMPLATES_REF + file: + - '/includes/include.drupalci.main.yml' + - '/includes/include.drupalci.variables.yml' + - '/includes/include.drupalci.workflows.yml' + +################ +# Pipeline configuration variables +# +# These are the variables provided to the Run Pipeline form that a user may want to override. +# +# Docs at https://git.drupalcode.org/project/gitlab_templates/-/blob/1.0.x/includes/include.drupalci.variables.yml +################ +variables: + # Convenient, and we have no secrets. + _SHOW_ENVIRONMENT_VARIABLES: 1 + DROPZONE_VERSION: v6.0.0-beta.2 + +.composer-base: + after_script: + - mkdir $_WEB_ROOT/libraries + - cd $_WEB_ROOT/libraries + - curl -L https://github.com/dropzone/dropzone/releases/download/$DROPZONE_VERSION/dist.zip -o dropzone.zip --silent + - unzip dropzone.zip + - mv dist dropzone + - mkdir imagesloaded + - curl -L https://cdnjs.cloudflare.com/ajax/libs/jquery.imagesloaded/4.1.4/imagesloaded.pkgd.min.js -o imagesloaded/imagesloaded.pkgd.min.js + - mkdir -p masonry/dist + - curl -L https://unpkg.com/masonry-layout@4/dist/masonry.pkgd.min.js -o masonry/dist/masonry.pkgd.min.js diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000000000000000000000000000000000000..1cda54be937849072650e8a9ad7ae3ffcdf5a8d0 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +*.yml diff --git a/.prettierrc.json b/.prettierrc.json new file mode 120000 index 0000000000000000000000000000000000000000..464f7117a17824b4211a49512d57413f465fd23e --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1 @@ +web/core/.prettierrc.json \ No newline at end of file diff --git a/README.txt b/README.txt index df06d9dbbaa4b4b1809b6a203ec41b3cd7b97fc0..786dc67d0c43b9b82969a42181a411650c2a9b8f 100644 --- a/README.txt +++ b/README.txt @@ -79,7 +79,7 @@ CONFIGURATION c. Download https://github.com/enyo/dropzone/archive/v4.3.0.zip and extract the download to /libraries/dropzone (or any libraries directory if you're using the Libraries module). - 2. Navigate to Adminstration > Extend and enabled the File Entity Browser + 2. Navigate to Administration > Extend and enabled the File Entity Browser and its dependencies. Please note: diff --git a/composer.json b/composer.json index 896a3354062c47eb1cde3e753a1b684acdda9ced..c19272f1f032052bb0e61956430eed91ee562742 100644 --- a/composer.json +++ b/composer.json @@ -4,10 +4,10 @@ "type": "drupal-module", "license": "GPL-2.0-or-later", "require": { - "drupal/core": "~8 || ~9 || ~10", - "drupal/entity_browser": "^2 || ^1", + "drupal/core": "~8 || ~9 || ~10 || ~11", "drupal/dropzonejs": "^2", "drupal/embed": "^1", + "drupal/entity_browser": "^2 || ^1", "drupal/entity_embed": "^1" }, "require-dev": { diff --git a/composer.libraries.json b/composer.libraries.json new file mode 100644 index 0000000000000000000000000000000000000000..5a7e22d7d2c83ca21f1babdb7bfa72e2c1609145 --- /dev/null +++ b/composer.libraries.json @@ -0,0 +1,45 @@ +{ + "repositories": [ + { + "type": "package", + "package": { + "name": "dropzone/dropzone", + "version": "5.7.3", + "type": "drupal-library", + "dist": { + "url": "https://github.com/dropzone/dropzone-packagist/archive/refs/tags/v5.7.3.zip", + "type": "zip" + } + } + }, + { + "type": "package", + "package": { + "name": "desandro/imagesloaded", + "version": "4.1.4", + "type": "drupal-library", + "dist": { + "url": "https://github.com/desandro/imagesloaded/archive/refs/tags/v4.1.4.zip", + "type": "zip" + } + } + }, + { + "type": "package", + "package": { + "name": "desandro/masonry", + "version": "4.1.4", + "type": "drupal-library", + "dist": { + "url": "https://github.com/desandro/masonry/archive/refs/tags/v4.2.2.zip", + "type": "zip" + } + } + } + ], + "require": { + "dropzone/dropzone": "^5", + "desandro/imagesloaded": "^4", + "desandro/masonry": "^4" + } +} diff --git a/config/install/embed.button.file_browser.yml b/config/install/embed.button.file_browser.yml index 6f858283c6622e408c23ac2db497ca9066d5c0fe..3245dad807ca9b7b819f353a49b1c806ca40c6f6 100644 --- a/config/install/embed.button.file_browser.yml +++ b/config/install/embed.button.file_browser.yml @@ -10,7 +10,7 @@ id: file_browser type_id: entity type_settings: entity_type: file - bundles: { } + bundles: {} display_plugins: - 'file:file_default' - 'image:image' diff --git a/config/install/entity_browser.browser.browse_files.yml b/config/install/entity_browser.browser.browse_files.yml index ca0e44b2d6c039696dcadfe213735bdb58b8d0dc..b493f12f4d667027d9ed585ea3e4bf944cc08670 100644 --- a/config/install/entity_browser.browser.browse_files.yml +++ b/config/install/entity_browser.browser.browse_files.yml @@ -23,7 +23,7 @@ selection_display_configuration: image_style: file_entity_browser_small selection_hidden: false widget_selector: tabs -widget_selector_configuration: { } +widget_selector_configuration: {} widgets: a4ad947c-9669-497c-9988-24351955a02f: settings: diff --git a/config/install/entity_browser.browser.browse_files_modal.yml b/config/install/entity_browser.browser.browse_files_modal.yml index b5cef3cce18010a8661a87a090c5772695e800fd..82a3cb21f88642d7898d9777c61070d4a8a3de6a 100644 --- a/config/install/entity_browser.browser.browse_files_modal.yml +++ b/config/install/entity_browser.browser.browse_files_modal.yml @@ -23,7 +23,7 @@ selection_display_configuration: image_style: file_entity_browser_small selection_hidden: false widget_selector: tabs -widget_selector_configuration: { } +widget_selector_configuration: {} widgets: a4ad947c-9669-497c-9988-24351955a02f: settings: diff --git a/config/install/image.style.file_entity_browser_small.yml b/config/install/image.style.file_entity_browser_small.yml index 29b08628aae718496c8e5e30b3db43eb308d7fb0..47b12dc5037ff7ba36ac9633622bea896a4fa917 100644 --- a/config/install/image.style.file_entity_browser_small.yml +++ b/config/install/image.style.file_entity_browser_small.yml @@ -1,6 +1,6 @@ langcode: en status: true -dependencies: { } +dependencies: {} name: file_entity_browser_small label: 'File Entity Browser small thumbnail' effects: diff --git a/config/install/image.style.file_entity_browser_thumbnail.yml b/config/install/image.style.file_entity_browser_thumbnail.yml index 400eb347bd04c2827abbd17762b6d54ea0a1177c..4f474ae727d4827fc9eafb456a9629c68aef97b0 100644 --- a/config/install/image.style.file_entity_browser_thumbnail.yml +++ b/config/install/image.style.file_entity_browser_thumbnail.yml @@ -1,6 +1,6 @@ langcode: en status: true -dependencies: { } +dependencies: {} name: file_entity_browser_thumbnail label: 'File Entity Browser thumbnail' effects: diff --git a/config/install/views.view.file_entity_browser.yml b/config/install/views.view.file_entity_browser.yml index 48b16ff80a50a73e6d5f6d24a0d78ea767052803..d47a97e8bd42eda129b947dbb26d87d4a330624e 100644 --- a/config/install/views.view.file_entity_browser.yml +++ b/config/install/views.view.file_entity_browser.yml @@ -30,7 +30,7 @@ display: perm: 'access content' cache: type: none - options: { } + options: {} query: type: views_query options: @@ -38,7 +38,7 @@ display: distinct: false replica: false query_comment: '' - query_tags: { } + query_tags: {} exposed_form: type: basic options: @@ -73,13 +73,13 @@ display: style: type: default options: - grouping: { } + grouping: {} row_class: grid-item default_row_class: true row: type: fields options: - inline: { } + inline: {} separator: '' hide_empty: false default_field_elements: true @@ -237,7 +237,7 @@ display: settings: link_to_entity: false group_column: value - group_columns: { } + group_columns: {} group_rows: true delta_limit: 0 delta_offset: 0 @@ -299,9 +299,9 @@ display: hide_alter_empty: true click_sort_column: value type: file_size - settings: { } + settings: {} group_column: value - group_columns: { } + group_columns: {} group_rows: true delta_limit: 0 delta_offset: 0 @@ -398,8 +398,8 @@ display: multiple: false remember: false default_group: All - default_group_multiple: { } - group_items: { } + default_group_multiple: {} + group_items: {} entity_type: file entity_field: filename plugin_id: string @@ -438,8 +438,8 @@ display: multiple: false remember: false default_group: All - default_group_multiple: { } - group_items: { } + default_group_multiple: {} + group_items: {} entity_type: file entity_field: filemime plugin_id: string @@ -478,8 +478,8 @@ display: multiple: false remember: false default_group: All - default_group_multiple: { } - group_items: { } + default_group_multiple: {} + group_items: {} entity_type: file entity_field: status plugin_id: file_status @@ -516,8 +516,8 @@ display: multiple: false remember: false default_group: All - default_group_multiple: { } - group_items: { } + default_group_multiple: {} + group_items: {} entity_type: file entity_field: filename plugin_id: string @@ -565,12 +565,12 @@ display: entity_type: file entity_field: filename plugin_id: standard - header: { } - footer: { } - empty: { } - relationships: { } - arguments: { } - display_extenders: { } + header: {} + footer: {} + empty: {} + relationships: {} + arguments: {} + display_extenders: {} css_class: '' use_ajax: true cache_metadata: @@ -584,14 +584,14 @@ display: - user.permissions cacheable: false max-age: -1 - tags: { } + tags: {} entity_browser_1: display_plugin: entity_browser id: entity_browser_1 display_title: 'Entity browser' position: 2 display_options: - display_extenders: { } + display_extenders: {} cache_metadata: contexts: - 'languages:language_content' @@ -603,4 +603,4 @@ display: - user.permissions cacheable: false max-age: -1 - tags: { } + tags: {} diff --git a/css/file_browser.dropzone.css b/css/file_browser.dropzone.css index a89227baa82865d692818489825e4fb2dd14636f..032761e432e2203eb7dfba83c520d259b8aeb806 100644 --- a/css/file_browser.dropzone.css +++ b/css/file_browser.dropzone.css @@ -3,24 +3,24 @@ */ .dropzone .dz-preview .dz-success-mark { - background: transparent url("../images/checkmark.svg") no-repeat center center; - background-size: 100% 100%; - width: 54px; - height: 54px; top: -20px; right: 0; bottom: 0; left: 0; + width: 54px; + height: 54px; margin: auto; + background: transparent url("../images/checkmark.svg") no-repeat center center; + background-size: 100% 100%; } .dropzone .dz-preview .dz-error-mark { - width: 54px; - height: 54px; top: -20px; right: 0; bottom: 0; left: 0; + width: 54px; + height: 54px; margin: auto; } diff --git a/css/file_browser.preview.css b/css/file_browser.preview.css index 348a501e6c6a34d6716619c1c2892b746f5aa848..c30d7b540aacfc91631a9c71db2ff1e7115d86ec 100644 --- a/css/file_browser.preview.css +++ b/css/file_browser.preview.css @@ -4,19 +4,19 @@ .file-browser-preview-dialog { position: absolute; - height: 100% !important; - width: 100% !important; - max-width: none !important; top: 0 !important; left: 0 !important; + width: 100% !important; + max-width: none !important; + height: 100% !important; } .file-browser-preview-dialog #drupal-modal { width: 100% !important; height: 100% !important; max-height: none !important; - padding-top: 0; margin-top: -20px; + padding-top: 0; background: #2d2d2d; } @@ -25,8 +25,8 @@ } .file-browser-preview-dialog.ui-dialog .ui-dialog-titlebar { - background-color: #2d2d2d; border-radius: 0; + background-color: #2d2d2d; } .file-browser-preview-dialog.ui-dialog .ui-dialog-title { diff --git a/css/file_browser.view.css b/css/file_browser.view.css index 46243bff1b7ddf89fe6d2e1a39b0cc015c4d3f09..21e9b888b00f6f37322f34fd6978af4cd8ac4ba5 100644 --- a/css/file_browser.view.css +++ b/css/file_browser.view.css @@ -2,7 +2,6 @@ * @file file_browser.view.css */ - /* Generic styles */ .pager { @@ -65,51 +64,63 @@ .grid-item { display: block; - opacity: 0; - text-align: center; - background-color: #dedede; overflow: hidden; + text-align: center; + opacity: 0; border-radius: 2px; - box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 1px 5px 0 rgba(0,0,0,0.12), 0 3px 1px -2px rgba(0,0,0,0.2); + background-color: #dedede; + box-shadow: + 0 2px 2px 0 rgba(0, 0, 0, 0.14), + 0 1px 5px 0 rgba(0, 0, 0, 0.12), + 0 3px 1px -2px rgba(0, 0, 0, 0.2); } .grid-item.item-style { + -moz-transition: + opacity 0.25s ease-in-out, + box-shadow 0.25s ease-in-out; + -webkit-transition: + opacity 0.25s ease-in-out, + box-shadow 0.25s ease-in-out; + transition: + opacity 0.25s ease-in-out, + box-shadow 0.25s ease-in-out; opacity: 1; - transition: opacity .25s ease-in-out, box-shadow .25s ease-in-out; - -moz-transition: opacity .25s ease-in-out, box-shadow .25s ease-in-out;; - -webkit-transition: opacity .25s ease-in-out, box-shadow .25s ease-in-out;; } .grid-item:hover { cursor: pointer; } -.grid-item.checked:before { - content: " "; - color: transparent; +.grid-item.checked::before { position: absolute; - left: 0; - right: 0; top: 0; + right: 0; + left: 0; + overflow: hidden; width: calc(100% - 4px); height: calc(100% - 4px); + content: " "; + color: transparent; border: 2px solid #37802f; - overflow: hidden; } .grid-item:hover { - box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 1px 7px 3px rgba(0,0,0,0.12), 0 3px 1px -2px rgba(0,0,0,0.2); + box-shadow: + 0 2px 2px 0 rgba(0, 0, 0, 0.14), + 0 1px 7px 3px rgba(0, 0, 0, 0.12), + 0 3px 1px -2px rgba(0, 0, 0, 0.2); } .view-content { - margin: 0 auto; width: 100% !important; + margin: 0 auto; } .grid-item img { - vertical-align: bottom; width: 100%; height: auto; + vertical-align: bottom; } .grid-item img::selection { @@ -120,32 +131,32 @@ display: none; } -.grid-item:after { - content: " "; - width: 100%; - height: 100%; +.grid-item::after { + position: absolute; top: 0; left: 0; - position: absolute; + width: 100%; + height: 100%; + content: " "; } .grid-item-info { position: absolute; z-index: 1; - width: calc(100% - 20px); bottom: 0; - background-color: #2d2d2d; - color: #dedede; + width: calc(100% - 20px); padding: 10px; + color: #dedede; + background-color: #2d2d2d; } .grid-item-info-left { float: left; + overflow: hidden; + max-width: 50%; text-align: left; white-space: nowrap; - overflow: hidden; text-overflow: ellipsis; - max-width: 50%; } .grid-item-info-right { @@ -156,17 +167,16 @@ position: relative; } - /* Remove border above tabs. */ -.file-browser-form .is-collapse-enabled .tabs:before, -.file-browser-form .is-horizontal .tabs:before { +.file-browser-form .is-collapse-enabled .tabs::before, +.file-browser-form .is-horizontal .tabs::before { background-color: transparent; } input[type="submit"][name="filter"] { - margin-left: 10px; margin-top: 30px; + margin-left: 10px; } .layout-container { @@ -175,16 +185,16 @@ input[type="submit"][name="filter"] { .file-browser-actions { position: fixed; + z-index: 2; bottom: 0; display: flex; flex-direction: row-reverse; - justify-content: flex-end; align-items: center; - z-index: 2; - padding: 10px; + justify-content: flex-end; width: 100%; - background: white; + padding: 10px; border-top: 1px solid #b8b8b8; + background: white; } input.entity-browser-show-selection { @@ -193,8 +203,8 @@ input.entity-browser-show-selection { .entities-list .item-container { position: relative; - border: 1px dashed gray; margin: 5px; + border: 1px dashed gray; } .entities-list .item-container > img, @@ -208,11 +218,11 @@ input.entity-browser-show-selection { .entities-list .item-container:hover img, .entities-list .item-container:hover input { - transition: .2s; + transition: 0.2s; } .entities-list .item-container:hover img { - opacity: .6; + opacity: 0.6; } .entities-list .item-container:hover input { @@ -220,21 +230,21 @@ input.entity-browser-show-selection { } .entities-list .item-container input { - background: url(../images/remove.svg); - opacity: 0; - background-size: cover; - color: transparent; - text-shadow: none; position: absolute; + top: 2px; + right: 2px; width: 20px; height: 20px; + margin: 0; padding: 0; - top: 2px; - right: 2px; + opacity: 0; + color: transparent; + border: 1px solid #585858; border-radius: 10px; - margin: 0; + background: url(../images/remove.svg); background-color: #dedede; - border: 1px solid #585858; + background-size: cover; + text-shadow: none; } .entities-list .item-container input:hover { @@ -245,12 +255,12 @@ input.entity-browser-show-selection { display: flex; align-items: center; height: 25px; - padding: 0 0 0 25px; margin-bottom: 5px; + padding: 0 0 0 25px; background: url(../images/checkmark.svg); - background-position: 0px; - background-size: 20px; background-repeat: no-repeat; + background-position: 0; + background-size: 20px; } .grid-item:hover .file-browser-preview-button { @@ -259,21 +269,24 @@ input.entity-browser-show-selection { .file-browser-preview-button { position: absolute; + z-index: 2; top: 5px; right: 5px; + width: 40px; + height: 40px; + transition: opacity 0.2s; + opacity: 0; + color: transparent; + border-radius: 50%; background: url(../images/preview.svg); - z-index: 2; - background-size: 30px; - background-position: 5px; background-color: #2d2d2d; - border-radius: 50%; - height: 40px; - width: 40px; background-repeat: no-repeat; - color: transparent; - box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 1px 5px 0 rgba(0,0,0,0.12), 0 3px 1px -2px rgba(0,0,0,0.2); - opacity: 0; - transition: opacity .2s; + background-position: 5px; + background-size: 30px; + box-shadow: + 0 2px 2px 0 rgba(0, 0, 0, 0.14), + 0 1px 5px 0 rgba(0, 0, 0, 0.12), + 0 3px 1px -2px rgba(0, 0, 0, 0.2); } .file-browser-preview-button:hover, diff --git a/file_browser.info.yml b/file_browser.info.yml index 576b4a59350bd1ed59fc57d2ddb7b13d17240ddc..09588d7d6a07fcea51a6a5ee5006f5436716302b 100644 --- a/file_browser.info.yml +++ b/file_browser.info.yml @@ -1,8 +1,7 @@ name: File Browser description: 'Provides a default Entity Browser for files, using Masonry and Imagesloaded.' type: module -core: 8.x -core_version_requirement: ^8 || ^9 || ^10 +core_version_requirement: ^10 || ^11 dependencies: - entity_browser:entity_browser - entity_embed:entity_embed diff --git a/file_browser.install b/file_browser.install index c8e2e638dd981013567340ea32cd6c8812a11ab8..7fd208695f894b9d8780b9f1c4f52efe3d29b5f1 100644 --- a/file_browser.install +++ b/file_browser.install @@ -6,9 +6,9 @@ */ use Drupal\Component\Serialization\Yaml; +use Drupal\Core\File\FileExists; use Drupal\image\Entity\ImageStyle; use Drupal\views\Entity\View; -use Drupal\Core\File\FileSystemInterface; /** * Implements hook_install(). @@ -18,7 +18,7 @@ function file_browser_install() { if (!\Drupal::isConfigSyncing()) { $data = file_get_contents(dirname(__FILE__) . '/file_browser_icon.png'); /** @var \Drupal\file\FileInterface $file */ - $file = \Drupal::service('file.repository')->writeData($data, 'public://file_browser_icon.png', FileSystemInterface::EXISTS_REPLACE); + $file = \Drupal::service('file.repository')->writeData($data, 'public://file_browser_icon.png', FileExists::Replace); if ($file) { // Set file uuid same as default config. $uuid = Yaml::decode(file_get_contents(dirname(__FILE__) . '/config/install/embed.button.file_browser.yml'))['icon_uuid']; @@ -47,8 +47,8 @@ function file_browser_requirements($phase) { // Optionally use the Libraries module to determine our library paths. if (\Drupal::moduleHandler()->moduleExists('libraries')) { - $imagesloaded_path = libraries_get_path('imagesloaded') . '/imagesloaded.pkgd.min.js'; - $masonry_path = libraries_get_path('masonry') . '/dist/masonry.pkgd.min.js'; + $imagesloaded_path = \Drupal::service('extension.path.resolver')->getPath('library', 'imagesloaded') . '/imagesloaded.pkgd.min.js'; + $masonry_path = \Drupal::service('extension.path.resolver')->getPath('library', 'masonry') . '/dist/masonry.pkgd.min.js'; } else { $imagesloaded_path = DRUPAL_ROOT . '/libraries/imagesloaded/imagesloaded.pkgd.min.js'; diff --git a/file_browser.module b/file_browser.module index 3cc240a483cf0db1940737c112b80a514fc3bc82..e6b0110cc7e0af235354a1edd86fa30900d75fce 100644 --- a/file_browser.module +++ b/file_browser.module @@ -71,8 +71,8 @@ function file_browser_preprocess_details(&$variables) { function file_browser_library_info_alter(&$libraries, $extension) { // Optionally use the Libraries module to determine our library paths. if ($extension == 'file_browser' && \Drupal::moduleHandler()->moduleExists('libraries')) { - $imagesloaded_path = libraries_get_path('imagesloaded') . '/imagesloaded.pkgd.min.js'; - $masonry_path = libraries_get_path('masonry') . '/dist/masonry.pkgd.min.js'; + $imagesloaded_path = \Drupal::service('extension.path.resolver')->getPath('library', 'imagesloaded') . '/imagesloaded.pkgd.min.js'; + $masonry_path = \Drupal::service('extension.path.resolver')->getPath('library', 'masonry') . '/dist/masonry.pkgd.min.js'; $libraries['imagesloaded']['js'] = ['/' . $imagesloaded_path => ['minified' => 'true']]; $libraries['masonry']['js'] = ['/' . $masonry_path => ['minified' => 'true']]; diff --git a/js/file_browser.preview.js b/js/file_browser.preview.js index 935ac940e45274e05d42c6cfa6a73f2ab1d58341..69542e48c3e95bf99cce7ce5d7f4bfdd07a6e5ec 100644 --- a/js/file_browser.preview.js +++ b/js/file_browser.preview.js @@ -3,25 +3,26 @@ * file_browser.preview.js */ -(function ($, Drupal) { - - "use strict"; - +(($, Drupal) => { /** * Contains logic for the view widget. */ Drupal.behaviors.fileBrowserPreview = { - attach: function (context, settings) { - var wrapper = once('file-browser-preview', '#file-browser-preview-wrapper'); + attach(context, settings) { + const wrapper = once( + 'file-browser-preview', + '#file-browser-preview-wrapper', + ); if (wrapper.length) { - $(wrapper).find('select').on('change', function () { - Drupal.ajax({ - url: settings.file_browser.preview_path + '/' + $(this).val(), - wrapper: 'file-browser-preview-wrapper' - }).execute(); - }); + $(wrapper) + .find('select') + .on('change', () => { + Drupal.ajax({ + url: `${settings.file_browser.preview_path} / ${this.val()}`, + wrapper: 'file-browser-preview-wrapper', + }).execute(); + }); } - } + }, }; - -}(jQuery, Drupal)); +})(jQuery, Drupal); diff --git a/js/file_browser.view.js b/js/file_browser.view.js index 60076932e4dbcecef4a6219893b6d84a00aac6a6..25ff830383647a3181fa710517cdd6d808d9560f 100644 --- a/js/file_browser.view.js +++ b/js/file_browser.view.js @@ -3,42 +3,61 @@ * file_browser.view.js */ -(function ($, Drupal) { - - "use strict"; - +(($, Drupal) => { /** * Renders the file counter based on our internally tracked count. */ function renderFileCounter() { - $('.file-browser-file-counter').each(function () { - $(this).remove(); - }); - var counter = []; - $('.entities-list [data-entity-id]').each(function () { - if (counter[this.dataset.entityId]) { - ++counter[this.dataset.entityId]; - } - else { - counter[this.dataset.entityId] = 1; - } - }); - for (var id in counter) { - var count = counter[id]; + document + .querySelectorAll('.file-browser-file-counter') + .forEach((el) => el.remove()); + + const counter = {}; + + document + .querySelectorAll('.entities-list [data-entity-id]') + .forEach((element) => { + const entityId = element.dataset.entityId; + if (counter[entityId]) { + counter[entityId] += 1; + } else { + counter[entityId] = 1; + } + }); + + Object.keys(counter).forEach((id) => { + const count = counter[id]; if (count > 0) { - var text = Drupal.formatPlural(count, 'Selected one time', 'Selected @count times'); - var $counter = $('<div class="file-browser-file-counter"></div>').text(text); - $('[name="entity_browser_select[file:' + id + ']"]').closest('.grid-item').find('.grid-item-info').prepend($counter); + const text = Drupal.formatPlural( + count, + 'Selected one time', + 'Selected @count times', + ); + const counterElement = document.createElement('div'); + counterElement.className = 'file-browser-file-counter'; + counterElement.textContent = text; + + const gridItemInfo = document + .querySelector(`[name = "entity_browser_select[file:${id}]"]`) + .closest('.grid-item') + .querySelector('.grid-item-info'); + + if (gridItemInfo) { + gridItemInfo.insertAdjacentElement('afterbegin', counterElement); + } } - } + }); } /** * Adjusts the padding on the body to account for the fixed actions bar. */ function adjustBodyPadding() { - setTimeout(function () { - $('body').css('padding-bottom', $('.file-browser-actions').outerHeight() + 'px'); + setTimeout(() => { + const bodyElement = document.querySelector('body'); + const actionsElement = document.querySelector('.file-browser-actions'); + const actionsHeight = actionsElement ? actionsElement.offsetHeight : 0; + bodyElement.style.paddingBottom = `${actionsHeight}px`; }, 2000); } @@ -46,18 +65,22 @@ * Initializes Masonry for the view widget. */ Drupal.behaviors.fileBrowserMasonry = { - attach: function (context) { - var $item = $('.grid-item', context); - var view = once('file-browser-init', $item.parent()); + attach(context) { + const $item = $('.grid-item', context); + const view = once('file-browser-init', $item.parent()); if (view.length) { - var $view = $(view); - $view.prepend('<div class="grid-sizer"></div><div class="gutter-sizer"></div>'); + const $view = $(view); + $view.prepend( + '<div class="grid-sizer"></div><div class="gutter-sizer"></div>', + ); // Indicate that images are loading. - $view.append('<div class="ajax-progress ajax-progress-fullscreen"> </div>'); - $view.imagesLoaded(function () { + $view.append( + '<div class="ajax-progress ajax-progress-fullscreen"> </div>', + ); + $view.imagesLoaded(() => { // Save the scroll position. - var scroll = document.body.scrollTop; + const scroll = document.body.scrollTop; // Remove old Masonry object if it exists. This allows modules like // Views Infinite Scroll to function with File Browser. if ($view.data('masonry')) { @@ -68,7 +91,7 @@ gutter: '.gutter-sizer', itemSelector: '.grid-item', percentPosition: true, - isFitWidth: true + isFitWidth: true, }); // Jump to the old scroll position. document.body.scrollTop = scroll; @@ -77,7 +100,7 @@ $view.find('.ajax-progress').remove(); }); } - } + }, }; /** @@ -87,20 +110,21 @@ * auto-select and multi-step. */ Drupal.behaviors.fileBrowserClickProxy = { - attach: function (context, settings) { + attach(context, settings) { if (!settings.entity_browser_widget.auto_select) { - $(once('bind-click-event', '.grid-item', context)).click(function () { - var input = $(this).find('.views-field-entity-browser-select input'); + $(once('bind-click-event', '.grid-item', context)).click(() => { + const input = $(this).find( + '.views-field-entity-browser-select input', + ); input.prop('checked', !input.prop('checked')); if (input.prop('checked')) { $(this).addClass('checked'); - } - else { + } else { $(this).removeClass('checked'); } }); } - } + }, }; /** @@ -108,23 +132,29 @@ * and displays that information on each grid item. */ Drupal.behaviors.fileBrowserEntityCount = { - attach: function (context) { + attach(context) { adjustBodyPadding(); renderFileCounter(); // Indicate when files have been selected. - var entities = once('file-browser-add-count', '.entities-list', context); + const entities = once( + 'file-browser-add-count', + '.entities-list', + context, + ); if (entities.length) { - $(entities).bind('add-entities', function (event, entity_ids) { - adjustBodyPadding(); - renderFileCounter(); + entities.forEach((entity) => { + entity.addEventListener('add-entities', () => { + adjustBodyPadding(); + renderFileCounter(); + }); }); - - $(entities).bind('remove-entities', function (event, entity_ids) { - adjustBodyPadding(); - renderFileCounter(); + entities.forEach((entity) => { + entity.addEventListener('remove-entities', () => { + adjustBodyPadding(); + renderFileCounter(); + }); }); } - } + }, }; - -}(jQuery, Drupal)); +})(jQuery, Drupal); diff --git a/modules/file_browser_example/config/install/block_content.type.file_browser.yml b/modules/file_browser_example/config/install/block_content.type.file_browser.yml index 803545280bba43440bdc13a6768761b956b10039..5e931a56557bc31679d44b17a1f4203cd2dfcb81 100644 --- a/modules/file_browser_example/config/install/block_content.type.file_browser.yml +++ b/modules/file_browser_example/config/install/block_content.type.file_browser.yml @@ -6,4 +6,4 @@ dependencies: id: file_browser label: 'File Browser' revision: 1 -description: 'An example Custom Block type that uses File Browser''s Entity Browser and EntityReferenceImageFormatter.' +description: "An example Custom Block type that uses File Browser's Entity Browser and EntityReferenceImageFormatter." diff --git a/modules/file_browser_example/config/install/core.entity_form_display.block_content.file_browser.default.yml b/modules/file_browser_example/config/install/core.entity_form_display.block_content.file_browser.default.yml index 5f33863469330e880efd94e8d0230e17e9cadb09..5e7df24df8413d637cd1f57a90cfd219bb8bfa22 100644 --- a/modules/file_browser_example/config/install/core.entity_form_display.block_content.file_browser.default.yml +++ b/modules/file_browser_example/config/install/core.entity_form_display.block_content.file_browser.default.yml @@ -19,7 +19,7 @@ content: field_widget_display: thumbnail field_widget_display_settings: image_style: medium - third_party_settings: { } + third_party_settings: {} type: entity_browser_entity_reference region: content info: @@ -28,6 +28,6 @@ content: settings: size: 60 placeholder: '' - third_party_settings: { } + third_party_settings: {} region: content -hidden: { } +hidden: {} diff --git a/modules/file_browser_example/config/install/core.entity_form_display.node.file_browser.default.yml b/modules/file_browser_example/config/install/core.entity_form_display.node.file_browser.default.yml index 4b429a45bdc9fde2641cc380814227a74bd07e2b..db4cd89ee3615b737fe133f8654bc05ab51b12a8 100644 --- a/modules/file_browser_example/config/install/core.entity_form_display.node.file_browser.default.yml +++ b/modules/file_browser_example/config/install/core.entity_form_display.node.file_browser.default.yml @@ -23,14 +23,14 @@ content: rows: 9 summary_rows: 3 placeholder: '' - third_party_settings: { } + third_party_settings: {} type: text_textarea_with_summary region: content created: type: datetime_timestamp weight: 4 - settings: { } - third_party_settings: { } + settings: {} + third_party_settings: {} region: content field_file_browser_image: weight: 2 @@ -40,34 +40,34 @@ content: field_widget_remove: true view_mode: default open: false - third_party_settings: { } + third_party_settings: {} type: entity_browser_file region: content langcode: type: language_select weight: 5 - settings: { } - third_party_settings: { } + settings: {} + third_party_settings: {} region: content path: type: path weight: 8 - settings: { } - third_party_settings: { } + settings: {} + third_party_settings: {} region: content promote: type: boolean_checkbox settings: display_label: true weight: 6 - third_party_settings: { } + third_party_settings: {} region: content sticky: type: boolean_checkbox settings: display_label: true weight: 7 - third_party_settings: { } + third_party_settings: {} region: content title: type: string_textfield @@ -75,7 +75,7 @@ content: settings: size: 60 placeholder: '' - third_party_settings: { } + third_party_settings: {} region: content uid: type: entity_reference_autocomplete @@ -84,6 +84,6 @@ content: match_operator: CONTAINS size: 60 placeholder: '' - third_party_settings: { } + third_party_settings: {} region: content -hidden: { } +hidden: {} diff --git a/modules/file_browser_example/config/install/core.entity_view_display.block_content.file_browser.default.yml b/modules/file_browser_example/config/install/core.entity_view_display.block_content.file_browser.default.yml index dfacc279d2ca6b495c6bec96bac80e23d1046620..35563bbe8f84c68f743d6a45cb1b72257c305b9d 100644 --- a/modules/file_browser_example/config/install/core.entity_view_display.block_content.file_browser.default.yml +++ b/modules/file_browser_example/config/install/core.entity_view_display.block_content.file_browser.default.yml @@ -18,7 +18,7 @@ content: settings: view_mode: default link: false - third_party_settings: { } + third_party_settings: {} type: entity_reference_entity_view region: content -hidden: { } +hidden: {} diff --git a/modules/file_browser_example/config/install/core.entity_view_display.node.file_browser.default.yml b/modules/file_browser_example/config/install/core.entity_view_display.node.file_browser.default.yml index 078ee9d90ba8eac1805ce2e2cbab8d98b02cba61..60c13bef0d9224e574e5442b91ecc57ec65f7e7a 100644 --- a/modules/file_browser_example/config/install/core.entity_view_display.node.file_browser.default.yml +++ b/modules/file_browser_example/config/install/core.entity_view_display.node.file_browser.default.yml @@ -20,8 +20,8 @@ content: body: weight: 3 label: above - settings: { } - third_party_settings: { } + settings: {} + third_party_settings: {} type: text_default region: content field_file_browser_image: @@ -30,13 +30,13 @@ content: settings: image_style: '' image_link: '' - third_party_settings: { } + third_party_settings: {} type: image region: content links: weight: 2 - settings: { } - third_party_settings: { } + settings: {} + third_party_settings: {} region: content hidden: langcode: true diff --git a/modules/file_browser_example/config/install/field.field.block_content.file_browser.field_file_browser_reference.yml b/modules/file_browser_example/config/install/field.field.block_content.file_browser.field_file_browser_reference.yml index e978217d0473796aa0eb52310caf6d6c08c71d57..a2973c09bac79592c2fda7f50f84b8e80e959b77 100644 --- a/modules/file_browser_example/config/install/field.field.block_content.file_browser.field_file_browser_reference.yml +++ b/modules/file_browser_example/config/install/field.field.block_content.file_browser.field_file_browser_reference.yml @@ -14,7 +14,7 @@ label: 'File Browser Reference' description: '' required: false translatable: false -default_value: { } +default_value: {} default_value_callback: '' settings: handler: 'default:file' diff --git a/modules/file_browser_example/config/install/field.field.node.file_browser.body.yml b/modules/file_browser_example/config/install/field.field.node.file_browser.body.yml index 441686ca0833723a42105d8a75ad092a4b290afa..3127b5506b23fe5f5496eb4d9e788c57190167bc 100644 --- a/modules/file_browser_example/config/install/field.field.node.file_browser.body.yml +++ b/modules/file_browser_example/config/install/field.field.node.file_browser.body.yml @@ -15,7 +15,7 @@ label: Body description: '' required: false translatable: true -default_value: { } +default_value: {} default_value_callback: '' settings: display_summary: false diff --git a/modules/file_browser_example/config/install/field.field.node.file_browser.field_file_browser_image.yml b/modules/file_browser_example/config/install/field.field.node.file_browser.field_file_browser_image.yml index 748a696efde93cd5704e7261a924b4ead06a0dfa..3370a8aa4009e7f4b94aeb84fc1fb324d25148d8 100644 --- a/modules/file_browser_example/config/install/field.field.node.file_browser.field_file_browser_image.yml +++ b/modules/file_browser_example/config/install/field.field.node.file_browser.field_file_browser_image.yml @@ -15,7 +15,7 @@ label: 'File Browser Image' description: '' required: false translatable: false -default_value: { } +default_value: {} default_value_callback: '' settings: file_directory: '[date:custom:Y]-[date:custom:m]' @@ -34,5 +34,5 @@ settings: width: null height: null handler: 'default:file' - handler_settings: { } + handler_settings: {} field_type: image diff --git a/modules/file_browser_example/config/install/field.storage.block_content.field_file_browser_reference.yml b/modules/file_browser_example/config/install/field.storage.block_content.field_file_browser_reference.yml index a11c544d7f82835e963c1ae6a047dfb6daf3965c..b527aab30dc159f8278f31584e6bba1206b8a669 100644 --- a/modules/file_browser_example/config/install/field.storage.block_content.field_file_browser_reference.yml +++ b/modules/file_browser_example/config/install/field.storage.block_content.field_file_browser_reference.yml @@ -15,6 +15,6 @@ module: core locked: false cardinality: -1 translatable: true -indexes: { } +indexes: {} persist_with_no_fields: false custom_storage: false diff --git a/modules/file_browser_example/config/install/field.storage.node.field_file_browser_image.yml b/modules/file_browser_example/config/install/field.storage.node.field_file_browser_image.yml index 3b97356d8dc1627eda21a27a8a8311aac9d686a0..e2ad07356cc862d0e1d69b8baaa683785d49dfa2 100644 --- a/modules/file_browser_example/config/install/field.storage.node.field_file_browser_image.yml +++ b/modules/file_browser_example/config/install/field.storage.node.field_file_browser_image.yml @@ -25,6 +25,6 @@ module: image locked: false cardinality: -1 translatable: true -indexes: { } +indexes: {} persist_with_no_fields: false custom_storage: false diff --git a/modules/file_browser_example/config/install/node.type.file_browser.yml b/modules/file_browser_example/config/install/node.type.file_browser.yml index 5e30e668b6bc12d1f75cbf289f8f1e621ebee4f0..079c8165314d415794a23fcbcdf6e693b2a7a1d4 100644 --- a/modules/file_browser_example/config/install/node.type.file_browser.yml +++ b/modules/file_browser_example/config/install/node.type.file_browser.yml @@ -11,7 +11,7 @@ third_party_settings: parent: 'main:' name: 'File Browser' type: file_browser -description: 'An example Custom Content type that uses File Browser''s Entity Browser and EntityReferenceImageFormatter.' +description: "An example Custom Content type that uses File Browser's Entity Browser and EntityReferenceImageFormatter." help: '' new_revision: false preview_mode: 1 diff --git a/src/Plugin/Block/ImageEmbedBlock.php b/src/Plugin/Block/ImageEmbedBlock.php index d55a4bfaa60bc97c6d0ff06979000891afe5cb78..5e5c1cfd1d93a264fbcb7d1ff5dc84dedecda2f6 100644 --- a/src/Plugin/Block/ImageEmbedBlock.php +++ b/src/Plugin/Block/ImageEmbedBlock.php @@ -5,7 +5,10 @@ namespace Drupal\file_browser\Plugin\Block; use Drupal\Component\Utility\NestedArray; use Drupal\Core\Block\BlockBase; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Image\ImageFactory; +use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\file\Entity\File; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Provides the "Image Embed" block. @@ -16,7 +19,46 @@ use Drupal\file\Entity\File; * category = @Translation("Embed") * ) */ -class ImageEmbedBlock extends BlockBase { +class ImageEmbedBlock extends BlockBase implements ContainerFactoryPluginInterface { + + /** + * The image factory service. + * + * @var \Drupal\Core\Image\ImageFactory + */ + protected ImageFactory $imageFactory; + + /** + * Constructs a new ImageEmbedBlock instance. + * + * @param \Symfony\Component\DependencyInjection\ContainerInterface $container + * The container to pull out services used in the plugin. + * @param mixed[] $configuration + * A configuration array containing information about the plugin instance. + * @param string $plugin_id + * The plugin ID for the plugin instance. + * @param mixed[] $plugin_definition + * The plugin implementation definition. + * + * @return static + * Returns an instance of this plugin. + */ + public static function create( + ContainerInterface $container, + array $configuration, + $plugin_id, + $plugin_definition, + ): static { + $instance = new static( + $configuration, + $plugin_id, + $plugin_definition, + ); + + $instance->imageFactory = $container->get('image.factory'); + + return $instance; + } /** * {@inheritdoc} @@ -45,7 +87,7 @@ class ImageEmbedBlock extends BlockBase { ], []); $files = []; foreach ($entities as $entity) { - $settings = isset($table[$entity->id()]) ? $table[$entity->id()] : []; + $settings = $table[$entity->id()] ?? []; $settings['fid'] = $entity->id(); $files[] = $settings; } @@ -120,7 +162,7 @@ class ImageEmbedBlock extends BlockBase { foreach ($files as $info) { $file = File::load($info['fid']); $uri = $file->getFileUri(); - $image = \Drupal::service('image.factory')->get($uri); + $image = $this->imageFactory->get($uri); if ($image->isValid()) { $width = $image->getWidth(); $height = $image->getHeight(); @@ -148,7 +190,7 @@ class ImageEmbedBlock extends BlockBase { 'alt' => [ '#type' => 'textfield', '#title' => $this->t('Alternative text'), - '#default_value' => isset($info['settings']['alt']) ? $info['settings']['alt'] : '', + '#default_value' => $info['settings']['alt'] ?? '', '#size' => 45, '#maxlength' => 512, '#description' => $this->t('This text will be used by screen readers, search engines, or when the image cannot be loaded.'), @@ -216,7 +258,7 @@ class ImageEmbedBlock extends BlockBase { $file = File::load($info['fid']); if ($file && $file->access('view')) { $uri = $file->getFileUri(); - $image = \Drupal::service('image.factory')->get($uri); + $image = $this->imageFactory->get($uri); if ($image->isValid()) { $width = $image->getWidth(); $height = $image->getHeight(); @@ -229,7 +271,7 @@ class ImageEmbedBlock extends BlockBase { '#theme' => 'image', '#width' => $width, '#height' => $height, - '#alt' => isset($info['settings']['alt']) ? $info['settings']['alt'] : '', + '#alt' => $info['settings']['alt'] ?? '', '#uri' => $uri, ]; diff --git a/src/Plugin/views/field/FileBrowserPreview.php b/src/Plugin/views/field/FileBrowserPreview.php index 51a8716c845f70edbb30a273a425abb4ef7fc0dc..3325ee88d32b33048698bae6499a8bd95911856e 100644 --- a/src/Plugin/views/field/FileBrowserPreview.php +++ b/src/Plugin/views/field/FileBrowserPreview.php @@ -69,7 +69,8 @@ class FileBrowserPreview extends FieldPluginBase { // Loading large files is slow, make sure it is an image mime type before // doing that. - list($type,) = explode('/', $file->getMimeType(), 2); + [$type] = explode('/', $file->getMimeType(), 2); + if ($type == 'image' && ($image = $image_factory->get($file->getFileUri())) && $image->isValid()) { // Fake an ImageItem object. $item = new \stdClass(); diff --git a/tests/src/Functional/InstallTest.php b/tests/src/Functional/InstallTest.php index e18add838e410cf5de7abe3a68d089bc3a0e6f98..a4f8539447a3cb3c936d22ddf8b77d305fb0d114 100644 --- a/tests/src/Functional/InstallTest.php +++ b/tests/src/Functional/InstallTest.php @@ -22,12 +22,12 @@ class InstallTest extends BrowserTestBase { /** * {@inheritdoc} */ - protected $defaultTheme = 'stable'; + protected $defaultTheme = 'claro'; /** * {@inheritdoc} */ - protected static $modules = ['file_browser']; + protected static $modules = ['file_browser', 'dropzonejs']; /** * Tests if the module can be installed during a config sync. diff --git a/tests/src/FunctionalJavascript/FileBrowserTest.php b/tests/src/FunctionalJavascript/FileBrowserTest.php index 2a670bbcf770062a048068b215291f21dbc2db18..52086f39aeeb3c3026590aeb8c50677e4ef31f6c 100644 --- a/tests/src/FunctionalJavascript/FileBrowserTest.php +++ b/tests/src/FunctionalJavascript/FileBrowserTest.php @@ -15,9 +15,15 @@ class FileBrowserTest extends EntityBrowserWebDriverTestBase { * {@inheritdoc} */ protected static $modules = [ + 'dropzonejs', 'file_browser', ]; + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'claro'; + /** * {@inheritdoc} */ @@ -41,7 +47,6 @@ class FileBrowserTest extends EntityBrowserWebDriverTestBase { 'type' => 'entity_browser_entity_reference', 'settings' => [ 'entity_browser' => 'browse_files', - 'field_widget_display' => 'label', 'open' => TRUE, ], ])->save();