summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathaniel Catchpole2018-06-22 14:05:00 (GMT)
committerNathaniel Catchpole2018-06-22 14:05:00 (GMT)
commitd4350e2b1ef7d92b9028dd302383955314b15a6c (patch)
treec91cde5310b1ababf903a367d3b2eb8f18167a8b
parent4dc2f4aea8bea761b6b51b366dea0d288e001b34 (diff)
Issue #2962110 by samuel.mortenson, drpal, andrewmacpherson, ckrina, phenaproxima, yoroy, webchick, amateescu, chr.fritsch, starshaped, lauriii, webflo, Dennis Cohn, dawehner, seanB, rfmarcelino, DyanneNova, benjifisher, jan.stoeckler, danbohea, John Pitcairn: Add the Media Library module to Drupal core
-rw-r--r--core/composer.json1
-rw-r--r--core/modules/media_library/config/install/core.entity_view_mode.media.media_library.yml12
-rw-r--r--core/modules/media_library/config/install/views.view.media_library.yml447
-rw-r--r--core/modules/media_library/config/optional/core.entity_view_display.media.audio.media_library.yml29
-rw-r--r--core/modules/media_library/config/optional/core.entity_view_display.media.file.media_library.yml29
-rw-r--r--core/modules/media_library/config/optional/core.entity_view_display.media.image.media_library.yml29
-rw-r--r--core/modules/media_library/config/optional/core.entity_view_display.media.video.media_library.yml29
-rw-r--r--core/modules/media_library/css/media_library.module.css60
-rw-r--r--core/modules/media_library/css/media_library.theme.css151
-rw-r--r--core/modules/media_library/js/media_library.click_to_select.es6.js31
-rw-r--r--core/modules/media_library/js/media_library.click_to_select.js24
-rw-r--r--core/modules/media_library/js/media_library.view.es6.js58
-rw-r--r--core/modules/media_library/js/media_library.view.js50
-rw-r--r--core/modules/media_library/media_library.info.yml10
-rw-r--r--core/modules/media_library/media_library.install49
-rw-r--r--core/modules/media_library/media_library.libraries.yml25
-rw-r--r--core/modules/media_library/media_library.links.action.yml5
-rw-r--r--core/modules/media_library/media_library.links.task.yml10
-rw-r--r--core/modules/media_library/media_library.module109
-rw-r--r--core/modules/media_library/templates/media--media-library.html.twig50
-rw-r--r--core/modules/media_library/tests/modules/media_library_test/config/install/core.entity_form_display.media.type_one.default.yml43
-rw-r--r--core/modules/media_library/tests/modules/media_library_test/config/install/core.entity_form_display.media.type_two.default.yml43
-rw-r--r--core/modules/media_library/tests/modules/media_library_test/config/install/core.entity_view_display.media.type_one.default.yml50
-rw-r--r--core/modules/media_library/tests/modules/media_library_test/config/install/core.entity_view_display.media.type_two.default.yml50
-rw-r--r--core/modules/media_library/tests/modules/media_library_test/config/install/field.field.media.type_one.field_media_test.yml18
-rw-r--r--core/modules/media_library/tests/modules/media_library_test/config/install/field.field.media.type_two.field_media_test_1.yml18
-rw-r--r--core/modules/media_library/tests/modules/media_library_test/config/install/field.storage.media.field_media_test.yml20
-rw-r--r--core/modules/media_library/tests/modules/media_library_test/config/install/field.storage.media.field_media_test_1.yml20
-rw-r--r--core/modules/media_library/tests/modules/media_library_test/config/install/media.type.type_one.yml16
-rw-r--r--core/modules/media_library/tests/modules/media_library_test/config/install/media.type.type_two.yml16
-rw-r--r--core/modules/media_library/tests/modules/media_library_test/media_library_test.info.yml10
-rw-r--r--core/modules/media_library/tests/src/FunctionalJavascript/MediaLibraryTest.php102
32 files changed, 1614 insertions, 0 deletions
diff --git a/core/composer.json b/core/composer.json
index 7452a07..770631d 100644
--- a/core/composer.json
+++ b/core/composer.json
@@ -133,6 +133,7 @@
"drupal/locale": "self.version",
"drupal/minimal": "self.version",
"drupal/media": "self.version",
+ "drupal/media_library": "self.version",
"drupal/menu_link_content": "self.version",
"drupal/menu_ui": "self.version",
"drupal/migrate": "self.version",
diff --git a/core/modules/media_library/config/install/core.entity_view_mode.media.media_library.yml b/core/modules/media_library/config/install/core.entity_view_mode.media.media_library.yml
new file mode 100644
index 0000000..3406f02
--- /dev/null
+++ b/core/modules/media_library/config/install/core.entity_view_mode.media.media_library.yml
@@ -0,0 +1,12 @@
+langcode: en
+status: true
+dependencies:
+ enforced:
+ module:
+ - media_library
+ module:
+ - media
+id: media.media_library
+label: 'Media library'
+targetEntityType: media
+cache: true
diff --git a/core/modules/media_library/config/install/views.view.media_library.yml b/core/modules/media_library/config/install/views.view.media_library.yml
new file mode 100644
index 0000000..8c9e784
--- /dev/null
+++ b/core/modules/media_library/config/install/views.view.media_library.yml
@@ -0,0 +1,447 @@
+langcode: en
+status: true
+dependencies:
+ config:
+ - core.entity_view_mode.media.media_library
+ enforced:
+ module:
+ - media_library
+ module:
+ - media
+ - user
+id: media_library
+label: 'Media library'
+module: views
+description: ''
+tag: ''
+base_table: media_field_data
+base_field: mid
+core: 8.x
+display:
+ default:
+ display_plugin: default
+ id: default
+ display_title: Master
+ position: 0
+ display_options:
+ access:
+ type: perm
+ options:
+ perm: 'access media overview'
+ cache:
+ type: tag
+ options: { }
+ query:
+ type: views_query
+ options:
+ disable_sql_rewrite: false
+ distinct: false
+ replica: false
+ query_comment: ''
+ query_tags: { }
+ exposed_form:
+ type: basic
+ options:
+ submit_button: 'Apply Filters'
+ reset_button: false
+ reset_button_label: Reset
+ exposed_sorts_label: 'Sort by'
+ expose_sort_order: false
+ sort_asc_label: Asc
+ sort_desc_label: Desc
+ pager:
+ type: mini
+ options:
+ items_per_page: 25
+ offset: 0
+ id: 0
+ total_pages: null
+ expose:
+ items_per_page: false
+ items_per_page_label: 'Items per page'
+ items_per_page_options: '5, 10, 25, 50'
+ items_per_page_options_all: false
+ items_per_page_options_all_label: '- All -'
+ offset: false
+ offset_label: Offset
+ tags:
+ previous: ‹‹
+ next: ››
+ style:
+ type: default
+ options:
+ grouping: { }
+ row_class: 'media-library-item js-click-to-select'
+ default_row_class: true
+ row:
+ type: fields
+ options:
+ default_field_elements: true
+ inline: { }
+ separator: ''
+ hide_empty: false
+ fields:
+ media_bulk_form:
+ id: media_bulk_form
+ table: media
+ field: media_bulk_form
+ relationship: none
+ group_type: group
+ admin_label: ''
+ label: ''
+ exclude: false
+ alter:
+ alter_text: false
+ text: ''
+ make_link: false
+ path: ''
+ absolute: false
+ external: false
+ replace_spaces: false
+ path_case: none
+ trim_whitespace: false
+ alt: ''
+ rel: ''
+ link_class: ''
+ prefix: ''
+ suffix: ''
+ target: ''
+ nl2br: false
+ max_length: 0
+ word_boundary: true
+ ellipsis: true
+ more_link: false
+ more_link_text: ''
+ more_link_path: ''
+ strip_tags: false
+ trim: false
+ preserve_tags: ''
+ html: false
+ element_type: ''
+ element_class: js-click-to-select__checkbox
+ element_label_type: ''
+ element_label_class: ''
+ element_label_colon: false
+ element_wrapper_type: ''
+ element_wrapper_class: ''
+ element_default_classes: true
+ empty: ''
+ hide_empty: false
+ empty_zero: false
+ hide_alter_empty: true
+ action_title: Action
+ include_exclude: exclude
+ selected_actions: { }
+ entity_type: media
+ plugin_id: bulk_form
+ rendered_entity:
+ id: rendered_entity
+ table: media
+ field: rendered_entity
+ relationship: none
+ group_type: group
+ admin_label: ''
+ label: ''
+ exclude: false
+ alter:
+ alter_text: false
+ text: ''
+ make_link: false
+ path: ''
+ absolute: false
+ external: false
+ replace_spaces: false
+ path_case: none
+ trim_whitespace: false
+ alt: ''
+ rel: ''
+ link_class: ''
+ prefix: ''
+ suffix: ''
+ target: ''
+ nl2br: false
+ max_length: 0
+ word_boundary: true
+ ellipsis: true
+ more_link: false
+ more_link_text: ''
+ more_link_path: ''
+ strip_tags: false
+ trim: false
+ preserve_tags: ''
+ html: false
+ element_type: ''
+ element_class: media-library-item__content
+ element_label_type: ''
+ element_label_class: ''
+ element_label_colon: false
+ element_wrapper_type: ''
+ element_wrapper_class: ''
+ element_default_classes: true
+ empty: ''
+ hide_empty: false
+ empty_zero: false
+ hide_alter_empty: true
+ view_mode: media_library
+ entity_type: media
+ plugin_id: rendered_entity
+ filters:
+ status:
+ id: status
+ table: media_field_data
+ field: status
+ relationship: none
+ group_type: group
+ admin_label: ''
+ operator: '='
+ value: '1'
+ group: 1
+ exposed: true
+ expose:
+ operator_id: ''
+ label: 'Publishing status'
+ description: null
+ use_operator: false
+ operator: status_op
+ identifier: status
+ required: true
+ remember: false
+ multiple: false
+ remember_roles:
+ authenticated: authenticated
+ is_grouped: true
+ group_info:
+ label: Published
+ description: ''
+ identifier: status
+ optional: true
+ widget: select
+ multiple: false
+ remember: false
+ default_group: All
+ default_group_multiple: { }
+ group_items:
+ 1:
+ title: Published
+ operator: '='
+ value: '1'
+ 2:
+ title: Unpublished
+ operator: '='
+ value: '0'
+ plugin_id: boolean
+ entity_type: media
+ entity_field: status
+ name:
+ id: name
+ table: media_field_data
+ field: name
+ relationship: none
+ group_type: group
+ admin_label: ''
+ operator: contains
+ value: ''
+ group: 1
+ exposed: true
+ expose:
+ operator_id: name_op
+ label: Name
+ description: ''
+ use_operator: false
+ operator: name_op
+ identifier: name
+ required: false
+ remember: false
+ multiple: false
+ remember_roles:
+ authenticated: authenticated
+ anonymous: '0'
+ administrator: '0'
+ is_grouped: false
+ group_info:
+ label: ''
+ description: ''
+ identifier: ''
+ optional: true
+ widget: select
+ multiple: false
+ remember: false
+ default_group: All
+ default_group_multiple: { }
+ group_items: { }
+ entity_type: media
+ entity_field: name
+ plugin_id: string
+ bundle:
+ id: bundle
+ table: media_field_data
+ field: bundle
+ relationship: none
+ group_type: group
+ admin_label: ''
+ operator: in
+ value: { }
+ group: 1
+ exposed: true
+ expose:
+ operator_id: bundle_op
+ label: 'Media type'
+ description: ''
+ use_operator: false
+ operator: bundle_op
+ identifier: type
+ required: false
+ remember: false
+ multiple: false
+ remember_roles:
+ authenticated: authenticated
+ anonymous: '0'
+ administrator: '0'
+ reduce: false
+ is_grouped: false
+ group_info:
+ label: 'Media type'
+ description: null
+ identifier: bundle
+ optional: true
+ widget: select
+ multiple: false
+ remember: false
+ default_group: All
+ default_group_multiple: { }
+ group_items:
+ 1: { }
+ 2: { }
+ 3: { }
+ entity_type: media
+ entity_field: bundle
+ plugin_id: bundle
+ sorts:
+ created:
+ id: created
+ table: media_field_data
+ field: created
+ relationship: none
+ group_type: group
+ admin_label: ''
+ order: DESC
+ exposed: true
+ expose:
+ label: 'Newest first'
+ granularity: second
+ entity_type: media
+ entity_field: created
+ plugin_id: date
+ name:
+ id: name
+ table: media_field_data
+ field: name
+ relationship: none
+ group_type: group
+ admin_label: ''
+ order: ASC
+ exposed: true
+ expose:
+ label: 'Name (A-Z)'
+ entity_type: media
+ entity_field: name
+ plugin_id: standard
+ name_1:
+ id: name_1
+ table: media_field_data
+ field: name
+ relationship: none
+ group_type: group
+ admin_label: ''
+ order: DESC
+ exposed: true
+ expose:
+ label: 'Name (Z-A)'
+ entity_type: media
+ entity_field: name
+ plugin_id: standard
+ title: Media
+ header: { }
+ footer: { }
+ empty: { }
+ relationships: { }
+ arguments:
+ bundle:
+ id: bundle
+ table: media_field_data
+ field: bundle
+ relationship: none
+ group_type: group
+ admin_label: ''
+ default_action: ignore
+ exception:
+ value: all
+ title_enable: false
+ title: All
+ title_enable: false
+ title: ''
+ default_argument_type: fixed
+ default_argument_options:
+ argument: ''
+ default_argument_skip_url: false
+ summary_options:
+ base_path: ''
+ count: true
+ items_per_page: 25
+ override: false
+ summary:
+ sort_order: asc
+ number_of_records: 0
+ format: default_summary
+ specify_validation: false
+ validate:
+ type: none
+ fail: 'not found'
+ validate_options: { }
+ glossary: false
+ limit: 0
+ case: none
+ path_case: none
+ transform_dash: false
+ break_phrase: false
+ entity_type: media
+ entity_field: bundle
+ plugin_id: string
+ display_extenders: { }
+ use_ajax: true
+ css_class: media-library-view
+ cache_metadata:
+ max-age: 0
+ contexts:
+ - 'languages:language_interface'
+ - url
+ - url.query_args
+ - 'url.query_args:sort_by'
+ - user.permissions
+ tags: { }
+ page:
+ display_plugin: page
+ id: page
+ display_title: Page
+ position: 1
+ display_options:
+ display_extenders: { }
+ path: admin/content/media
+ menu:
+ type: tab
+ title: Media
+ description: 'Allows users to browse and administer media items'
+ expanded: false
+ parent: system.admin_content
+ weight: 5
+ context: '0'
+ menu_name: admin
+ cache_metadata:
+ max-age: 0
+ contexts:
+ - 'languages:language_interface'
+ - url
+ - url.query_args
+ - 'url.query_args:sort_by'
+ - user.permissions
+ tags: { }
diff --git a/core/modules/media_library/config/optional/core.entity_view_display.media.audio.media_library.yml b/core/modules/media_library/config/optional/core.entity_view_display.media.audio.media_library.yml
new file mode 100644
index 0000000..e74e3eb
--- /dev/null
+++ b/core/modules/media_library/config/optional/core.entity_view_display.media.audio.media_library.yml
@@ -0,0 +1,29 @@
+langcode: en
+status: true
+dependencies:
+ config:
+ - core.entity_view_mode.media.media_library
+ - field.field.media.audio.field_media_audio_file
+ - image.style.thumbnail
+ - media.type.audio
+ module:
+ - image
+id: media.audio.media_library
+targetEntityType: media
+bundle: audio
+mode: media_library
+content:
+ thumbnail:
+ type: image
+ weight: 0
+ region: content
+ label: hidden
+ settings:
+ image_style: thumbnail
+ image_link: ''
+ third_party_settings: { }
+hidden:
+ created: true
+ field_media_audio_file: true
+ name: true
+ uid: true
diff --git a/core/modules/media_library/config/optional/core.entity_view_display.media.file.media_library.yml b/core/modules/media_library/config/optional/core.entity_view_display.media.file.media_library.yml
new file mode 100644
index 0000000..e09e611
--- /dev/null
+++ b/core/modules/media_library/config/optional/core.entity_view_display.media.file.media_library.yml
@@ -0,0 +1,29 @@
+langcode: en
+status: true
+dependencies:
+ config:
+ - core.entity_view_mode.media.media_library
+ - field.field.media.file.field_media_file
+ - image.style.thumbnail
+ - media.type.file
+ module:
+ - image
+id: media.file.media_library
+targetEntityType: media
+bundle: file
+mode: media_library
+content:
+ thumbnail:
+ type: image
+ weight: 0
+ region: content
+ label: hidden
+ settings:
+ image_style: thumbnail
+ image_link: ''
+ third_party_settings: { }
+hidden:
+ created: true
+ field_media_file: true
+ name: true
+ uid: true
diff --git a/core/modules/media_library/config/optional/core.entity_view_display.media.image.media_library.yml b/core/modules/media_library/config/optional/core.entity_view_display.media.image.media_library.yml
new file mode 100644
index 0000000..a916760
--- /dev/null
+++ b/core/modules/media_library/config/optional/core.entity_view_display.media.image.media_library.yml
@@ -0,0 +1,29 @@
+langcode: en
+status: true
+dependencies:
+ config:
+ - core.entity_view_mode.media.media_library
+ - field.field.media.image.field_media_image
+ - image.style.medium
+ - media.type.image
+ module:
+ - image
+id: media.image.media_library
+targetEntityType: media
+bundle: image
+mode: media_library
+content:
+ thumbnail:
+ type: image
+ weight: 0
+ region: content
+ label: hidden
+ settings:
+ image_style: medium
+ image_link: ''
+ third_party_settings: { }
+hidden:
+ created: true
+ field_media_image: true
+ name: true
+ uid: true
diff --git a/core/modules/media_library/config/optional/core.entity_view_display.media.video.media_library.yml b/core/modules/media_library/config/optional/core.entity_view_display.media.video.media_library.yml
new file mode 100644
index 0000000..33d4e88
--- /dev/null
+++ b/core/modules/media_library/config/optional/core.entity_view_display.media.video.media_library.yml
@@ -0,0 +1,29 @@
+langcode: en
+status: true
+dependencies:
+ config:
+ - core.entity_view_mode.media.media_library
+ - field.field.media.video.field_media_video_file
+ - image.style.thumbnail
+ - media.type.video
+ module:
+ - image
+id: media.video.media_library
+targetEntityType: media
+bundle: video
+mode: media_library
+content:
+ thumbnail:
+ type: image
+ weight: 0
+ region: content
+ label: hidden
+ settings:
+ image_style: thumbnail
+ image_link: ''
+ third_party_settings: { }
+hidden:
+ created: true
+ field_media_video_file: true
+ name: true
+ uid: true
diff --git a/core/modules/media_library/css/media_library.module.css b/core/modules/media_library/css/media_library.module.css
new file mode 100644
index 0000000..11ad56d
--- /dev/null
+++ b/core/modules/media_library/css/media_library.module.css
@@ -0,0 +1,60 @@
+/**
+* @file media_library.module.css
+*/
+
+.media-library-page-form {
+ display: flex;
+ flex-wrap: wrap;
+}
+
+.media-library-page-form > .form-actions {
+ flex-basis: 100%;
+}
+
+.media-library-page-form__header > div,
+.media-library-view .form--inline {
+ display: flex;
+ flex-wrap: wrap;
+}
+
+.media-library-page-form__header {
+ flex-basis: 100%;
+}
+
+.media-library-item {
+ position: relative;
+}
+
+.media-library-item .js-click-to-select__trigger {
+ overflow: hidden;
+ cursor: pointer;
+}
+
+.media-library-view .form-actions {
+ align-self: flex-end;
+}
+
+.media-library-item .js-click-to-select__checkbox {
+ position: absolute;
+ display: block;
+ z-index: 1;
+ top: 5px;
+ right: 0;
+}
+
+.media-library-item__status {
+ position: absolute;
+ top: 10px;
+ left: 2px;
+ pointer-events: none;
+}
+
+.media-library-select-all {
+ flex-basis: 100%;
+}
+
+@media screen and (max-width: 600px) {
+ .media-library-view .form-actions {
+ flex-basis: 100%;
+ }
+}
diff --git a/core/modules/media_library/css/media_library.theme.css b/core/modules/media_library/css/media_library.theme.css
new file mode 100644
index 0000000..0427143
--- /dev/null
+++ b/core/modules/media_library/css/media_library.theme.css
@@ -0,0 +1,151 @@
+/**
+ * @file media_library.theme.css
+ *
+ * @todo Move into the Seven theme when this module is marked as stable.
+ * @see https://www.drupal.org/project/drupal/issues/2980769
+ */
+
+.media-library-page-form__header .form-item {
+ margin-right: 8px;
+}
+
+#drupal-modal .view-header {
+ margin: 16px 0;
+}
+
+.media-library-item {
+ justify-content: center;
+ vertical-align: top;
+ padding: 2px;
+ border: 1px solid #ebebeb;
+ margin: 16px 16px 2px 2px;
+ width: 180px;
+ background: #fff;
+ transition: border-color 0.2s, color 0.2s, background 0.2s;
+}
+
+.media-library-view .form-actions {
+ margin: 0.75em 0;
+}
+
+.media-library-item .field--name-thumbnail {
+ background-color: #ebebeb;
+ margin: 2px;
+ overflow: hidden;
+ text-align: center;
+}
+
+.media-library-item .field--name-thumbnail img {
+ height: 180px;
+ object-fit: contain;
+ object-position: center center;
+}
+
+.media-library-item.is-hover,
+.media-library-item.checked,
+.media-library-item.is-focus {
+ border-color: #40b6ff;
+ border-width: 3px;
+ border-radius: 3px;
+ margin: 14px 14px 0 0;
+}
+
+.media-library-item.checked {
+ border-color: #0076c0;
+}
+
+.media-library-item .js-click-to-select__checkbox input {
+ width: 30px;
+ height: 30px;
+}
+
+.media-library-item .js-click-to-select__checkbox .form-item {
+ margin: 0;
+}
+
+.media-library-item__preview {
+ padding-bottom: 44px;
+}
+
+.media-library-item__status {
+ color: #e4e4e4;
+ font-style: italic;
+ background: #666;
+ padding: 5px 10px;
+ font-size: 12px;
+}
+
+.media-library-item .views-field-operations {
+ height: 30px;
+}
+
+.media-library-item .views-field-operations .dropbutton-wrapper {
+ display: inline-block;
+ position: absolute;
+ right: 5px;
+ bottom: 5px;
+}
+
+.media-library-item__attributes {
+ position: absolute;
+ bottom: 0;
+ display: block;
+ padding: 10px;
+ max-width: calc(100% - 20px);
+ max-height: calc(100% - 60px);
+ overflow: hidden;
+ background: white;
+}
+
+.media-library-item__name {
+ font-size: 14px;
+}
+
+.media-library-item__name a {
+ display: block;
+ text-decoration: underline;
+ margin: 2px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.media-library-item__attributes:hover .media-library-item__name a,
+.media-library-item__name a:focus,
+.media-library-item.is-focus .media-library-item__name a,
+.media-library-item.checked .media-library-item__name a {
+ white-space: normal;
+}
+
+.media-library-item__name a:focus {
+ border: 2px solid;
+ margin: 0;
+}
+
+.media-library-item__type {
+ font-size: 12px;
+ color: #696969;
+}
+
+.media-library-select-all {
+ margin: 10px 0 10px 0;
+}
+
+.media-library-select-all input {
+ margin-right: 10px;
+}
+
+@media screen and (max-width: 600px) {
+ .media-library-item {
+ width: 150px;
+ }
+ .media-library-item .field--name-thumbnail img {
+ height: 150px;
+ width: 150px;
+ }
+ .media-library-item .views-field-operations .dropbutton-wrapper {
+ position: relative;
+ right: 0;
+ border: 0;
+ }
+}
diff --git a/core/modules/media_library/js/media_library.click_to_select.es6.js b/core/modules/media_library/js/media_library.click_to_select.es6.js
new file mode 100644
index 0000000..321ffe0
--- /dev/null
+++ b/core/modules/media_library/js/media_library.click_to_select.es6.js
@@ -0,0 +1,31 @@
+/**
+ * @file media_library.click_to_select.es6.js
+ */
+
+(($, Drupal) => {
+ /**
+ * Allows users to select an element which checks a hidden checkbox.
+ */
+ Drupal.behaviors.ClickToSelect = {
+ attach(context) {
+ $('.js-click-to-select__trigger', context)
+ .once('media-library-click-to-select')
+ .on('click', (event) => {
+ // Links inside the trigger should not be click-able.
+ event.preventDefault();
+ // Click the hidden checkbox when the trigger is clicked.
+ const $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', ({ currentTarget }) => {
+ $(currentTarget)
+ .closest('.js-click-to-select')
+ .toggleClass('checked', $(currentTarget).prop('checked'));
+ });
+ },
+ };
+})(jQuery, Drupal);
diff --git a/core/modules/media_library/js/media_library.click_to_select.js b/core/modules/media_library/js/media_library.click_to_select.js
new file mode 100644
index 0000000..4bc041c
--- /dev/null
+++ b/core/modules/media_library/js/media_library.click_to_select.js
@@ -0,0 +1,24 @@
+/**
+* DO NOT EDIT THIS FILE.
+* See the following change record for more information,
+* https://www.drupal.org/node/2815083
+* @preserve
+**/
+
+(function ($, Drupal) {
+ Drupal.behaviors.ClickToSelect = {
+ attach: function attach(context) {
+ $('.js-click-to-select__trigger', context).once('media-library-click-to-select').on('click', function (event) {
+ event.preventDefault();
+
+ 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'));
+ });
+ }
+ };
+})(jQuery, Drupal); \ No newline at end of file
diff --git a/core/modules/media_library/js/media_library.view.es6.js b/core/modules/media_library/js/media_library.view.es6.js
new file mode 100644
index 0000000..26e9a5b
--- /dev/null
+++ b/core/modules/media_library/js/media_library.view.es6.js
@@ -0,0 +1,58 @@
+/**
+ * @file media_library.view.es6.js
+ */
+(($, Drupal) => {
+ /**
+ * Adds hover effect to media items.
+ */
+ Drupal.behaviors.MediaLibraryHover = {
+ attach(context) {
+ $('.media-library-item .js-click-to-select__trigger,.media-library-item .js-click-to-select__checkbox', context).once('media-library-item-hover')
+ .on('mouseover mouseout', ({ currentTarget, type }) => {
+ $(currentTarget).closest('.media-library-item').toggleClass('is-hover', type === 'mouseover');
+ });
+ },
+ };
+
+ /**
+ * Adds focus effect to media items.
+ */
+ Drupal.behaviors.MediaLibraryFocus = {
+ attach(context) {
+ $('.media-library-item .js-click-to-select__checkbox input', context).once('media-library-item-focus')
+ .on('focus blur', ({ currentTarget, type }) => {
+ $(currentTarget).closest('.media-library-item').toggleClass('is-focus', type === 'focus');
+ });
+ },
+ };
+
+ /**
+ * Adds checkbox to select all items in the library.
+ */
+ Drupal.behaviors.MediaLibrarySelectAll = {
+ attach(context) {
+ const $view = $('.media-library-view', context).once('media-library-select-all');
+ if ($view.length && $view.find('.media-library-item').length) {
+ const $checkbox = $('<input type="checkbox" class="form-checkbox" />')
+ .on('click', ({ currentTarget }) => {
+ // Toggle all checkboxes.
+ const $checkboxes = $(currentTarget)
+ .closest('.media-library-view')
+ .find('.media-library-item input[type="checkbox"]');
+ $checkboxes
+ .prop('checked', $(currentTarget).prop('checked'))
+ .trigger('change');
+ // Announce the selection.
+ const announcement = $(currentTarget).prop('checked') ?
+ Drupal.t('Zero items selected') :
+ Drupal.t('All @count items selected', { '@count': $checkboxes.length });
+ Drupal.announce(announcement);
+ });
+ const $label = $('<label class="media-library-select-all"></label>')
+ .text(Drupal.t('Select all media'));
+ $label.prepend($checkbox);
+ $view.find('.media-library-item').first().before($label);
+ }
+ },
+ };
+})(jQuery, Drupal);
diff --git a/core/modules/media_library/js/media_library.view.js b/core/modules/media_library/js/media_library.view.js
new file mode 100644
index 0000000..1cde60c
--- /dev/null
+++ b/core/modules/media_library/js/media_library.view.js
@@ -0,0 +1,50 @@
+/**
+* DO NOT EDIT THIS FILE.
+* See the following change record for more information,
+* https://www.drupal.org/node/2815083
+* @preserve
+**/
+
+(function ($, Drupal) {
+ Drupal.behaviors.MediaLibraryHover = {
+ attach: function attach(context) {
+ $('.media-library-item .js-click-to-select__trigger,.media-library-item .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('.media-library-item').toggleClass('is-hover', type === 'mouseover');
+ });
+ }
+ };
+
+ Drupal.behaviors.MediaLibraryFocus = {
+ attach: function attach(context) {
+ $('.media-library-item .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('.media-library-item').toggleClass('is-focus', type === 'focus');
+ });
+ }
+ };
+
+ Drupal.behaviors.MediaLibrarySelectAll = {
+ attach: function attach(context) {
+ var $view = $('.media-library-view', context).once('media-library-select-all');
+ if ($view.length && $view.find('.media-library-item').length) {
+ var $checkbox = $('<input type="checkbox" class="form-checkbox" />').on('click', function (_ref3) {
+ var currentTarget = _ref3.currentTarget;
+
+ var $checkboxes = $(currentTarget).closest('.media-library-view').find('.media-library-item input[type="checkbox"]');
+ $checkboxes.prop('checked', $(currentTarget).prop('checked')).trigger('change');
+
+ var announcement = $(currentTarget).prop('checked') ? Drupal.t('Zero items selected') : Drupal.t('All @count items selected', { '@count': $checkboxes.length });
+ Drupal.announce(announcement);
+ });
+ var $label = $('<label class="media-library-select-all"></label>').text(Drupal.t('Select all media'));
+ $label.prepend($checkbox);
+ $view.find('.media-library-item').first().before($label);
+ }
+ }
+ };
+})(jQuery, Drupal); \ No newline at end of file
diff --git a/core/modules/media_library/media_library.info.yml b/core/modules/media_library/media_library.info.yml
new file mode 100644
index 0000000..9f7aa91
--- /dev/null
+++ b/core/modules/media_library/media_library.info.yml
@@ -0,0 +1,10 @@
+name: 'Media library'
+type: module
+description: 'Provides a library for re-using Media Items.'
+package: Core (Experimental)
+version: VERSION
+core: 8.x
+dependencies:
+ - drupal:media
+ - drupal:views
+ - drupal:user
diff --git a/core/modules/media_library/media_library.install b/core/modules/media_library/media_library.install
new file mode 100644
index 0000000..79a9786
--- /dev/null
+++ b/core/modules/media_library/media_library.install
@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * @file
+ * Install, update and uninstall functions for the media_library module.
+ */
+
+use Drupal\views\Entity\View;
+
+/**
+ * Implements hook_install().
+ */
+function media_library_install() {
+ // Change the path to the original media view.
+ /** @var \Drupal\views\Entity\View $view */
+ if ($view = View::load('media')) {
+ $display = &$view->getDisplay('media_page_list');
+ if (!empty($display)) {
+ $display['display_options']['path'] = 'admin/content/media-table';
+ unset($display['display_options']['menu']);
+ $view->trustData()->save();
+ }
+ }
+}
+
+/**
+ * Implements hook_uninstall().
+ */
+function media_library_uninstall() {
+ // Restore the path to the original media view.
+ /** @var \Drupal\views\Entity\View $view */
+ if ($view = View::load('media')) {
+ $display = &$view->getDisplay('media_page_list');
+ if (!empty($display)) {
+ $display['display_options']['path'] = 'admin/content/media';
+ $display['display_options']['menu'] = [
+ 'type' => 'tab',
+ 'title' => 'Media',
+ 'description' => '',
+ 'expanded' => FALSE,
+ 'parent' => '',
+ 'weight' => 0,
+ 'context' => '0',
+ 'menu_name' => 'main',
+ ];
+ $view->trustData()->save();
+ }
+ }
+}
diff --git a/core/modules/media_library/media_library.libraries.yml b/core/modules/media_library/media_library.libraries.yml
new file mode 100644
index 0000000..e32dbe0
--- /dev/null
+++ b/core/modules/media_library/media_library.libraries.yml
@@ -0,0 +1,25 @@
+style:
+ version: VERSION
+ css:
+ component:
+ css/media_library.module.css: {}
+ theme:
+ css/media_library.theme.css: {}
+
+click_to_select:
+ version: VERSION
+ js:
+ js/media_library.click_to_select.js: {}
+ dependencies:
+ - core/drupal
+ - core/jquery.once
+
+view:
+ version: VERSION
+ js:
+ js/media_library.view.js: {}
+ dependencies:
+ - media_library/style
+ - media_library/click_to_select
+ - core/drupal.announce
+ - core/jquery.once
diff --git a/core/modules/media_library/media_library.links.action.yml b/core/modules/media_library/media_library.links.action.yml
new file mode 100644
index 0000000..6a37769
--- /dev/null
+++ b/core/modules/media_library/media_library.links.action.yml
@@ -0,0 +1,5 @@
+media_library.add:
+ route_name: entity.media.add_page
+ title: 'Add media'
+ appears_on:
+ - view.media_library.page
diff --git a/core/modules/media_library/media_library.links.task.yml b/core/modules/media_library/media_library.links.task.yml
new file mode 100644
index 0000000..757ecd8
--- /dev/null
+++ b/core/modules/media_library/media_library.links.task.yml
@@ -0,0 +1,10 @@
+media_library.grid:
+ title: 'Grid'
+ parent_id: entity.media.collection
+ route_name: entity.media.collection
+ weight: 10
+media_library.table:
+ title: 'Table'
+ parent_id: entity.media.collection
+ route_name: view.media.media_page_list
+ weight: 20
diff --git a/core/modules/media_library/media_library.module b/core/modules/media_library/media_library.module
new file mode 100644
index 0000000..63b3cad
--- /dev/null
+++ b/core/modules/media_library/media_library.module
@@ -0,0 +1,109 @@
+<?php
+
+/**
+ * @file
+ * Contains hook implementations for the media_library module.
+ */
+
+use Drupal\Core\Routing\RouteMatchInterface;
+use Drupal\views\Plugin\views\cache\CachePluginBase;
+use Drupal\views\ViewExecutable;
+use Drupal\Core\Template\Attribute;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Render\Element;
+
+/**
+ * Implements hook_help().
+ *
+ * @todo Update in https://www.drupal.org/project/drupal/issues/2964789
+ */
+function media_library_help($route_name, RouteMatchInterface $route_match) {
+ switch ($route_name) {
+ case 'help.page.media_library':
+ $output = '<h3>' . t('About') . '</h3>';
+ $output .= '<p>' . t('The Media library module overrides the /admin/content/media view to provide a rich visual interface for performing administrative operations on media. For more information, see the <a href=":media">online documentation for the Media library module</a>.', [':media' => 'https://www.drupal.org/docs/8/core/modules/media']) . '</p>';
+ return $output;
+ }
+}
+
+/**
+ * Implements hook_theme().
+ */
+function media_library_theme() {
+ return [
+ 'media__media_library' => [
+ 'base hook' => 'media',
+ ],
+ ];
+}
+
+/**
+ * Implements hook_views_post_render().
+ */
+function media_library_views_post_render(ViewExecutable $view, &$output, CachePluginBase $cache) {
+ if ($view->id() === 'media_library') {
+ $output['#attached']['library'][] = 'media_library/view';
+ }
+}
+
+/**
+ * Implements hook_preprocess_media().
+ */
+function media_library_preprocess_media(&$variables) {
+ if ($variables['view_mode'] === 'media_library') {
+ /** @var \Drupal\media\MediaInterface $media */
+ $media = $variables['media'];
+ $variables['#cache']['contexts'][] = 'user.permissions';
+ $rel = $media->access('edit') ? 'edit-form' : 'canonical';
+ $variables['url'] = $media->toUrl($rel, [
+ 'language' => $media->language(),
+ ]);
+ $variables['preview_attributes'] = new Attribute();
+ $variables['preview_attributes']->addClass('media-library-item__preview', 'js-click-to-select__trigger');
+ $variables['metadata_attributes'] = new Attribute();
+ $variables['metadata_attributes']->addClass('media-library-item__attributes');
+ $variables['status'] = $media->isPublished();
+ }
+}
+
+/**
+ * Alter the bulk form to add a more accessible label.
+ *
+ * @param array $form
+ * An associative array containing the structure of the form.
+ * @param \Drupal\Core\Form\FormStateInterface $form_state
+ * The current state of the form.
+ *
+ * @todo Remove in https://www.drupal.org/project/drupal/issues/2969660
+ */
+function media_library_form_views_form_media_library_page_alter(array &$form, FormStateInterface $form_state) {
+ if (isset($form['media_bulk_form']) && isset($form['output'])) {
+ $form['#attributes']['class'][] = 'media-library-page-form';
+ $form['header']['#attributes']['class'][] = 'media-library-page-form__header';
+ /** @var \Drupal\views\ViewExecutable $view */
+ $view = $form['output'][0]['#view'];
+ foreach (Element::getVisibleChildren($form['media_bulk_form']) as $key) {
+ if (isset($view->result[$key])) {
+ $media = $view->field['media_bulk_form']->getEntity($view->result[$key]);
+ $form['media_bulk_form'][$key]['#title'] = t('Select @label', [
+ '@label' => $media->label(),
+ ]);
+ }
+ }
+ }
+}
+
+/**
+ * Implements hook_local_tasks_alter().
+ *
+ * Removes tasks for the Media library if the view display no longer exists.
+ */
+function media_library_local_tasks_alter(&$local_tasks) {
+ /** @var \Symfony\Component\Routing\RouteCollection $route_collection */
+ $route_collection = \Drupal::service('router')->getRouteCollection();
+ foreach (['media_library.grid', 'media_library.table'] as $key) {
+ if (isset($local_tasks[$key]) && !$route_collection->get($local_tasks[$key]['route_name'])) {
+ unset($local_tasks[$key]);
+ }
+ }
+}
diff --git a/core/modules/media_library/templates/media--media-library.html.twig b/core/modules/media_library/templates/media--media-library.html.twig
new file mode 100644
index 0000000..a55024a
--- /dev/null
+++ b/core/modules/media_library/templates/media--media-library.html.twig
@@ -0,0 +1,50 @@
+{#
+/**
+ * @file
+ * Default theme implementation to present a media entity in the media library.
+ *
+ * Available variables:
+ * - media: The entity with limited access to object properties and methods.
+ * Only method names starting with "get", "has", or "is" and a few common
+ * methods such as "id", "label", and "bundle" are available. For example:
+ * - entity.getEntityTypeId() will return the entity type ID.
+ * - entity.hasField('field_example') returns TRUE if the entity includes
+ * field_example. (This does not indicate the presence of a value in this
+ * field.)
+ * Calling other methods, such as entity.delete(), will result in an exception.
+ * See \Drupal\Core\Entity\EntityInterface for a full list of methods.
+ * - name: Name of the media.
+ * - content: Media content.
+ * - title_prefix: Additional output populated by modules, intended to be
+ * displayed in front of the main title tag that appears in the template.
+ * - title_suffix: Additional output populated by modules, intended to be
+ * displayed after the main title tag that appears in the template.
+ * - view_mode: View mode; for example, "teaser" or "full".
+ * - attributes: HTML attributes for the containing element.
+ * - title_attributes: Same as attributes, except applied to the main title
+ * tag that appears in the template.
+ * - url: Direct URL of the media.
+ * - preview_attributes: HTML attributes for the preview wrapper.
+ * - metadata_attributes: HTML attributes for the expandable metadata area.
+ * - status: Whether or not the Media is published.
+ *
+ * @see template_preprocess_media()
+ *
+ * @ingroup themeable
+ */
+#}
+<article{{ attributes }}>
+ {% if content %}
+ <div{{ preview_attributes }}>
+ {{ content|without('name') }}
+ </div>
+ {% if not status %}
+ <div class="media-library-item__status">{{ "unpublished" | t }}</div>
+ {% endif %}
+ <div{{ metadata_attributes }}>
+ <div class="media-library-item__name">
+ <a href="{{ url }}" rel="bookmark">{{ name }}</a>
+ </div>
+ </div>
+ {% endif %}
+</article>
diff --git a/core/modules/media_library/tests/modules/media_library_test/config/install/core.entity_form_display.media.type_one.default.yml b/core/modules/media_library/tests/modules/media_library_test/config/install/core.entity_form_display.media.type_one.default.yml
new file mode 100644
index 0000000..212daf8
--- /dev/null
+++ b/core/modules/media_library/tests/modules/media_library_test/config/install/core.entity_form_display.media.type_one.default.yml
@@ -0,0 +1,43 @@
+langcode: en
+status: true
+dependencies:
+ config:
+ - field.field.media.type_one.field_media_test
+ - media.type.type_one
+id: media.type_one.default
+targetEntityType: media
+bundle: type_one
+mode: default
+content:
+ created:
+ type: datetime_timestamp
+ weight: 10
+ region: content
+ settings: { }
+ third_party_settings: { }
+ field_media_test:
+ settings:
+ size: 60
+ placeholder: ''
+ third_party_settings: { }
+ type: string_textfield
+ weight: 11
+ region: content
+ name:
+ type: string_textfield
+ weight: -5
+ region: content
+ settings:
+ size: 60
+ placeholder: ''
+ third_party_settings: { }
+ uid:
+ type: entity_reference_autocomplete
+ weight: 5
+ settings:
+ match_operator: CONTAINS
+ size: 60
+ placeholder: ''
+ region: content
+ third_party_settings: { }
+hidden: { }
diff --git a/core/modules/media_library/tests/modules/media_library_test/config/install/core.entity_form_display.media.type_two.default.yml b/core/modules/media_library/tests/modules/media_library_test/config/install/core.entity_form_display.media.type_two.default.yml
new file mode 100644
index 0000000..fabd13b
--- /dev/null
+++ b/core/modules/media_library/tests/modules/media_library_test/config/install/core.entity_form_display.media.type_two.default.yml
@@ -0,0 +1,43 @@
+langcode: en
+status: true
+dependencies:
+ config:
+ - field.field.media.type_two.field_media_test_1
+ - media.type.type_two
+id: media.type_two.default
+targetEntityType: media
+bundle: type_two
+mode: default
+content:
+ created:
+ type: datetime_timestamp
+ weight: 10
+ region: content
+ settings: { }
+ third_party_settings: { }
+ field_media_test_1:
+ settings:
+ size: 60
+ placeholder: ''
+ third_party_settings: { }
+ type: string_textfield
+ weight: 11
+ region: content
+ name:
+ type: string_textfield
+ weight: -5
+ region: content
+ settings:
+ size: 60
+ placeholder: ''
+ third_party_settings: { }
+ uid:
+ type: entity_reference_autocomplete
+ weight: 5
+ settings:
+ match_operator: CONTAINS
+ size: 60
+ placeholder: ''
+ region: content
+ third_party_settings: { }
+hidden: { }
diff --git a/core/modules/media_library/tests/modules/media_library_test/config/install/core.entity_view_display.media.type_one.default.yml b/core/modules/media_library/tests/modules/media_library_test/config/install/core.entity_view_display.media.type_one.default.yml
new file mode 100644
index 0000000..95670b3
--- /dev/null
+++ b/core/modules/media_library/tests/modules/media_library_test/config/install/core.entity_view_display.media.type_one.default.yml
@@ -0,0 +1,50 @@
+langcode: en
+status: true
+dependencies:
+ config:
+ - field.field.media.type_one.field_media_test
+ - image.style.thumbnail
+ - media.type.type_one
+ module:
+ - image
+ - user
+id: media.type_one.default
+targetEntityType: media
+bundle: type_one
+mode: default
+content:
+ created:
+ label: hidden
+ type: timestamp
+ weight: 0
+ region: content
+ settings:
+ date_format: medium
+ custom_date_format: ''
+ timezone: ''
+ third_party_settings: { }
+ field_media_test:
+ label: above
+ settings:
+ link_to_entity: true
+ third_party_settings: { }
+ type: string
+ weight: 6
+ region: content
+ thumbnail:
+ type: image
+ weight: 5
+ label: hidden
+ settings:
+ image_style: thumbnail
+ image_link: ''
+ region: content
+ third_party_settings: { }
+ uid:
+ label: hidden
+ type: author
+ weight: 0
+ region: content
+ settings: { }
+ third_party_settings: { }
+hidden: { }
diff --git a/core/modules/media_library/tests/modules/media_library_test/config/install/core.entity_view_display.media.type_two.default.yml b/core/modules/media_library/tests/modules/media_library_test/config/install/core.entity_view_display.media.type_two.default.yml
new file mode 100644
index 0000000..a884fee
--- /dev/null
+++ b/core/modules/media_library/tests/modules/media_library_test/config/install/core.entity_view_display.media.type_two.default.yml
@@ -0,0 +1,50 @@
+langcode: en
+status: true
+dependencies:
+ config:
+ - field.field.media.type_two.field_media_test_1
+ - image.style.thumbnail
+ - media.type.type_two
+ module:
+ - image
+ - user
+id: media.type_two.default
+targetEntityType: media
+bundle: type_two
+mode: default
+content:
+ created:
+ label: hidden
+ type: timestamp
+ weight: 0
+ region: content
+ settings:
+ date_format: medium
+ custom_date_format: ''
+ timezone: ''
+ third_party_settings: { }
+ field_media_test_1:
+ label: above
+ settings:
+ link_to_entity: false
+ third_party_settings: { }
+ type: string
+ weight: 6
+ region: content
+ thumbnail:
+ type: image
+ weight: 5
+ label: hidden
+ settings:
+ image_style: thumbnail
+ image_link: ''
+ region: content
+ third_party_settings: { }
+ uid:
+ label: hidden
+ type: author
+ weight: 0
+ region: content
+ settings: { }
+ third_party_settings: { }
+hidden: { }
diff --git a/core/modules/media_library/tests/modules/media_library_test/config/install/field.field.media.type_one.field_media_test.yml b/core/modules/media_library/tests/modules/media_library_test/config/install/field.field.media.type_one.field_media_test.yml
new file mode 100644
index 0000000..f19207c
--- /dev/null
+++ b/core/modules/media_library/tests/modules/media_library_test/config/install/field.field.media.type_one.field_media_test.yml
@@ -0,0 +1,18 @@
+langcode: en
+status: true
+dependencies:
+ config:
+ - field.storage.media.field_media_test
+ - media.type.type_one
+id: media.type_one.field_media_test
+field_name: field_media_test
+entity_type: media
+bundle: type_one
+label: field_media_test
+description: ''
+required: false
+translatable: true
+default_value: { }
+default_value_callback: ''
+settings: { }
+field_type: string
diff --git a/core/modules/media_library/tests/modules/media_library_test/config/install/field.field.media.type_two.field_media_test_1.yml b/core/modules/media_library/tests/modules/media_library_test/config/install/field.field.media.type_two.field_media_test_1.yml
new file mode 100644
index 0000000..5b093ca
--- /dev/null
+++ b/core/modules/media_library/tests/modules/media_library_test/config/install/field.field.media.type_two.field_media_test_1.yml
@@ -0,0 +1,18 @@
+langcode: en
+status: true
+dependencies:
+ config:
+ - field.storage.media.field_media_test_1
+ - media.type.type_two
+id: media.type_two.field_media_test_1
+field_name: field_media_test_1
+entity_type: media
+bundle: type_two
+label: field_media_test_1
+description: ''
+required: false
+translatable: true
+default_value: { }
+default_value_callback: ''
+settings: { }
+field_type: string
diff --git a/core/modules/media_library/tests/modules/media_library_test/config/install/field.storage.media.field_media_test.yml b/core/modules/media_library/tests/modules/media_library_test/config/install/field.storage.media.field_media_test.yml
new file mode 100644
index 0000000..40a7791
--- /dev/null
+++ b/core/modules/media_library/tests/modules/media_library_test/config/install/field.storage.media.field_media_test.yml
@@ -0,0 +1,20 @@
+langcode: en
+status: true
+dependencies:
+ module:
+ - media
+id: media.field_media_test
+field_name: field_media_test
+entity_type: media
+type: string
+settings:
+ max_length: 255
+ is_ascii: false
+ case_sensitive: false
+module: core
+locked: false
+cardinality: 1
+translatable: true
+indexes: { }
+persist_with_no_fields: false
+custom_storage: false
diff --git a/core/modules/media_library/tests/modules/media_library_test/config/install/field.storage.media.field_media_test_1.yml b/core/modules/media_library/tests/modules/media_library_test/config/install/field.storage.media.field_media_test_1.yml
new file mode 100644
index 0000000..73b1105
--- /dev/null
+++ b/core/modules/media_library/tests/modules/media_library_test/config/install/field.storage.media.field_media_test_1.yml
@@ -0,0 +1,20 @@
+langcode: en
+status: true
+dependencies:
+ module:
+ - media
+id: media.field_media_test_1
+field_name: field_media_test_1
+entity_type: media
+type: string
+settings:
+ max_length: 255
+ is_ascii: false
+ case_sensitive: false
+module: core
+locked: false
+cardinality: 1
+translatable: true
+indexes: { }
+persist_with_no_fields: false
+custom_storage: false
diff --git a/core/modules/media_library/tests/modules/media_library_test/config/install/media.type.type_one.yml b/core/modules/media_library/tests/modules/media_library_test/config/install/media.type.type_one.yml
new file mode 100644
index 0000000..1f72b8b
--- /dev/null
+++ b/core/modules/media_library/tests/modules/media_library_test/config/install/media.type.type_one.yml
@@ -0,0 +1,16 @@
+langcode: en
+status: true
+dependencies:
+ module:
+ - media
+ - media_test_source
+id: type_one
+label: 'Type One'
+description: ''
+source: test
+queue_thumbnail_downloads: false
+new_revision: false
+source_configuration:
+ source_field: field_media_test
+ test_config_value: 'This is default value.'
+field_map: { }
diff --git a/core/modules/media_library/tests/modules/media_library_test/config/install/media.type.type_two.yml b/core/modules/media_library/tests/modules/media_library_test/config/install/media.type.type_two.yml
new file mode 100644
index 0000000..13b549c
--- /dev/null
+++ b/core/modules/media_library/tests/modules/media_library_test/config/install/media.type.type_two.yml
@@ -0,0 +1,16 @@
+langcode: en
+status: true
+dependencies:
+ module:
+ - media
+ - media_test_source
+id: type_two
+label: 'Type Two'
+description: ''
+source: test
+queue_thumbnail_downloads: false
+new_revision: false
+source_configuration:
+ source_field: field_media_test_1
+ test_config_value: 'This is default value.'
+field_map: { }
diff --git a/core/modules/media_library/tests/modules/media_library_test/media_library_test.info.yml b/core/modules/media_library/tests/modules/media_library_test/media_library_test.info.yml
new file mode 100644
index 0000000..3ad1ae5
--- /dev/null
+++ b/core/modules/media_library/tests/modules/media_library_test/media_library_test.info.yml
@@ -0,0 +1,10 @@
+name: 'Media library test'
+type: module
+description: 'Test module for Media library.'
+package: Testing
+core: 8.x
+dependencies:
+ - drupal:media_library
+ - drupal:media_test_source
+ - drupal:menu_ui
+ - drupal:path
diff --git a/core/modules/media_library/tests/src/FunctionalJavascript/MediaLibraryTest.php b/core/modules/media_library/tests/src/FunctionalJavascript/MediaLibraryTest.php
new file mode 100644
index 0000000..f8604e6
--- /dev/null
+++ b/core/modules/media_library/tests/src/FunctionalJavascript/MediaLibraryTest.php
@@ -0,0 +1,102 @@
+<?php
+
+namespace Drupal\Tests\media_library\FunctionalJavascript;
+
+use Drupal\FunctionalJavascriptTests\JavascriptTestBase;
+use Drupal\media\Entity\Media;
+
+/**
+ * Contains Media library integration tests.
+ *
+ * @group media_library
+ */
+class MediaLibraryTest extends JavascriptTestBase {
+
+ /**
+ * {@inheritdoc}
+ */
+ protected static $modules = ['block', 'media_library_test'];
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function setUp() {
+ parent::setUp();
+
+ // Create a few example media items for use in selection.
+ $media = [
+ 'type_one' => [
+ 'media_1',
+ 'media_2',
+ ],
+ 'type_two' => [
+ 'media_3',
+ 'media_4',
+ ],
+ ];
+
+ foreach ($media as $type => $names) {
+ foreach ($names as $name) {
+ $entity = Media::create(['name' => $name, 'bundle' => $type]);
+ $source_field = $type === 'type_one' ? 'field_media_test' : 'field_media_test_1';
+ $entity->set($source_field, $this->randomString());
+ $entity->save();
+ }
+ }
+
+ // Create a user who can use the Media library.
+ $user = $this->drupalCreateUser([
+ 'access administration pages',
+ 'access media overview',
+ 'create media',
+ 'delete any media',
+ 'view media',
+ ]);
+ $this->drupalLogin($user);
+ $this->drupalPlaceBlock('local_tasks_block');
+ $this->drupalPlaceBlock('local_actions_block');
+ }
+
+ /**
+ * Tests that the Media library's administration page works as expected.
+ */
+ public function testAdministrationPage() {
+ $assert_session = $this->assertSession();
+
+ // Visit the administration page.
+ $this->drupalGet('admin/content/media');
+
+ // Verify that the "Add media" link is present.
+ $assert_session->linkExists('Add media');
+
+ // Verify that media from two separate types is present.
+ $assert_session->pageTextContains('media_1');
+ $assert_session->pageTextContains('media_3');
+
+ // Test that users can filter by type.
+ $this->getSession()->getPage()->selectFieldOption('Media type', 'Type One');
+ $this->getSession()->getPage()->pressButton('Apply Filters');
+ $assert_session->assertWaitOnAjaxRequest();
+ $assert_session->pageTextContains('media_2');
+ $assert_session->pageTextNotContains('media_4');
+ $this->getSession()->getPage()->selectFieldOption('Media type', 'Type Two');
+ $this->getSession()->getPage()->pressButton('Apply Filters');
+ $assert_session->assertWaitOnAjaxRequest();
+ $assert_session->pageTextNotContains('media_2');
+ $assert_session->pageTextContains('media_4');
+
+ // Test that selecting elements as a part of bulk operations works.
+ $this->getSession()->getPage()->selectFieldOption('Media type', '- Any -');
+ $this->getSession()->getPage()->pressButton('Apply Filters');
+ $assert_session->assertWaitOnAjaxRequest();
+ // This tests that anchor tags clicked inside the preview are suppressed.
+ $this->getSession()->executeScript('jQuery(".js-click-to-select__trigger a")[0].click()');
+ $this->submitForm([], 'Apply to selected items');
+ $assert_session->pageTextContains('media_1');
+ $assert_session->pageTextNotContains('media_2');
+ $this->submitForm([], 'Delete');
+ $assert_session->pageTextNotContains('media_1');
+ $assert_session->pageTextContains('media_2');
+ }
+
+}