From e8918a45ab23f5153a48df067cd66f582d6824be Mon Sep 17 00:00:00 2001
From: wulff <wulff@ratatosk.net>
Date: Fri, 1 Apr 2011 23:17:31 +0200
Subject: [PATCH] Issue #1095806 by wulff: Add sorting options to overall project list

---
 l10n_community/pages.inc       |  125 ++++++++++++++++++++++++++++++++++++----
 l10n_server/l10n_server.module |   25 ++++----
 2 files changed, 125 insertions(+), 25 deletions(-)

diff --git a/l10n_community/pages.inc b/l10n_community/pages.inc
index dc9f9fb..d8275db 100644
--- a/l10n_community/pages.inc
+++ b/l10n_community/pages.inc
@@ -98,7 +98,7 @@ function l10n_community_explore_projects() {
 
   $pager_setting = variable_get('l10n_community_project_per_page', 10);
 
-  $options = array('pager' => $pager_setting);
+  $options = array();
   if (isset($_GET['initial'])) {
     $options['initial'] = strtolower($_GET['initial']);
   }
@@ -118,28 +118,129 @@ function l10n_community_explore_projects() {
     $output .= drupal_get_form('l10n_community_explore_projects_jump_form');
   }
 
-  $pager = theme('pager', NULL, $pager_setting, 0);
+  $rows = array();
+  foreach ($projects as $project) {
+    $sum = @$string_counts[$project->pid]['count'] * $language_count;
+    $translated = (int) @$string_counts[$project->pid]['translations'];
+    $untranslated = $sum - $translated;
+    $suggestions = (int) @$string_counts[$project->pid]['suggestions'];
+
+    $bar = '';
+    if ($sum > 0) {
+      // Compute numbers, percentages and provide alternate text titles.
+      $done_percent = round($translated / $sum * 100, 2);
+      $status = array(
+        'translated'     => array((int) $translated, $done_percent, t('!percent translated')),
+        'untranslated'   => array($sum - $translated, 100 - $done_percent, t('!percent untranslated')),
+        // suggestions are not in the bar as they overlap with both translated and
+        // untranslated strings, so we cannot display them here.
+      );
 
-  $output .= _l10n_community_alphabetic_pager();
-  $output .= $pager;
+      // Visual summary with a progress bar.
+      $bar = '<div class="l10n-community-progress">';
+      foreach ($status as $key => $values) {
+        if ($values[1] > 0) {
+          $bar .= '<div class="l10n-community-progress-'. $key .'" style="width:'. $values[1] .'%;" title="'. strtr($values[2], array('!percent' => $values[1] .'%')) .'"></div>';
+        }
+      }
+      $bar .= '</div>';
+    }
 
-  $table = array();
-  foreach ($projects as $project) {
-    $table[] = array_merge(
+    $row = array(
+      array(
+        'data' => $project->weight,
+        'sortdata' => $project->weight,
+      ),
       array(
-        array('data' => l($project->title, 'translate/projects/'. $project->uri), 'class' => 'rowhead'),
+        'data' => l($project->title, 'translate/projects/'. $project->uri),
+        'sortdata' => $project->title,
+        'class' => 'rowhead',
+      ),
+      array(
+        'data' => $project->uri,
+        'sortdata' => $project->uri,
+        'class' => 'rowhead',
+      ),
+      array(
+        'data' => $bar,
+        'sortdata' => $done_percent,
+      ),
+      array(
+        'data' => $untranslated,
+        'sortdata' => $untranslated,
+      ),
+      array(
+        'data' => $suggestions,
+        'sortdata' => $suggestions,
       ),
-      // Multiply summary count by languages handled, so we get an
-      // accurate picture of completeness.
-      theme('l10n_community_progress_columns', (@$string_counts[$project->pid]['count'] * $language_count), @$string_counts[$project->pid]['translations'], @$string_counts[$project->pid]['suggestions'])
     );
+
+    $rows[] = $row;
   }
-  $output .= theme('table', theme('l10n_community_progress_headers', t('Project')), $table, array('class' => 'l10n-community-overview'));
+
+  usort($rows, 'l10n_server_sort_by_column_project');
+  $rows = _l10n_community_page_rows($rows, $pager_setting);
+
+  $pager = theme('pager', NULL, $pager_setting, 0);
+
+  $output .= _l10n_community_alphabetic_pager();
+  $output .= $pager;
+
+  $header = array(
+    array('data' => '#', 'field' => 'weight', 'sort' => 'desc'),
+    array('data' => t('Project'), 'field' => 'title', 'class' => 'rowhead'),
+    array('data' => t('Project name'), 'field' => 'uri', 'class' => 'rowhead'), // FIXME: use a different class name for this
+    array('data' => t('Progress'), 'field' => 'progress'),
+    array('data' => t('Untranslated'), 'field' => 'untranslated'),
+    array('data' => t('Suggestions'), 'field' => 'suggestions'),
+  );
+
+  $output .= theme('table', $header, $rows, array('class' => 'l10n-community-overview'));
+
   $output .= $pager;
   return $output .'<div class="clear-block"></div>';
 }
 
 /**
+ * Order listing table by column for project overview columns.
+ */
+function l10n_server_sort_by_column_project($a, $b) {
+  $sortkeys = array(
+    '#' => 0,
+    t('Project') => 1,
+    t('Project name') => 2,
+    t('Progress') => 3,
+    t('Untranslated') => 4,
+    t('Suggestions') => 5,
+  );
+
+  // sort on the first column if no column is given
+  $sortkey = isset($_GET['order']) ? $sortkeys[$_GET['order']] : 0;
+
+  if (@$a[$sortkey]['sortdata'] == @$b[$sortkey]['sortdata']) {
+    return 0;
+  }
+  return ((@$a[$sortkey]['sortdata'] < @$b[$sortkey]['sortdata']) ? -1 : 1) * ($_GET['sort'] == 'asc' ? 1 : -1);
+}
+
+/**
+ * Slice an array of rows according to the current pager settings.
+ */
+function _l10n_community_page_rows($rows, $items_per_page) {
+  global $pager_page_array, $pager_total, $pager_total_items;
+
+  $page = isset($_GET['page']) ? $_GET['page'] : '';
+  $pager_page_array = explode(',', $page);
+
+  $pager_total_items[0] = count($rows);
+  $pager_total[0] = ceil(count($rows) / $items_per_page);
+
+  $offset = !empty($pager_page_array[0]) ? $pager_page_array[0] * $items_per_page : 0;
+
+  return $rows = array_slice($rows, $offset, $items_per_page);
+}
+
+/**
  * Provide a form to jump to a specific project from the project listing.
  */
 function l10n_community_explore_projects_jump_form() {
diff --git a/l10n_server/l10n_server.module b/l10n_server/l10n_server.module
index bd92915..678d1f7 100644
--- a/l10n_server/l10n_server.module
+++ b/l10n_server/l10n_server.module
@@ -489,20 +489,19 @@ function l10n_server_get_projects($options = array()) {
   // Consider returning all projects or just published ones.
   $where = (empty($options['all']) ? 'WHERE status = 1 ' : '');
 
-  if (isset($options['pager'])) {
-    $arguments = array();
-
-    if (isset($options['initial'])) {
-      $initials = l10n_server_get_project_initials();
-      if (isset($initials[$options['initial']])) {
-        if (!empty($where)) {
-          $where .= 'AND ';
-        }
-        $where .= 'SUBSTR(title, 1, 1) IN ('. db_placeholders($initials[$options['initial']]['values'], 'varchar') .') ';
-        $arguments = $initials[$options['initial']]['values'];
+  $arguments = array();
+  if (isset($options['initial'])) {
+    $initials = l10n_server_get_project_initials();
+    if (isset($initials[$options['initial']])) {
+      if (!empty($where)) {
+        $where .= 'AND ';
       }
-   }
+      $where .= 'SUBSTR(title, 1, 1) IN ('. db_placeholders($initials[$options['initial']]['values'], 'varchar') .') ';
+      $arguments = $initials[$options['initial']]['values'];
+    }
+  }
 
+  if (isset($options['pager'])) {
     // If a pager view was asked for, collect data independently.
     $results = pager_query('SELECT * FROM {l10n_server_project} '. $where .'ORDER BY title', $options['pager'], 0, NULL, $arguments);
     $pager_results = array();
@@ -529,7 +528,7 @@ function l10n_server_get_projects($options = array()) {
     }
     else {
       // A list of *all* projects was asked for.
-      $results = db_query('SELECT * FROM {l10n_server_project} '. $where .'ORDER BY uri');
+      $results = db_query('SELECT * FROM {l10n_server_project} '. $where .'ORDER BY uri', $arguments);
       while ($project = db_fetch_object($results)) {
         $projects[$project->uri] = $project;
       }
-- 
1.7.0.3

