changeset 1012:bbca6f4eebc7 live

Merge from branch "browsing"
author Chris Cannam
date Mon, 12 Nov 2012 14:40:09 +0000
parents 96f4b03623ed (current diff) f44860e089c5 (diff)
children b98f60a6d231
files
diffstat 21 files changed, 237 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Fri Nov 09 14:55:35 2012 +0000
+++ b/.hgignore	Mon Nov 12 14:40:09 2012 +0000
@@ -29,7 +29,7 @@
 .svn/
 .git/
 *~
-
+public/themes/soundsoftware/stylesheets/fonts/*
 
 .bundle
 Gemfile.lock
--- a/app/controllers/activities_controller.rb	Fri Nov 09 14:55:35 2012 +0000
+++ b/app/controllers/activities_controller.rb	Mon Nov 12 14:40:09 2012 +0000
@@ -40,7 +40,20 @@
 
     events = @activity.events(@date_from, @date_to)
 
-    if events.empty? || stale?(:etag => [@activity.scope, @date_to, @date_from, @with_subprojects, @author, events.first, User.current, current_language])
+    @institution_name = params[:institution]
+    if !@institution_name.blank?
+      events = events.select do |e|
+        e.respond_to?(:event_author) and e.event_author and
+          e.event_author.ssamr_user_detail.institution_name == @institution_name
+      end
+      if events.empty?
+        # We don't want to dump into the output any arbitrary string
+        # from the URL that has no matching events
+        @institution_name = ""
+      end
+    end
+
+    if events.empty? || stale?(:etag => [@activity.scope, @date_to, @date_from, @with_subprojects, @author, @institution_name, events.first, User.current, current_language])
       respond_to do |format|
         format.html {
           @events_by_day = events.group_by(&:event_date)
--- a/app/controllers/projects_controller.rb	Fri Nov 09 14:55:35 2012 +0000
+++ b/app/controllers/projects_controller.rb	Mon Nov 12 14:40:09 2012 +0000
@@ -20,8 +20,8 @@
   menu_item :roadmap, :only => :roadmap
   menu_item :settings, :only => :settings
 
-  before_filter :find_project, :except => [ :index, :list, :new, :create, :copy ]
-  before_filter :authorize, :except => [ :index, :list, :new, :create, :copy, :archive, :unarchive, :destroy]
+  before_filter :find_project, :except => [ :index, :list, :explore, :new, :create, :copy ]
+  before_filter :authorize, :except => [ :index, :list, :explore, :new, :create, :copy, :archive, :unarchive, :destroy]
   before_filter :authorize_global, :only => [:new, :create]
   before_filter :require_admin, :only => [ :copy, :archive, :unarchive, :destroy ]
   accept_rss_auth :index
@@ -43,6 +43,8 @@
   helper :repositories
   include RepositoriesHelper
   include ProjectsHelper
+  include ActivitiesHelper
+  helper :activities
 
   # Lists visible projects. Paginator is for top-level projects only
   # (subprojects belong to them)
@@ -76,6 +78,16 @@
     end
   end
 
+  # A different view of projects using explore boxes
+  def explore
+    respond_to do |format|
+      format.html {
+        @projects = Project.visible
+        render :template => 'projects/explore.html.erb', :layout => !request.xhr?
+      }
+    end
+  end
+
   def new
     @issue_custom_fields = IssueCustomField.find(:all, :order => "#{CustomField.table_name}.position")
     @trackers = Tracker.all
--- a/app/controllers/welcome_controller.rb	Fri Nov 09 14:55:35 2012 +0000
+++ b/app/controllers/welcome_controller.rb	Mon Nov 12 14:40:09 2012 +0000
@@ -25,7 +25,6 @@
     @site_project = Project.find_by_identifier "soundsoftware-site"
     @site_news = []
     @site_news = News.latest_for @site_project if @site_project
-    @projects = Project.latest User.current
     
     # tests if user is logged in to generate the tips of the day list
     if User.current.logged?
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/helpers/activities_helper.rb	Mon Nov 12 14:40:09 2012 +0000
@@ -0,0 +1,24 @@
+
+module ActivitiesHelper
+
+  def busy_projects(events, count)
+    # Transform events list into hash from project id to number of
+    # occurrences of project in list (there is surely a tidier way
+    # to do this, e.g. chunk() in Ruby 1.9 but not in 1.8)
+    phash = events.map { |e| e.project unless !e.respond_to?(:project) }.sort.group_by { |p| p.id }
+    phash = phash.merge(phash) { |k,v| v.length }
+    threshold = phash.values.sort.last(count).first
+    busy = phash.keys.select { |k| phash[k] >= threshold }.sample(count)
+    busy.map { |pid| Project.find(pid) }
+  end
+
+  def busy_institutions(events, count)
+    authors = events.map { |e| e.event_author unless !e.respond_to?(:event_author) }.compact
+    institutions = authors.map { |a| a.ssamr_user_detail.institution_name }
+    insthash = institutions.compact.sort.group_by { |i| i }
+    insthash = insthash.merge(insthash) { |k,v| v.length }
+    threshold = insthash.values.sort.last(count).first
+    insthash.keys.select { |k| insthash[k] >= threshold }.sample(count)
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/views/activities/_busy.html.erb	Mon Nov 12 14:40:09 2012 +0000
@@ -0,0 +1,48 @@
+<% events = @events_by_day %>
+<% if (events.nil?) 
+     activity = Redmine::Activity::Fetcher.new(User.current)
+     events = activity.events(Date.today - 14, Date.today + 1)
+   end
+%>
+
+<% if events.empty? %>
+
+<% else %>
+
+   <ul>
+
+   <% 
+      for project in busy_projects(events, 5)
+   %>
+
+   <li class="busy">
+     <span class="title">
+       <% if !project.root? %>
+         <% project.ancestors.each do |p| %>
+           <%= h(p) %>&nbsp;&#187;
+         <% end %>
+       <% end %>
+       <%= link_to_project project %>
+     </span>
+     <% if !project.is_public? %>
+       <span class="private"><%= l(:field_is_private) %></span>
+     <% end %>
+     <span class='managers'>
+     <%
+	u = project.users_by_role
+	if ! u.empty? %>
+     (<%=
+	   mgmt_roles = u.keys.select{ |r| r.allowed_to?(:edit_project) }
+	   managers = mgmt_roles.map{ |r| u[r] }.flatten.sort.uniq
+	   managers.map{ |m| m.name }.join(', ')
+	 %>)<%
+	end
+	%>
+	</span>
+
+     <%= render_project_short_description project %>
+   </li>
+
+    <% end %>
+  </ul>
+<% end %>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/views/activities/_busy_institution.html.erb	Mon Nov 12 14:40:09 2012 +0000
@@ -0,0 +1,26 @@
+<% events = @events_by_day %>
+<% if (events.nil?) 
+     activity = Redmine::Activity::Fetcher.new(User.current)
+     events = activity.events(Date.today - 14, Date.today + 1)
+   end
+%>
+
+<% if events.empty? %>
+
+<% else %>
+
+   <ul>
+
+   <% 
+      for institution in busy_institutions(events, 5)
+   %>
+
+   <li class="busy">
+     <span class="title">
+       <%= link_to h(institution), { :controller => 'activities', :institution => institution } %>
+     </span>
+   </li>
+
+    <% end %>
+  </ul>
+<% end %>
--- a/app/views/activities/index.html.erb	Fri Nov 09 14:55:35 2012 +0000
+++ b/app/views/activities/index.html.erb	Mon Nov 12 14:40:09 2012 +0000
@@ -1,4 +1,14 @@
-<h2><%= @author.nil? ? l(:label_activity) : l(:label_user_activity, link_to_user(@author)) %></h2>
+<h2><%=
+  if @author.nil?
+    if @institution_name.blank?
+      l(:label_activity)
+    else
+      l(:label_institution_activity, h(@institution_name))
+    end
+  else
+    l(:label_user_activity, link_to_user(@author))
+  end
+  %></h2>
 <p class="subtitle"><%= l(:label_date_from_to, :start => format_date(@date_to - @days), :end => format_date(@date_to-1)) %></p>
 
 <div id="activity">
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/views/projects/_latest.html.erb	Mon Nov 12 14:40:09 2012 +0000
@@ -0,0 +1,19 @@
+    <ul>
+    <% for project in Project.latest(User.current) %>
+	<li class="latest">
+	<span class="title">
+	  <% if !project.root? %>
+	    <% project.ancestors.each do |p| %>
+	      <%= h(p) %>&nbsp;&#187;
+	    <% end %>
+	  <% end %>
+	<%= link_to_project project %>
+	</span>
+	<% if !project.is_public? %>
+	   <span class="private"><%= l(:field_is_private) %></span>
+	<% end %>
+	<span class="time"><%= format_time(project.created_on)%></span>
+	<%= render_project_short_description project %>
+      </li>
+    <% end %>
+    </ul>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/views/projects/explore.html.erb	Mon Nov 12 14:40:09 2012 +0000
@@ -0,0 +1,23 @@
+
+<h2><%= l(:label_explore_projects) %></h2>
+
+  <div class="tags box">
+  <h3><%=l(:label_project_tags_all)%></h3>
+    <%= render :partial => 'projects/tagcloud' %>
+  </div>
+<div class="splitcontentleft">
+  <div class="institutions box">
+  <h3><%=l(:label_institutions_busy)%></h3>
+    <%= render :partial => 'activities/busy_institution' %>
+  </div>
+  <div class="projects box">
+  <h3><%=l(:label_project_latest)%></h3>
+    <%= render :partial => 'projects/latest' %>
+  </div>
+</div>
+<div class="splitcontentright">
+  <div class="projects box">
+  <h3><%=l(:label_projects_busy)%></h3>
+    <%= render :partial => 'activities/busy' %>
+  </div>
+</div>
--- a/app/views/welcome/index.html.erb	Fri Nov 09 14:55:35 2012 +0000
+++ b/app/views/welcome/index.html.erb	Mon Nov 12 14:40:09 2012 +0000
@@ -14,40 +14,17 @@
 
 <div class="splitcontentright">
   <% if @site_news.any? %>
-  <div class="news box">
-	<h3><%=l(:label_news_site_latest)%></h3>
+    <div class="news box">
+       <h3><%=l(:label_news_site_latest)%></h3>
 	<%= render :partial => 'news/news', :locals => { :project => @site_project }, :collection => @site_news %>
-	
 	<%= link_to l(:label_news_more), { :controller => 'projects', :action => @site_project.identifier, :id => 'news' } %>
   </div>
   <% end %>
-    <% if @projects.any? %>
   <div class="projects box">
   <h3><%=l(:label_project_latest)%></h3>
-    <ul>
-    <% for project in @projects %>
-      <% @project = project %>
-	<li class="latest">
-	<span class="title">
-	  <% if !project.root? %>
-	    <% project.ancestors.each do |p| %>
-	      <%= h(p) %>&nbsp;&#187;
-	    <% end %>
-	  <% end %>
-	<%= link_to_project project %>
-	</span>
-	<% if !project.is_public? %>
-	   <span class="private"><%= l(:field_is_private) %></span>
-	<% end %>
-	<span class="time"><%= format_time(project.created_on)%></span>
-	<%= render_project_short_description project %>
-      </li>
-    <% end %>
-    <% @project = nil %>
-    </ul>
-	<%= link_to l(:label_projects_more), :controller => 'projects' %>
+    <%= render :partial => 'projects/latest' %>
+    <%= link_to l(:label_projects_more), :controller => 'projects' %>
   </div>
-  <% end %>
     <%= call_hook(:view_welcome_index_right, :projects => @projects) %>
 </div>
 
--- a/config/locales/en.yml	Fri Nov 09 14:55:35 2012 +0000
+++ b/config/locales/en.yml	Mon Nov 12 14:40:09 2012 +0000
@@ -494,6 +494,9 @@
   label_project_all: All Projects
   label_project_latest: Latest projects
   label_projects_more: More projects
+  label_project_tags_all: Popular tags
+  label_projects_busy: Busy projects
+  label_institutions_busy: Active institutions
   label_managers: Managed by
   label_issue: Issue
   label_issue_new: New issue
@@ -560,6 +563,7 @@
   label_activity_my_recent_none: No recent activity
   label_overall_activity: Overall activity
   label_user_activity: "%{value}'s activity"
+  label_institution_activity: "Activity from %{value}"
   label_new: New
   label_logged_as: Logged in as
   label_environment: Environment
@@ -689,7 +693,7 @@
   label_repository: Repository
   label_is_external_repository: Track an external repository
   label_repository_plural: Repositories
-  label_browse: Browse
+  label_explore_projects: Explore projects
   label_modification: "%{count} change"
   label_modification_plural: "%{count} changes"
   label_branch: Branch
--- a/config/routes.rb	Fri Nov 09 14:55:35 2012 +0000
+++ b/config/routes.rb	Mon Nov 12 14:40:09 2012 +0000
@@ -32,6 +32,8 @@
   # TODO: wasteful since this is also nested under issues, projects, and projects/issues
   map.resources :time_entries, :controller => 'timelog'
 
+  map.connect 'explore', :controller => 'projects', :action => 'explore'
+
   map.connect 'projects/:id/wiki', :controller => 'wikis', :action => 'edit', :conditions => {:method => :post}
   map.connect 'projects/:id/wiki/destroy', :controller => 'wikis', :action => 'destroy', :conditions => {:method => :get}
   map.connect 'projects/:id/wiki/destroy', :controller => 'wikis', :action => 'destroy', :conditions => {:method => :post}
--- a/public/stylesheets/application.css	Fri Nov 09 14:55:35 2012 +0000
+++ b/public/stylesheets/application.css	Mon Nov 12 14:40:09 2012 +0000
@@ -240,6 +240,8 @@
 div.members h3 { background: url(../images/group.png) no-repeat 0% 50%; padding-left: 20px; }
 div.news h3 { background: url(../images/news.png) no-repeat 0% 50%; padding-left: 20px; }
 div.projects h3 { background: url(../images/projects.png) no-repeat 0% 50%; padding-left: 20px; }
+div.tags h3 { background: url(../images/ticket_note.png) no-repeat 0% 50%; padding-left: 20px; }
+div.institutions h3 { background: url(../images/group.png) no-repeat 0% 50%; padding-left: 20px; }
 
 #watchers ul {margin: 0;  padding: 0;}
 #watchers li {list-style-type:none;margin: 0px 2px 0px 0px; padding: 0px 0px 0px 0px;}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vendor/plugins/redmine_tags/app/controllers/tags_controller.rb	Mon Nov 12 14:40:09 2012 +0000
@@ -0,0 +1,15 @@
+class TagsController < ApplicationController
+  
+  def index
+    respond_to do |format|
+      format.html {
+        render :template => 'tags/index.html.erb', :layout => !request.xhr?
+      }
+      format.api  {
+      }
+      format.atom {
+      }
+    end
+  end
+
+end
--- a/vendor/plugins/redmine_tags/app/helpers/tags_helper.rb	Fri Nov 09 14:55:35 2012 +0000
+++ b/vendor/plugins/redmine_tags/app/helpers/tags_helper.rb	Mon Nov 12 14:40:09 2012 +0000
@@ -40,8 +40,11 @@
     content_tag('span', content, :class => 'tag-label')
   end
 
-  def render_project_tag_link(tag)
+  def render_project_tag_link(tag, options = {})
     content = link_to tag.name, :controller => :projects, :action => :index, :project => { :tag_list => tag.name } 
+    if options[:show_count]
+      content << content_tag('span', "(#{tag.count})", :class => 'tag-count')
+    end
     content_tag('span', content, :class => 'tag-label')
   end
 
@@ -73,7 +76,7 @@
       end
 
       tag_cloud tags, (1..8).to_a do |tag, weight|
-        content << " " + content_tag(item_el, render_tag_link(tag, options), :class => "tag-nube-#{weight}") + " "
+        content << " " + content_tag(item_el, render_project_tag_link(tag, options), :class => "tag-nube-#{weight}") + " "
       end
 
       content_tag(list_el, content, :class => 'tags')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vendor/plugins/redmine_tags/app/views/projects/_tagcloud.html.erb	Mon Nov 12 14:40:09 2012 +0000
@@ -0,0 +1,9 @@
+<% content_for :header_tags do %>
+    <%= stylesheet_link_tag 'redmine_tags', :plugin => 'redmine_tags' %>
+<% end %>
+
+<div id="tags">
+<%= render_tags_list(Project.available_tags, :style => :cloud) %>
+</div>
+
+
--- a/vendor/plugins/redmine_tags/app/views/projects/index.html.erb	Fri Nov 09 14:55:35 2012 +0000
+++ b/vendor/plugins/redmine_tags/app/views/projects/index.html.erb	Mon Nov 12 14:40:09 2012 +0000
@@ -11,7 +11,6 @@
 </div>
 
 
-
 <div style="clear:both;"></div>
 <% if User.current.logged? %>
   <%= render :partial => 'my_projects' %>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vendor/plugins/redmine_tags/app/views/tags/index.html.erb	Mon Nov 12 14:40:09 2012 +0000
@@ -0,0 +1,13 @@
+<% content_for :header_tags do %>
+    <%= auto_discovery_link_tag(:atom, {:action => 'index', :format => 'atom', :key => User.current.rss_key}) %>
+    <%= stylesheet_link_tag 'redmine_tags', :plugin => 'redmine_tags' %>
+<% end %>
+
+
+<div style="clear:both;"></div>
+<h2>
+  <%= l("label_project_tags_all") %>
+</h2>
+
+<%= render_tags_list(Project.available_tags, :style => :cloud) %>
+
--- a/vendor/plugins/redmine_tags/assets/stylesheets/redmine_tags.css	Fri Nov 09 14:55:35 2012 +0000
+++ b/vendor/plugins/redmine_tags/assets/stylesheets/redmine_tags.css	Mon Nov 12 14:40:09 2012 +0000
@@ -22,6 +22,7 @@
 ul.tags li { margin: .25em 0px; }
 
 div.tags { text-align: center; }
+div.tags h3 { text-align: left; }
 div.tags .tag-label { margin: .25em; }
 div.tags .tag-nube-1 { font-size: .8em; }
 div.tags .tag-nube-2 { font-size: .9em; }
--- a/vendor/plugins/redmine_tags/lib/redmine_tags/patches/projects_helper_patch.rb	Fri Nov 09 14:55:35 2012 +0000
+++ b/vendor/plugins/redmine_tags/lib/redmine_tags/patches/projects_helper_patch.rb	Mon Nov 12 14:40:09 2012 +0000
@@ -4,6 +4,7 @@
 
       def self.included(base) # :nodoc:
         base.send(:include, InstanceMethods)
+        base.send(:include, TagsHelper)
         base.class_eval do
           unloadable
         end