Index: project.inc
===================================================================
--- project.inc	(revision 570)
+++ project.inc	(working copy)
@@ -337,18 +337,6 @@
     // Build a nested array of sections of links to display on project_project node pages.
     $all_links = array();
 
-    // Resources section
-    $all_links['resources'] = array(
-      'name' => t('Resources'),
-      'weight' => 4,
-    );
-    foreach (array('homepage' => t('Home page'), 'documentation' => t('Read documentation'), 'license' => t('Read license'), 'changelog' => t('Read complete log of changes'), 'demo' => t('Try out a demonstration'), 'screenshots' => t('Look at screenshots')) as $uri => $name) {
-      if (!empty($node->project[$uri])) {
-        $all_links['resources']['links'][$uri] = l($name, $node->project[$uri]);
-      }
-    }
-
-
     // Flags that indicate what kind of access to project issues to allow.
     $has_issues = module_exists('project_issue') && !empty($node->project_issue['issues']);
     $view_issues = $has_issues && (user_access('access project issues') || user_access('access own project issues') || user_access('administer projects'));
@@ -378,29 +366,6 @@
     }
     $all_links['support']['links'] = $links;
 
-
-    // Developer section
-    $all_links['development'] = array(
-      'name' => t('Development'),
-      'weight' => 8,
-    );
-    $links = array();
-    if ($view_issues) {
-      $links['pending_patches'] = l(t('View pending patches'), 'project/issues/'. $node->project['uri'], array('query' => 'states=8,13', 'absolute' => TRUE, 'html' => TRUE));
-      $links['available_tasks'] = l(t('View available tasks'), 'project/issues/'. $node->project['uri'], array('query' => 'categories=task'));
-      $links['pending_issues'] = l(t('View all pending issues'), 'project/issues/'. $node->project['uri']);
-    }
-
-    if ($node->project['cvs']) {
-      $links['browse_repository'] = l(t('Browse the CVS repository'), $node->project['cvs']);
-    }
-
-    if (project_use_cvs($node)) {
-      $links['view_cvs_messages'] = l(t('View CVS messages'), 'project/cvs/'. $node->nid);
-      $links['developers'] = l(t('Developers'), 'project/developers/'. $node->nid);
-    }
-    $all_links['development']['links'] = $links;
-
     // Allow other modules to add sections of links and/or links to the sections defined above.
     project_page_link_alter($node, $all_links);
 
Index: project.module
===================================================================
--- project.module	(revision 570)
+++ project.module	(working copy)
@@ -71,6 +71,14 @@
       'info' => t('Project navigation (text field)'),
       'cache' => BLOCK_CACHE_PER_ROLE,
     );
+    $blocks[3] = array(
+      'info' => t('Project links'),
+      'cache' => BLOCK_CACHE_PER_ROLE,
+    );
+    $blocks[4] = array(
+      'info' => t('Get involved'),
+      'cache' => BLOCK_CACHE_PER_ROLE,
+    );
     return $blocks;
   }
   else if ($op == 'view') {
@@ -96,6 +104,20 @@
           'content' => drupal_get_form('project_quick_navigate_title_form'),
         );
         break;
+        
+      case 3:
+        $block = array(
+          'subject' => t('Links'),
+          'content' => project_links_block_output(),
+        );
+        break;
+        
+      case 4:
+        $block = array(
+          'subject' => t('Get involved'),
+          'content' => project_get_involved_block_output(),
+        );
+        break;
     }
     return $block;
   }
@@ -114,6 +136,63 @@
   }
 }
 
+/**
+ * Function that outputs the content of a project "Links" block.
+ */ 
+function project_links_block_output() {
+  if (arg(0) != 'node' && !is_numeric(arg(1))) {
+    return;
+  }
+  $node = node_load(arg(1));
+  $links = array();
+  foreach (array('homepage' => t('Home page'), 'documentation' => t('Read documentation'), 'license' => t('Read license'), 'changelog' => t('Read complete log of changes'), 'demo' => t('Try out a demonstration'), 'screenshots' => t('Look at screenshots')) as $uri => $name) {
+    if (!empty($node->project[$uri])) {
+      $links[$uri] = l($name, $node->project[$uri]);
+    }
+  }
+  if (count($links)) {
+    $output = theme('item_list', $links); 
+  }
+  return $output;
+}
+
+/**
+ * Function that outputs the content of a project "Get involved" block.
+ */ 
+function project_get_involved_block_output() {
+  if (arg(0) != 'node' && !is_numeric(arg(1))) {
+    return;
+  }
+  $node = node_load(arg(1));
+  
+  // Flags that indicate what kind of access to project issues to allow.
+  $has_issues = module_exists('project_issue') && !empty($node->project_issue['issues']);
+  $view_issues = $has_issues && (user_access('access project issues') || user_access('access own project issues') || user_access('administer projects'));
+  $make_issues = $has_issues && node_access('create', 'project_issue');
+  
+  $links = array();
+  if ($view_issues) {
+    $links['pending_patches'] = l(t('View pending patches'), 'project/issues/'. $node->project['uri'], array('query' => 'states=8,13', 'absolute' => TRUE, 'html' => TRUE));
+    $links['available_tasks'] = l(t('View available tasks'), 'project/issues/'. $node->project['uri'], array('query' => 'categories=task'));
+    $links['pending_issues'] = l(t('View all pending issues'), 'project/issues/'. $node->project['uri']);
+  }
+
+  if ($node->project['cvs']) {
+    $links['browse_repository'] = l(t('Browse the CVS repository'), $node->project['cvs']);
+  }
+
+  if (project_use_cvs($node)) {
+    $links['view_cvs_messages'] = l(t('View CVS messages'), 'project/cvs/'. $node->nid);
+    $links['developers'] = l(t('Developers'), 'project/developers/'. $node->nid);
+  }
+
+  if (count($links)) {
+  	$output = '<p>'. t('Put your Drupal expertise to good use and get involved now:') .'</p>';
+    $output .= theme('item_list', $links);
+  }
+  return $output;
+}
+
 function project_search_block_form($form_state, $node_type) {
   $form = search_box($form_state, 'project_search_block_form');
   $form['node_type'] = array(
@@ -1103,3 +1182,4 @@
   return $uris[$nid];
 }
 
+
Index: project.inc
===================================================================
--- project.inc	(revision 581)
+++ project.inc	(working copy)
@@ -337,18 +337,6 @@
     // Build a nested array of sections of links to display on project_project node pages.
     $all_links = array();
 
-    // Resources section
-    $all_links['resources'] = array(
-      'name' => t('Resources'),
-      'weight' => 4,
-    );
-    foreach (array('homepage' => t('Home page'), 'documentation' => t('Read documentation'), 'license' => t('Read license'), 'changelog' => t('Read complete log of changes'), 'demo' => t('Try out a demonstration'), 'screenshots' => t('Look at screenshots')) as $uri => $name) {
-      if (!empty($node->project[$uri])) {
-        $all_links['resources']['links'][$uri] = l($name, $node->project[$uri]);
-      }
-    }
-
-
     // Flags that indicate what kind of access to project issues to allow.
     $has_issues = module_exists('project_issue') && !empty($node->project_issue['issues']);
     $view_issues = $has_issues && (user_access('access project issues') || user_access('access own project issues') || user_access('administer projects'));
@@ -378,29 +366,6 @@
     }
     $all_links['support']['links'] = $links;
 
-
-    // Developer section
-    $all_links['development'] = array(
-      'name' => t('Development'),
-      'weight' => 8,
-    );
-    $links = array();
-    if ($view_issues) {
-      $links['pending_patches'] = l(t('View pending patches'), 'project/issues/'. $node->project['uri'], array('query' => 'states=8,13', 'absolute' => TRUE, 'html' => TRUE));
-      $links['available_tasks'] = l(t('View available tasks'), 'project/issues/'. $node->project['uri'], array('query' => 'categories=task'));
-      $links['pending_issues'] = l(t('View all pending issues'), 'project/issues/'. $node->project['uri']);
-    }
-
-    if ($node->project['cvs']) {
-      $links['browse_repository'] = l(t('Browse the CVS repository'), $node->project['cvs']);
-    }
-
-    if (project_use_cvs($node)) {
-      $links['view_cvs_messages'] = l(t('View CVS messages'), 'project/cvs/'. $node->nid);
-      $links['developers'] = l(t('Developers'), 'project/developers/'. $node->nid);
-    }
-    $all_links['development']['links'] = $links;
-
     // Allow other modules to add sections of links and/or links to the sections defined above.
     project_page_link_alter($node, $all_links);
 
Index: project.module
===================================================================
--- project.module	(revision 581)
+++ project.module	(working copy)
@@ -71,6 +71,18 @@
       'info' => t('Project navigation (text field)'),
       'cache' => BLOCK_CACHE_PER_ROLE,
     );
+    $blocks[3] = array(
+      'info' => t('Project links'),
+      'cache' => BLOCK_CACHE_PER_ROLE,
+    );
+    $blocks[4] = array(
+      'info' => t('Get involved'),
+      'cache' => BLOCK_CACHE_PER_ROLE,
+    );
+    $blocks[5] = array(
+      'info' => t('Project developers'),
+      'cache' => BLOCK_CACHE_PER_ROLE,
+    );
     return $blocks;
   }
   else if ($op == 'view') {
@@ -96,6 +108,24 @@
           'content' => drupal_get_form('project_quick_navigate_title_form'),
         );
         break;
+        
+      case 3:
+        $block = array(
+          'subject' => t('Links'),
+          'content' => project_links_block_output(),
+        );
+        break;
+        
+      case 4:
+        $block = array(
+          'subject' => t('Get involved'),
+          'content' => project_get_involved_block_output(),
+        );
+        break;
+        
+      case 5:
+      	$block = project_developers_block();
+        break;
     }
     return $block;
   }
@@ -114,6 +144,94 @@
   }
 }
 
+/**
+ * Function that outputs the content of a project "Links" block.
+ */ 
+function project_links_block_output() {
+  if (arg(0) != 'node' && !is_numeric(arg(1))) {
+    return;
+  }
+  $node = node_load(arg(1));
+  $links = array();
+  foreach (array('homepage' => t('Home page'), 'documentation' => t('Read documentation'), 'license' => t('Read license'), 'changelog' => t('Read complete log of changes'), 'demo' => t('Try out a demonstration'), 'screenshots' => t('Look at screenshots')) as $uri => $name) {
+    if (!empty($node->project[$uri])) {
+      $links[$uri] = l($name, $node->project[$uri]);
+    }
+  }
+  if (count($links)) {
+    $output = theme('item_list', $links); 
+  }
+  return $output;
+}
+
+/**
+ * Function that outputs the content of a project "Get involved" block.
+ */ 
+function project_get_involved_block_output() {
+  if (arg(0) != 'node' && !is_numeric(arg(1))) {
+    return;
+  }
+  $node = node_load(arg(1));
+  
+  // Flags that indicate what kind of access to project issues to allow.
+  $has_issues = module_exists('project_issue') && !empty($node->project_issue['issues']);
+  $view_issues = $has_issues && (user_access('access project issues') || user_access('access own project issues') || user_access('administer projects'));
+  $make_issues = $has_issues && node_access('create', 'project_issue');
+  
+  $links = array();
+  if ($view_issues) {
+    $links['pending_patches'] = l(t('View pending patches'), 'project/issues/'. $node->project['uri'], array('query' => 'states=8,13', 'absolute' => TRUE, 'html' => TRUE));
+    $links['available_tasks'] = l(t('View available tasks'), 'project/issues/'. $node->project['uri'], array('query' => 'categories=task'));
+    $links['pending_issues'] = l(t('View all pending issues'), 'project/issues/'. $node->project['uri']);
+  }
+
+  if ($node->project['cvs']) {
+    $links['browse_repository'] = l(t('Browse the CVS repository'), $node->project['cvs']);
+  }
+
+  if (project_use_cvs($node)) {
+    $links['view_cvs_messages'] = l(t('View CVS messages'), 'project/cvs/'. $node->nid);
+    $links['developers'] = l(t('Developers'), 'project/developers/'. $node->nid);
+  }
+
+  if (count($links)) {
+    $output = '<p>'. t('Put your Drupal expertise to good use and get involved now:') .'</p>';
+    $output .= theme('item_list', $links);
+  }
+  return $output;
+}
+
+/**
+ * Function that generates the whole project "Developers" block (title + content).
+ *
+ */
+function project_developers_block() {
+  if (arg(0) != 'node' && !is_numeric(arg(1))) {
+    return;
+  }
+  $node = node_load(arg(1));
+  
+  $result = db_query("SELECT f.uid, u.name, MIN(m.created) AS first_commit, MAX(m.created) AS last_commit, COUNT(f.cid) AS commits FROM {cvs_files} f INNER JOIN {cvs_messages} m ON m.cid = f.cid INNER JOIN {users} u ON f.uid = u.uid WHERE f.uid != %d AND f.nid = %d GROUP BY f.nid, f.uid". tablesort_sql($header), 0, $node->nid);
+  $items = array();
+  while ($contributor = db_fetch_object($result)) {
+  	$items[] = theme('project_developer_item', $contributor, $contributor->commits, $contributor->first_commit, $contributor->last_commit); 
+    /*$items[] = array(
+      theme('username', $contributor),
+      t('!time ago', array('!time' => format_interval(time() - $contributor->last_commit, 1))),
+      t('!time ago', array('!time' => format_interval(time() - $contributor->first_commit, 1))),
+      format_plural($contributor->commits, '1 commit', '@count commits')
+    );*/
+  }
+  $content = theme('item_list', $items);
+
+  $block = array(
+    'subject' => t('Developers for @project_name', array('@project_name' => $node->title)),
+    'content' => $content,
+  );
+  
+  return $block;
+}
+
 function project_search_block_form($form_state, $node_type) {
   $form = search_box($form_state, 'project_search_block_form');
   $form['node_type'] = array(
@@ -857,7 +975,15 @@
       'arguments' => array(
         'term' => NULL,
       ),
-    ),
+    ),
+    'project_developer_item' => array(
+      'arguments' => array(
+        'user' => NULL,
+        'commits_nb' => NULL,
+        'first_commit' => NULL,
+        'last_commit' => NULL,
+      )
+    )
   );
 }
 
@@ -1066,9 +1192,29 @@
     $output .= '<p>' . filter_xss($term->description) . '</p>';
   }
   return $output;
+}
+
+/**
+ * Theme a developer item to display in "Developers for project" block.
+ *
+ * @param $contributor
+ *   The contributor object, as returned by the block's SQL query.
+ * 
+ * @return
+ *   The HTML output.
+ */
+function theme_project_developer_item($contributor) {
+      /*$items[] = array(
+      theme('username', $contributor),
+      t('!time ago', array('!time' => format_interval(time() - $contributor->last_commit, 1))),
+      t('!time ago', array('!time' => format_interval(time() - $contributor->first_commit, 1))),
+      format_plural($contributor->commits, '1 commit', '@count commits')
+    );*/
+	$output = '<h6>'. theme('username', $contributor) .' - '. format_plural($contributor->commits, '1 commit', '@count commits') .'</h6>';
+	$output .= '<p class="date">'. t('last: !last_time ago, first: !first_time ago', array('!last_time' => format_interval(time() - $contributor->last_commit, 1), '!first_time' => format_interval(time() - $contributor->first_commit, 1))) .'</p>';
+	return $output;
 }
 
-
 /**
  * Find a project node ID (nid) based on project short name (uri).
  *
@@ -1103,3 +1249,4 @@
   return $uris[$nid];
 }
 
+
