Skip to content
Snippets Groups Projects
Commit 3c9e7a80 authored by Brian Canini's avatar Brian Canini
Browse files

Merge branch 'module_filter' into module-updates-rc

parents 45464254 013e51bf
No related branches found
No related tags found
No related merge requests found
Showing
with 235 additions and 49 deletions
......@@ -6479,29 +6479,26 @@
},
{
"name": "drupal/module_filter",
"version": "3.1.0",
"version": "3.2.0",
"source": {
"type": "git",
"url": "https://git.drupalcode.org/project/module_filter.git",
"reference": "8.x-3.1"
"reference": "8.x-3.2"
},
"dist": {
"type": "zip",
"url": "https://ftp.drupal.org/files/projects/module_filter-8.x-3.1.zip",
"reference": "8.x-3.1",
"shasum": "39d627ce60280ae54bcf9beae217b85cce1969e4"
"url": "https://ftp.drupal.org/files/projects/module_filter-8.x-3.2.zip",
"reference": "8.x-3.2",
"shasum": "b5c1a5141da392340232a1ad0934b921b862e1f4"
},
"require": {
"drupal/core": "~8.0"
"drupal/core": "^8 || ^9"
},
"type": "drupal-module",
"extra": {
"branch-alias": {
"dev-3.x": "3.x-dev"
},
"drupal": {
"version": "8.x-3.1",
"datestamp": "1507650844",
"version": "8.x-3.2",
"datestamp": "1614918371",
"security-coverage": {
"status": "covered",
"message": "Covered by Drupal's security advisory policy"
......@@ -6510,26 +6507,23 @@
},
"notification-url": "https://packages.drupal.org/8/downloads",
"license": [
"GPL-2.0-or-later"
"GPL-2.0+"
],
"authors": [
{
"name": "greenSkin",
"homepage": "https://www.drupal.org/user/173855"
},
{
"name": "realityloop",
"homepage": "https://www.drupal.org/user/139189"
"name": "andrey.troeglazov",
"homepage": "https://www.drupal.org/user/3145389"
},
{
"name": "shumushin",
"homepage": "https://www.drupal.org/user/22093"
"name": "greenSkin",
"homepage": "https://www.drupal.org/user/173855"
}
],
"description": "Filter the modules list.",
"homepage": "https://www.drupal.org/project/module_filter",
"homepage": "http://drupal.org/project/module_filter",
"support": {
"source": "http://cgit.drupalcode.org/module_filter"
"source": "https://git.drupalcode.org/project/module_filter",
"issues": "https://www.drupal.org/project/issues/module_filter"
}
},
{
......
CONTENTS OF THIS FILE
---------------------
* Introduction
* Installation
* Configuration
* Tabs
* Filter operators
* Maintainers
INTRODUCTION
------------
This module provides a method for filtering modules on the modules page as well
as for filtering projects on the update status report.
The supplied filter is simpler than using your browsers find a feature which
searches the entire page. The provided filter will filter modules/projects that
do not meet your input.
Along with the filter textfield there are additional
checkboxes that help to narrow the search more. The modules page contains 3
checkboxes: Enabled, Disabled, and Unavailable. While the first two
are self-explanatory, the latter two can take an explanation. The Required
checkbox affects visibility of modules that are enabled and have other
module(s) that require it also enabled. The Unavailable checkbox affects
visibility of modules that are disabled and depend on module(s) that are
missing.
The update status report filter also contains four checkboxes: Up-to-Date,
Update available, Security update, and Unknown. These directly affect the
visibility of each project; whether it is up-to-date, there is an update
available, a security update is available, or the status is unknown.
Installation
------------
To install this module, do the following:
1. Extract the tarball that you downloaded from Drupal.org.
2. Upload the entire directory and all its contents to your modules directory.
Configuration
-------------
To enable and configure this module do the following:
1. Go to Admin -> Modules, and enable Module Filter.
2. Go to Admin -> Configuration -> User interface -> Module filter, and make
any necessary configuration changes.
Tabs
----
By default Module Filter alters the modules page into tabs (Can be disabled on
configuration page). In the tabs view, each package is converted to a vertical
tab rather than a fieldset which greatly increases the ability to browse them.
There are several benefits to using the tabs view over the standard view for
the modules page. I've listed the key benefits below as well as additional
information that pertains to each.
1. The increased ease of browsing between packages.
2. Allows all modules to be listed alphabetically outside of their package,
making it all the easier to find the module by name rather than package it
happens to be in.
3. The operations for a module are moved within the description column giving
the description more "elbow room".
4. Filtering is restricted to within the active tab or globally when no tab is
selected. By default no tab is selected which will list all modules. When a
tab is active and you want to get back to the 'all' state click on the
active tab to deselect it.
5. The number of enabled modules per tab is shown on the active tab. (Can be
disabled on configuration page)
6. Nice visual aids become available showing what modules are to be
enabled/disabled and the number of matching modules in each tab when
filtering. (Can be disabled on configuration page)
7. The save configuration button becomes more accessible, either staying at
the bottom of the window when the tabs exceed past the bottom and at the
top when scrolling past the tabs. (Can be disabled on configuration page)
8. When filtering, tabs that do not contain matches can be hidden. (Can be
enabled on configuration page)
9. Tab states are remembered like individual pages allowing you to move
forward and backward within your selections via your browsers
forward/backward buttons.
10. When viewing all modules (no active tab) and mousing over modules it's tab
becomes highlighted to signify which tab it belongs to.
Filter operators
----------------
The modules page's filter has three filter operators available. Filter
operators allow alternative filtering techniques. A filter operator is applied
by typing within the filter textfield 'operator:' (where operator is the
operator type) followed immediately with the string to pass to the operator
function (e.g. 'requires:block'). The available operators are:
description:
Filter based on a module's description.
requiredBy:
Filter based on what a module is required by.
requires:
Filter based on what a module requires.
Multiple filters (or queries) can be applied by space delimiting. For example,
the filter string 'description:ctools views' would filter down to modules with
"ctools" in the description and "views" within the module's name. To pass a
space within a single query wrap it within double quotes (e.g. 'requires:"chaos
tools"' or '"bulk export"').
Maintainers
------------------
- Green Skin (greenSkin) - https://www.drupal.org/u/greenskin
- Andrey Troeglazov (andrey.troeglazov) - https://www.drupal.org/u/andreytroeglazov
{
"name": "drupal/module_filter",
"description": "Filter the modules list.",
"type": "drupal-module",
"license": "GPL-2.0+",
"homepage": "http://drupal.org/project/module_filter",
"support": {
"issues": "https://www.drupal.org/project/issues/module_filter",
"source": "https://git.drupalcode.org/project/module_filter"
}
}
module_filter.settings:
type: config_object
label: 'Module filter settings'
mapping:
tabs:
type: boolean
label: 'Boolean indicating whether the Extend page should be enhanced with tabs'
......@@ -5,7 +5,7 @@
position: relative;
overflow: hidden;
margin: 10px 0;
background: #E6E5E1;
background: #e6e5e1;
border: 1px solid #bdbdbd;
border-radius: 4px;
}
......@@ -33,7 +33,7 @@
border-bottom: 1px solid #ccc;
}
.modules-tabs__menu-item.suggest {
background: #F9F9F9;
background: #f9f9f9;
}
.modules-tabs__menu-item.disabled {
background: #ccc;
......@@ -47,7 +47,7 @@
}
.modules-tabs__menu-item a:hover,
.modules-tabs__menu-item a:focus {
background: #D5D5D5;
background: #d5d5d5;
text-decoration: none;
outline: 0;
}
......@@ -55,11 +55,11 @@
.modules-tabs__menu-item.is-selected a:hover,
.modules-tabs__menu-item.is-selected a:focus,
.modules-tabs__menu-item.is-selected a:active {
background-color: #FCFCFA;
background-color: #fcfcfa;
margin-right: -1px;
}
.modules-tabs__menu-item.disabled a,
.modules-tabs__menu-item.disabled span{
.modules-tabs__menu-item.disabled span {
color: #999;
}
.modules-tabs__menu-item.disabled a {
......@@ -93,13 +93,13 @@
.modules-tabs__pane {
margin: 0 0 0 240px; /* LTR */
padding: 10px 15px;
background: #FCFCFA;
border-left: 1px solid #A6A5A1; /* LTR */
background: #fcfcfa;
border-left: 1px solid #a6a5a1; /* LTR */
}
[dir="rtl"] .modules-tabs__pane {
margin: 0 240px 0 0;
border-left: none;
border-right: 1px solid #A6A5A1;
border-right: 1px solid #a6a5a1;
}
.modules-tabs__pane:after {
content: '';
......@@ -131,4 +131,3 @@
overflow: hidden;
text-overflow: ellipsis;
}
......@@ -45,7 +45,7 @@
ModuleFilter.modulesWrapper = $('.modules-wrapper', ModuleFilter.wrapper);
ModuleFilter.input.winnow(ModuleFilter.wrapperId + ' ' + ModuleFilter.selector, {
textSelector: 'td.module .module-name',
textSelector: 'td.module .module-name, .module-machine-name',
emptyMessage: Drupal.t('No results'),
clearLabel: Drupal.t('clear'),
wrapper: ModuleFilter.modulesWrapper,
......
......@@ -335,7 +335,8 @@
ModuleFilter.modulesWrapper.children('details').each(function() {
var $details = $(this);
var packageName = $details.children('summary').text();
var packageId = packageName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
var packageId = $details.children('summary').attr('aria-controls');
packageId = packageId.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
if (tabs[packageId] == undefined) {
tabs[packageId] = new Tab(packageName, packageId);
......
name: Module filter
name: Module Filter
type: module
description: Filter the modules list.
package: Administration
# core: 8.x
core: 8.x
core_version_requirement: ^8 || ^9
configure: module_filter.settings
# Information added by Drupal.org packaging script on 2017-10-10
version: '8.x-3.1'
core: '8.x'
dependencies:
- drupal:system (>= 8.3)
# Information added by Drupal.org packaging script on 2021-03-05
version: '8.x-3.2'
project: 'module_filter'
datestamp: 1507650850
datestamp: 1614918374
......@@ -10,7 +10,7 @@
*/
function module_filter_install() {
$state = \Drupal::state();
$state->set('module_filter.recent', ['module_filter' => REQUEST_TIME]);
$state->set('module_filter.recent', ['module_filter' => \Drupal::time()->getRequestTime()]);
}
/**
......
......@@ -7,6 +7,27 @@
use Drupal\Core\Render\Element;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Routing\RouteMatchInterface;
/**
* Implements hook_help().
*/
function module_filter_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
case 'help.page.module_filter':
$output = '';
$output .= '<p>';
$output .= t('The modules list page can become quite big when dealing with a fairly large site or even just a dev site meant for testing new and various modules being considered.');
$output .= '</p>';
$output .= '<p>';
$output .= t('What this module aims to accomplish is the ability to quickly find the module you are looking for without having to rely on the browsers search feature which more times than not shows you the module name in the -Required by- or -Depends on- sections of the various modules or even some other location on the page like a menu item.');
$output .= '</p>';
$output .= '<p>';
$output .= t('See the <a href=":project_page">project page on Drupal.org</a> for more details.', [':project_page' => 'https://www.drupal.org/project/module_filter']);
return $output;
}
}
/**
* Implements hook_form_FORM_ID_alter().
......@@ -53,7 +74,7 @@ function module_filter_form_system_modules_alter(&$form, FormStateInterface $for
// Remove recent items older than a week.
$recent = array_filter($recent, function ($val) {
return !($val < REQUEST_TIME - 60 * 60 * 24 * 7);
return !($val < \Drupal::time()->getRequestTime() - 60 * 60 * 24 * 7);
});
$state->set('module_filter.recent', $recent);
......@@ -68,7 +89,7 @@ function module_filter_form_system_modules_alter(&$form, FormStateInterface $for
}
}
$modules = system_rebuild_module_data();
$modules = \Drupal::service('extension.list.module')->reset()->getList();
foreach ($modules as $name => $module) {
if ($name == 'module_filter') {
......@@ -102,7 +123,7 @@ function module_filter_form_system_modules_confirm_form_alter(&$form, FormStateI
/**
* Implements hook_form_FORM_ID_alter().
*/
function module_filter_form_system_modules_uninstall_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
function module_filter_form_system_modules_uninstall_alter(&$form, FormStateInterface $form_state, $form_id) {
$key = array_search('system/drupal.system.modules', $form['#attached']['library']);
if ($key !== FALSE) {
unset($form['#attached']['library'][$key]);
......@@ -118,7 +139,7 @@ function module_filter_form_system_modules_uninstall_alter(&$form, \Drupal\Core\
/**
* Implements hook_form_FORM_ID_alter().
*/
function module_filter_form_user_admin_permissions_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
function module_filter_form_user_admin_permissions_alter(&$form, FormStateInterface $form_state, $form_id) {
$form['filters'] = [
'#type' => 'container',
'#attributes' => [
......@@ -157,6 +178,18 @@ function module_filter_theme_registry_alter(&$theme_registry) {
* Implements hook_preprocess_HOOK().
*/
function module_filter_preprocess_system_modules_details(&$variables) {
$display_path = \Drupal::config('module_filter.settings')->get('path');
if ($display_path) {
foreach ($variables['modules'] as &$module) {
// Get the module id from parents.
// Because core does not provide it in template_preprocess_system_modules_details.
$id = $module['name']['#parents'][1];
$path = drupal_get_path('module', $id);
if (!empty($path)) {
$module['path'] = $path;
}
}
}
}
/**
......@@ -170,7 +203,7 @@ function module_filter_system_modules_recent_enabled_submit($form, FormStateInte
// the version of Drupal and building the $modules array accordingly.
// @see https://www.drupal.org/node/2851653
$modules = [];
if (version_compare(\DRUPAL::VERSION, '8.3.0', '<')) {
if (version_compare(\Drupal::VERSION, '8.3.0', '<')) {
foreach ($form_state->getValue('modules') as $package) {
$modules += $package;
}
......@@ -182,7 +215,7 @@ function module_filter_system_modules_recent_enabled_submit($form, FormStateInte
foreach (Element::children($form['modules']) as $package) {
foreach ($modules as $module => $details) {
if (isset($form['modules'][$package][$module]) && $form['modules'][$package][$module]['enable']['#default_value'] != $details['enable']) {
$recent[$module] = REQUEST_TIME;
$recent[$module] = \Drupal::time()->getRequestTime();
}
}
}
......
......@@ -37,6 +37,13 @@ public function buildForm(array $form, FormStateInterface $form_state) {
'#default_value' => $config->get('tabs'),
];
$form['modules']['path'] = [
'#type' => 'checkbox',
'#title' => $this->t('Show module path in modules list'),
'#description' => $this->t('Defines if the relative path of each module will be display in its row.'),
'#default_value' => $config->get('path'),
];
return $form;
}
......@@ -47,6 +54,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
$values = $form_state->getValues();
$this->config('module_filter.settings')
->set('tabs', $values['tabs'])
->set('path', $values['path'])
->save();
parent::submitForm($form, $form_state);
......
......@@ -48,7 +48,7 @@
<div class="details-wrapper">
<div class="details-description">
<div class="requirements">
<div class="admin-requirements">{{ 'Machine name: <span dir="ltr" class="table-filter-text-source">@machine-name</span>'|t({'@machine-name': module.machine_name }) }}</div>
<div class="admin-requirements">{{ 'Machine name: <span dir="ltr" class="module-machine-name table-filter-text-source">@machine-name</span>'|t({'@machine-name': module.machine_name }) }}</div>
{% if module.version %}
<div class="admin-requirements">{{ 'Version: @module-version'|t({'@module-version': module.version }) }}</div>
{% endif %}
......@@ -58,6 +58,9 @@
{% if module.required_by %}
<div class="admin-requirements required-by">{{ 'Required by: @module-list'|t({'@module-list': module.required_by }) }}</div>
{% endif %}
{% if module.path %}
<div class="admin-requirements module-path">{{ 'Module path: @module-list'|t({'@module-list': module.path }) }}</div>
{% endif %}
</div>
{% if module.links %}
<div class="links">
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment