From c5f2a3832ddf606be31bef819ea3f6fb42e12d90 Mon Sep 17 00:00:00 2001
From: Danillo Nunes <git@danillonunes.net>
Date: Sun, 14 Oct 2012 14:53:30 -0300
Subject: [PATCH] Issue #1790280: Module page redesign 2.0

---
 core/modules/system/system.admin.css  | 77 ++++++++++++++++++++++++++++++++++-
 core/modules/system/system.admin.inc  | 68 ++++++++++++++++++++-----------
 core/modules/system/system.module     | 12 ++++++
 core/modules/system/system.modules.js | 67 ++++++++++++++++++++++++++++++
 core/themes/seven/style.css           | 27 ++++++++++++
 5 files changed, 225 insertions(+), 26 deletions(-)
 create mode 100644 core/modules/system/system.modules.js

diff --git a/core/modules/system/system.admin.css b/core/modules/system/system.admin.css
index 957d3e0..d01fb8f 100644
--- a/core/modules/system/system.admin.css
+++ b/core/modules/system/system.admin.css
@@ -58,13 +58,84 @@ small .admin-link:after {
 /**
  * Modules page.
  */
+#system-modules th.description {
+  width: 70%;
+}
 #system-modules div.incompatible {
   font-weight: bold;
 }
+#system-modules td {
+  vertical-align: top;
+}
+#system-modules .expand .inner {
+  background: transparent url(../../misc/menu-collapsed.png) left .6em no-repeat;
+  margin-left: -12px;
+  padding-left: 12px;
+}
+#system-modules .expanded .expand .inner {
+  background: transparent url(../../misc/menu-expanded.png) left .6em no-repeat;
+}
+#system-modules label {
+  color: #1d1d1d;
+  font-size: 1.15em;
+}
+#system-modules td.description {
+  cursor: pointer;
+}
+#system-modules .description .inner {
+  color: #5c5c5b;
+  height: 20px;
+  line-height: 20px;
+  position: relative;
+}
+#system-modules .description .details,
+#system-modules .description .text {
+  display: block;
+  width: 100%;
+}
+#system-modules .description .text {
+  margin-right: -9999px;
+  overflow: hidden; /* truncates descriptions if too long */
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+#system-modules .expanded .description .inner {
+  height: auto;
+}
+#system-modules .expanded .description .text {
+  -webkit-hyphens: auto;
+  -moz-hyphens: auto;
+  hyphens: auto;
+  margin-right: auto;
+  overflow: visible;
+  white-space: normal;
+}
+
+@media screen and (max-width: 40em) {
+  #system-modules .description .text {
+    display: none;
+  }
+  #system-modules th.description {
+    width: 40%;
+  }
+}
+#system-modules .requirements {
+  padding: 5px 0;
+  max-width: 490px;
+}
+#system-modules .links {
+  overflow: hidden; /* prevents collapse */
+}
+#system-modules .checkbox {
+  margin: 0 5px;
+}
+#system-modules .checkbox .form-item {
+  margin-bottom: 0;
+}
 div.admin-requirements,
 div.admin-required {
   font-size: 0.9em;
-  color: #444;
+  color: #666;
 }
 span.admin-disabled {
   color: #800;
@@ -77,8 +148,10 @@ span.admin-missing {
 }
 a.module-link {
   display: block;
-  padding: 1px 0 1px 20px; /* LTR */
+  padding: 2px 20px;
   white-space: nowrap;
+  margin-top: 2px;
+  float: left; /* LTR */
 }
 a.module-link-help {
   background: url(../../misc/help.png) 0 50% no-repeat; /* LTR */
diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc
index c55289c..ad3ab57 100644
--- a/core/modules/system/system.admin.inc
+++ b/core/modules/system/system.admin.inc
@@ -853,7 +853,7 @@ function system_modules($form, $form_state = array()) {
           $extra['disabled'] = TRUE;
         }
         elseif ($files[$requires]->status) {
-          $extra['requires'][$requires] = t('@module (<span class="admin-enabled">enabled</span>)', array('@module' => $requires_name));
+          $extra['requires'][$requires] = t('@module', array('@module' => $requires_name));
         }
         else {
           $extra['requires'][$requires] = t('@module (<span class="admin-disabled">disabled</span>)', array('@module' => $requires_name));
@@ -900,7 +900,7 @@ function system_modules($form, $form_state = array()) {
       // Hidden modules are unset already.
       if (isset($visible_files[$required_by])) {
         if ($files[$required_by]->status == 1 && $module->status == 1) {
-          $extra['required_by'][] = t('@module (<span class="admin-enabled">enabled</span>)', array('@module' => $files[$required_by]->info['name']));
+          $extra['required_by'][] = t('@module', array('@module' => $files[$required_by]->info['name']));
           $extra['disabled'] = TRUE;
         }
         else {
@@ -920,10 +920,8 @@ function system_modules($form, $form_state = array()) {
       '#theme' => 'system_modules_fieldset',
       '#header' => array(
         array('data' => t('Enabled'), 'class' => array('checkbox')),
-        t('Name'),
-        array('data' => t('Version'), 'class' => array(RESPONSIVE_PRIORITY_MEDIUM)),
-        array('data' => t('Description'), 'class' => array(RESPONSIVE_PRIORITY_LOW)),
-        array('data' => t('Operations'), 'colspan' => 3),
+        array('data' => t('Name'), 'class' => array('name')),
+        array('data' => t('Description'), 'class' => array('description', RESPONSIVE_PRIORITY_LOW)),
       ),
       // Ensure that the "Core" package fieldset comes first.
       '#weight' => $package == 'Core' ? -10 : NULL,
@@ -933,6 +931,7 @@ function system_modules($form, $form_state = array()) {
   // Lastly, sort all fieldsets by title.
   uasort($form['modules'], 'element_sort_by_title');
 
+  $form['#attached']['library'][] = array('system', 'drupal.system.modules');
   $form['actions'] = array('#type' => 'actions');
   $form['actions']['submit'] = array(
     '#type' => 'submit',
@@ -2498,33 +2497,54 @@ function theme_system_modules_fieldset($variables) {
 
   // Individual table headers.
   $rows = array();
-  // Iterate through all the modules, which are
-  // children of this fieldset.
+  // Iterate through all the modules, which are children of this fieldset.
   foreach (element_children($form) as $key) {
-    // Stick it into $module for easier accessing.
+    // Stick the key into $module for easier access.
     $module = $form[$key];
+    // Create the row for the table.
     $row = array();
+    // Add the checkbox into the first cell.
     unset($module['enable']['#title']);
+    $module['#requires'] = array_filter($module['#requires']);
+    $module['#required_by'] = array_filter($module['#required_by']);
+
+    $requires = !empty($module['#requires']);
+    $required_by = !empty($module['#required_by']);
+    $version = !empty($module['version']['#markup']);
+
     $row[] = array('class' => array('checkbox'), 'data' => drupal_render($module['enable']));
-    $label = '<label';
-    if (isset($module['enable']['#id'])) {
-      $label .= ' for="' . $module['enable']['#id'] . '"';
-    }
-    $row[] = $label . '><strong>' . drupal_render($module['name']) . '</strong></label>';
-    $row[] = drupal_render($module['version']);
+
+    // Add the module label and expand/collapse functionalty.
+    $col2 = '<label for="' . $module['enable']['#id'] . '" class="module-name">' . drupal_render($module['name']) . '</label>';
+    $row[] = array('class' => array('module'), 'data' => $col2);
+
     // Add the description, along with any modules it requires.
-    $description = drupal_render($module['description']);
-    if ($module['#requires']) {
-      $description .= '<div class="admin-requirements">' . t('Requires: !module-list', array('!module-list' => implode(', ', $module['#requires']))) . '</div>';
-    }
-    if ($module['#required_by']) {
-      $description .= '<div class="admin-requirements">' . t('Required by: !module-list', array('!module-list' => implode(', ', $module['#required_by']))) . '</div>';
+    $description = '<span class="details"><span class="text">' . drupal_render($module['description']) . '</span></span>';
+    if ($version || $requires || $required_by) {
+      $description .= ' <div class="requirements">';
+      if ($version) {
+        $description .= '<div class="admin-requirements">' . t('Version: !module-version', array('!module-version' => drupal_render($module['version']))) . '</div>';
+      }
+      if ($requires) {
+        $description .= '<div class="admin-requirements">' . t('Requires: !module-list', array('!module-list' => implode(', ', $module['#requires']))) . '</div>';
+      }
+      if ($required_by) {
+        $description .= '<div class="admin-requirements">' . t('Required by: !module-list', array('!module-list' => implode(', ', $module['#required_by']))) . '</div>';
+      }
+      $description .= '</div>';
     }
-    $row[] = array('data' => $description, 'class' => array('description'));
-    // Display links (such as help or permissions) in their own columns.
+    $links = '';
     foreach (array('help', 'permissions', 'configure') as $key) {
-      $row[] = array('data' => drupal_render($module['links'][$key]), 'class' => array($key));
+      $links .= drupal_render($module['links'][$key]);
     }
+    if ($links) {
+      $description .= '  <div class="links">';
+      $description .= $links;
+      $description .= '</div>';
+    }
+    $col4 = '<div class="inner" tabindex="0"><span class="module-description-prefix element-invisible" role="button">Show description</span> ' . $description . '</div>';
+    $row[] = array('class' => array('description', 'expand'), 'data' => $col4);
+
     $rows[] = $row;
   }
 
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 255c669..2bc2bef 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -1935,6 +1935,18 @@ function system_library_info() {
       array('system', 'jquery.once'),
     ),
   );
+  $libraries['drupal.system.modules'] = array(
+    'title' => 'System cron',
+    'version' => VERSION,
+    'js' => array(
+      drupal_get_path('module', 'system') . '/system.modules.js' => array(),
+    ),
+    'dependencies' => array(
+      array('system', 'jquery'),
+      array('system', 'drupal'),
+      array('system', 'jquery.once'),
+    ),
+  );
 
   return $libraries;
 }
diff --git a/core/modules/system/system.modules.js b/core/modules/system/system.modules.js
new file mode 100644
index 0000000..7ae499c
--- /dev/null
+++ b/core/modules/system/system.modules.js
@@ -0,0 +1,67 @@
+(function ($, Drupal) {
+
+"use strict";
+
+$.extend(Drupal.settings, {
+  hideModules: {
+    method: 'toggle',
+    duration: 0
+  }
+});
+
+/**
+ * Show/hide the requirements information on modules page.
+ */
+Drupal.behaviors.hideModuleInformation = {
+  attach: function (context, settings) {
+    var $table = $('#system-modules').once('expand-modules');
+    var effect = settings.hideModules;
+    if ($table.length) {
+      var $tbodies = $table.find('tbody');
+
+      // Fancy animating.
+      $tbodies.on('click keydown', '.description', function (e) {
+        if (e.keyCode && e.keyCode !== 13) {
+          return;
+        }
+        e.preventDefault();
+        var $tr = $(this).closest('tr');
+        var $toggleElements = $tr.find('.requirements, .links');
+
+        $toggleElements[effect.method](effect.duration)
+          .promise().done(function() {
+            $tr.toggleClass('expanded');
+          });
+
+        // Change screen reader text.
+        $tr.find('.module-description-prefix').text(function () {
+          if ($tr.hasClass('expanded')) {
+            return Drupal.t('Hide description');
+          }
+          else {
+            return Drupal.t('Show description');
+          }
+        });
+      });
+      // Makes the whole cell a click target.
+      $tbodies.on('click', 'td.checkbox', function (e) {
+        e.stopPropagation();
+        var input = $(this).find('input').get(0);
+        if (!input.readOnly && !input.disabled) {
+          input.checked = !input.checked;
+        }
+      });
+      // Catch the event on the checkbox to avoid triggering previous handler.
+      $tbodies.on('click', 'input', function (e) {
+        e.stopPropagation();
+      });
+      // Don't close the row when clicking a link in the description.
+      $tbodies.on('click', '.description a', function (e) {
+        e.stopPropagation();
+      });
+    }
+    $table.find('.requirements, .links').hide();
+  }
+};
+
+}(jQuery, Drupal));
diff --git a/core/themes/seven/style.css b/core/themes/seven/style.css
index 7b8ae1b..5f0a239 100644
--- a/core/themes/seven/style.css
+++ b/core/themes/seven/style.css
@@ -1018,6 +1018,33 @@ div.add-or-remove-shortcuts {
   margin-bottom: 0;
 }
 
+/* Modules page */
+#system-modules fieldset {
+  border: 0;
+  border-top: 1px solid #ccc;
+}
+#system-modules .fieldset-wrapper {
+  padding: 0;
+}
+#system-modules table {
+  border: 0;
+}
+#system-modules tr.even,
+#system-modules tr.odd {
+  background: #f3f4ee;
+  border: 0;
+  border-bottom: 10px solid #fff;
+}
+#system-modules tr td:last-child {
+  border: 0;
+}
+#system-modules table th {
+  border: 0;
+  border-bottom: 10px solid #fff;
+}
+#system-modules .sticky-header th {
+  border: 0;
+}
 /* Recent content block */
 #block-node-recent table,
 #block-node-recent tr {
-- 
1.7.12.3

