changeset 124:bc91f2025d05 cannam

Make the project list into a sortable table with a little more information in it
author Chris Cannam <chris.cannam@soundsoftware.ac.uk>
date Tue, 18 Jan 2011 17:02:06 +0000
parents 605adf7e1735
children ca48d8b6f55d
files app/controllers/projects_controller.rb app/helpers/projects_helper.rb app/views/projects/index.rhtml config/locales/en-GB.yml config/locales/en.yml public/themes/soundsoftware/stylesheets/application.css
diffstat 6 files changed, 94 insertions(+), 50 deletions(-) [+]
line wrap: on
line diff
--- a/app/controllers/projects_controller.rb	Mon Jan 17 17:22:39 2011 +0000
+++ b/app/controllers/projects_controller.rb	Tue Jan 18 17:02:06 2011 +0000
@@ -47,11 +47,13 @@
   def index
     respond_to do |format|
       format.html { 
+        sort_init 'lft'
+        sort_update %w(lft title created_on updated_on)
         @limit = per_page_option
         @project_count = Project.visible.count
         @project_pages = Paginator.new self, @project_count, @limit, params['page']
         @offset ||= @project_pages.current.offset
-        @projects = Project.visible.all(:offset => @offset, :limit => @limit, :order => 'lft') 
+        @projects = Project.visible.all(:offset => @offset, :limit => @limit, :order => sort_clause) 
         if User.current.logged?
           @user_projects = User.current.projects
         end
--- a/app/helpers/projects_helper.rb	Mon Jan 17 17:22:39 2011 +0000
+++ b/app/helpers/projects_helper.rb	Tue Jan 18 17:02:06 2011 +0000
@@ -143,66 +143,93 @@
     a
   end
 
-  # Renders a tree of projects where the current DOES NOT belong
-  # as a nested set of unordered lists
-  # The given collection may be a subset of the whole project tree
-  # (eg. some intermediate nodes are private and can not be seen)
-  def render_other_project_hierarchy(projects)
-    a = ''
-    s = ''
+  # Renders a tree of projects that the current user does not belong
+  # to, or of all projects if the current user is not logged in.  The
+  # given collection may be a subset of the whole project tree
+  # (eg. some intermediate nodes are private and can not be seen).  We
+  # are potentially interested in various things: the project name,
+  # description, manager(s), creation date, last activity date,
+  # general activity level, whether there is anything actually hosted
+  # here for the project, etc.
+  def render_project_table(projects)
 
-    # True if user has any projects (affects the heading used)
-    t = FALSE
+    s = ""
+    s << "<div class='autoscroll'>"
+    s << "<table class='list projects'>"
+    s << "<thead><tr>"
+    
+    s << sort_header_tag('lft', :caption => l("field_name"), :default_order => 'desc')
+    s << "<th class='managers'>" << l("label_managers") << "</th>"
+    s << sort_header_tag('created_on', :default_order => 'desc')
+    s << sort_header_tag('updated_on', :default_order => 'desc')
 
-    if projects.any?
-      ancestors = []
-      original_project = @project
-      projects.each do |project|
-        # set the project environment to please macros.
+    s << "</tr></thead><tbody>"
 
-        @project = project
+    ancestors = []
+    original_project = @project
+    oddeven = 'even'
+    level = 0
 
-        if not User.current.member_of?(project):
+    projects.each do |project|
 
-          if (ancestors.empty? || project.is_descendant_of?(ancestors.last))
-            s << "<ul class='projects #{ ancestors.empty? ? 'root' : nil}'>\n"
-          else
-            ancestors.pop
-            s << "</li>"
-            while (ancestors.any? && !project.is_descendant_of?(ancestors.last))
-              ancestors.pop
-              s << "</ul></li>\n"
+      # set the project environment to please macros.
+
+      @project = project
+
+      if (ancestors.empty? || project.is_descendant_of?(ancestors.last))
+        level = level + 1
+      else
+        level = 0
+        oddeven = cycle('odd','even')
+        ancestors.pop
+        while (ancestors.any? && !project.is_descendant_of?(ancestors.last))
+          ancestors.pop
+        end
+      end
+      
+      classes = (ancestors.empty? ? 'root' : 'child')
+
+      s << "<tr class='#{oddeven} #{classes} level#{level}'>"
+      s << "<td class='firstcol name hosted_here'>" << link_to_project(project, {}, :class => "project #{User.current.member_of?(project) ? 'my-project' : nil}") << "</td>"
+      s << "<td class='managers'>"
+
+      u = project.users_by_role
+      if u
+        u.keys.each do |r|
+          if r.allowed_to?(:edit_project)
+            mgrs = []
+            u[r].sort.each do |m|
+              mgrs << link_to_user(m)
+            end
+            if mgrs.size < 3
+              s << '<nobr>' << mgrs.join(', ') << '</nobr>'
+            else
+              s << mgrs.join(', ')
             end
           end
+        end
+      end
 
-          classes = (ancestors.empty? ? 'root' : 'child')
-          s << "<li class='#{classes}'><div class='#{classes}'>" +
-                 link_to_project(project, {}, :class => "project #{User.current.member_of?(project) ? 'my-project' : nil}")
-          s << "<div class='wiki description'>#{textilizable(project.short_description, :project => project)}</div>" unless project.description.blank?
-          s << "</div>\n"
-          ancestors << project          
-        else
-          t = TRUE
-        end
-       end
+      s << "</td>"
+      s << "<td class='created_on'>" << format_date(project.created_on) << "</td>"
+      s << "<td class='updated_on'>" << format_date(project.updated_on) << "</td>"
 
-      s << ("</li></ul>\n" * ancestors.size)
-      @project = original_project
+      s << "</tr>"
+      s << "<tr class='#{oddeven} #{classes}'>"
+      s << "<td class='firstcol wiki description'>"
+      s << textilizable(project.short_description, :project => project) unless project.description.blank?
+      s << "</td>"
+      s << "<td colspan=3>&nbsp;</td>"
+      s << "</tr>"
+
+      ancestors << project          
     end
 
-    if t == TRUE
-      a << "<h2>"
-      a <<  l("label_other_project_plural")
-      a << "</h2>"
-      a << s
-    else
-      a << "<h2>"
-      a << l("label_project_all")
-      a << "</h2>"
-      a << s
-    end
+    s << "</table>"
 
-    a
+    @project = original_project
+
+    s
   end
 
 
--- a/app/views/projects/index.rhtml	Mon Jan 17 17:22:39 2011 +0000
+++ b/app/views/projects/index.rhtml	Tue Jan 18 17:02:06 2011 +0000
@@ -14,7 +14,11 @@
 
 <% end %>
 
-<%= render_other_project_hierarchy(@projects)%>
+<h2>
+<%= l("label_project_all") %>
+</h2>
+
+<%= render_project_table(@projects) %>
 
 <p class="pagination"><%= pagination_links_full @project_pages, @project_count %></p>
 
--- a/config/locales/en-GB.yml	Mon Jan 17 17:22:39 2011 +0000
+++ b/config/locales/en-GB.yml	Tue Jan 18 17:02:06 2011 +0000
@@ -434,6 +434,7 @@
     other: "%{count} projects"
   label_project_all: All Projects
   label_project_latest: Latest projects
+  label_managers: Managed by
   label_issue: Issue
   label_issue_new: New issue
   label_issue_plural: Issues
--- a/config/locales/en.yml	Mon Jan 17 17:22:39 2011 +0000
+++ b/config/locales/en.yml	Tue Jan 18 17:02:06 2011 +0000
@@ -452,6 +452,7 @@
     other: "%{count} projects"
   label_project_all: All Projects
   label_project_latest: Latest projects
+  label_managers: Managed by
   label_issue: Issue
   label_issue_new: New issue
   label_issue_plural: Issues
--- a/public/themes/soundsoftware/stylesheets/application.css	Mon Jan 17 17:22:39 2011 +0000
+++ b/public/themes/soundsoftware/stylesheets/application.css	Tue Jan 18 17:02:06 2011 +0000
@@ -67,6 +67,15 @@
 tr.entry { border-left: 1px solid #a9b680; border-right: 1px solid #a9b680; }
 tr.entry:last-child { border-bottom: 1px solid #a9b680; }
 
+table.projects th { text-align: left; }
+table.projects th.managers { color: #3e442c; }
+table.projects .hosted_here { font-weight: bold; }
+table.projects .child .name { font-weight: normal; }
+table.projects .child .description { font-size: 0.95em; }
+table.projects .child .firstcol { padding-left: 1em }
+table.projects .level2 .firstcol { padding-left: 2em; }
+table.projects .level3 .firstcol { padding-left: 3em; }
+
 #top-menu { position: absolute; top: 0; z-index: 1; left: 0px; width: 100%; font-size: 90%; /* height: 2em; */ margin: 0; padding: 0; padding-top: 0.5em; background-color: #3e442c; }
 #top-menu ul { margin-left: 10px; }
 #top-menu a { font-weight: bold; }