changeset 379:f25c73364bfb cannam-pre-20110113-merge

Merge from branch "feature_121"
author Chris Cannam
date Mon, 04 Apr 2011 10:29:54 +0100
parents 773777b12fa1 (diff) c80fd1ef305f (current diff)
children 6627ac1de32b 7ba3ba2a0f63 59a5c4d96ff2
files app/views/activities/_recent.rhtml
diffstat 20 files changed, 153 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/app/controllers/application_controller.rb	Mon Apr 04 10:28:08 2011 +0100
+++ b/app/controllers/application_controller.rb	Mon Apr 04 10:29:54 2011 +0100
@@ -263,12 +263,17 @@
         uri = URI.parse(back_url)
         # do not redirect user to another host or to the login or register page
         if (uri.relative? || (uri.host == request.host)) && !uri.path.match(%r{/(login|account/register)})
+          # soundsoftware: if back_url is the home page,
+          # change it to My Page (#125)
+          if (uri.path == home_path)
+            uri.path = uri.path + "/my"
+          end
           # soundsoftware: if login page is https but back_url http,
           # switch back_url to https to ensure cookie validity (#83)
           if (uri.scheme == "http") && (URI.parse(request.url).scheme == "https")
             uri.scheme = "https"
-            back_url = uri.to_s
           end
+          back_url = uri.to_s
           redirect_to(back_url)
           return
         end
--- a/app/controllers/files_controller.rb	Mon Apr 04 10:28:08 2011 +0100
+++ b/app/controllers/files_controller.rb	Mon Apr 04 10:29:54 2011 +0100
@@ -8,7 +8,7 @@
   include SortHelper
 
   def index
-    sort_init 'active', 'asc'
+    sort_init 'active', 'desc'
     sort_update 'filename' => "#{Attachment.table_name}.filename",
 		'active' => "#{Attachment.table_name}.active",
                 'created_on' => "#{Attachment.table_name}.created_on",
--- a/app/controllers/my_controller.rb	Mon Apr 04 10:28:08 2011 +0100
+++ b/app/controllers/my_controller.rb	Mon Apr 04 10:29:54 2011 +0100
@@ -26,12 +26,13 @@
              'issueswatched' => :label_watched_issues,
              'activitymyprojects' => :label_activity_my_recent,
              'news' => :label_news_latest,
+             'tipoftheday' => :label_tipoftheday,
              'calendar' => :label_calendar,
              'documents' => :label_document_plural,
              'timelog' => :label_spent_time
            }.merge(Redmine::Views::MyPage::Block.additional_blocks).freeze
 
-  DEFAULT_LAYOUT = {  'left' => ['activitymyprojects'], 
+  DEFAULT_LAYOUT = {  'left' => ['tipoftheday', 'activitymyprojects'], 
                       'right' => ['issueswatched','calendar'] 
                    }.freeze
 
--- a/app/controllers/projects_controller.rb	Mon Apr 04 10:28:08 2011 +0100
+++ b/app/controllers/projects_controller.rb	Mon Apr 04 10:29:54 2011 +0100
@@ -217,7 +217,15 @@
       end
     end
   end
-  
+
+  def overview
+    @project.has_welcome_page = params[:has_welcome_page]
+    if @project.save
+      flash[:notice] = l(:notice_successful_update)
+    end
+    redirect_to :action => 'settings', :id => @project, :tab => 'overview'
+  end
+
   def modules
     @project.enabled_module_names = params[:enabled_modules]
     flash[:notice] = l(:notice_successful_update)
--- a/app/controllers/welcome_controller.rb	Mon Apr 04 10:28:08 2011 +0100
+++ b/app/controllers/welcome_controller.rb	Mon Apr 04 10:29:54 2011 +0100
@@ -22,10 +22,12 @@
   helper :projects
 
   def index
-    @news = News.latest User.current
+    @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 gfenerate the tips of the day list
+    # tests if user is logged in to generate the tips of the day list
     if User.current.logged?
       @tipsoftheday = Setting.tipoftheday_text
     else
--- a/app/helpers/projects_helper.rb	Mon Apr 04 10:28:08 2011 +0100
+++ b/app/helpers/projects_helper.rb	Mon Apr 04 10:29:54 2011 +0100
@@ -23,6 +23,7 @@
   
   def project_settings_tabs
     tabs = [{:name => 'info', :action => :edit_project, :partial => 'projects/edit', :label => :label_information_plural},
+            {:name => 'overview', :action => :edit_project, :partial => 'projects/settings/overview', :label => :label_welcome_page},
             {:name => 'modules', :action => :select_project_modules, :partial => 'projects/settings/modules', :label => :label_module_plural},
             {:name => 'members', :action => :manage_members, :partial => 'projects/settings/members', :label => :label_member_plural},
             {:name => 'versions', :action => :manage_versions, :partial => 'projects/settings/versions', :label => :label_version_plural},
--- a/app/models/news.rb	Mon Apr 04 10:28:08 2011 +0100
+++ b/app/models/news.rb	Mon Apr 04 10:29:54 2011 +0100
@@ -37,4 +37,9 @@
   def self.latest(user = User.current, count = 5)
     find(:all, :limit => count, :conditions => Project.allowed_to_condition(user, :view_news), :include => [ :author, :project ], :order => "#{News.table_name}.created_on DESC")	
   end
+
+  # returns latest news for a specific project
+  def self.latest_for(project, count = 5)
+    find(:all, :limit => count, :conditions => [ "#{News.table_name}.project_id = #{project.id}", Project.allowed_to_condition(User.current, :view_news) ], :include => [ :author, :project ], :order => "#{News.table_name}.created_on DESC") 
+  end
 end
--- a/app/views/activities/_recent.rhtml	Mon Apr 04 10:28:08 2011 +0100
+++ b/app/views/activities/_recent.rhtml	Mon Apr 04 10:29:54 2011 +0100
@@ -2,11 +2,21 @@
 <% max = 5 %>
 <% if (events.nil?) 
      activity = Redmine::Activity::Fetcher.new(User.current, :project => @project)
+     
+     if @project
+        # Don't show news (duplicated with News box) or wiki edits (too
+	# tedious) in project front page
+        activity.scope = [ "changesets", "files", "issues", "documents" ]
+     end
+     
      events = activity.events(Date.today - 28, Date.today + 1)
+     
      if defined? user
        events = events.select { |e| user.member_of? e.project }
      end
+     
      events = events.first(max)
+
    end
 %>
 
--- a/app/views/layouts/base.rhtml	Mon Apr 04 10:28:08 2011 +0100
+++ b/app/views/layouts/base.rhtml	Mon Apr 04 10:29:54 2011 +0100
@@ -88,7 +88,7 @@
 	
 <div id="footer">
   <div class="bgl"><div class="bgr">
-    Powered by <%= link_to Redmine::Info.app_name, Redmine::Info.url %> &copy; 2006-2011 Jean-Philippe Lang
+    <small>Powered by <%= link_to Redmine::Info.app_name, Redmine::Info.url %><br>&copy; 2006-2011 Jean-Philippe Lang</small>
   </div></div>
 </div>
 </div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/views/my/blocks/_tipoftheday.rhtml	Mon Apr 04 10:29:54 2011 +0100
@@ -0,0 +1,4 @@
+    <h3><%=l(:label_tipoftheday)%></h3>
+    <div class="tipoftheday box">
+          <div class="tip"><%= textilizable Setting.tipoftheday_text %></div>
+    </div>
--- a/app/views/news/_news.rhtml	Mon Apr 04 10:28:08 2011 +0100
+++ b/app/views/news/_news.rhtml	Mon Apr 04 10:29:54 2011 +0100
@@ -1,6 +1,13 @@
-<p><%= link_to_project(news.project) + ': ' unless @project %>
-<%= link_to h(news.title), news_path(news) %>
-<%= "(#{l(:label_x_comments, :count => news.comments_count)})" if news.comments_count > 0 %>
-<br />
+<div id="news">
+<dt>
+<span class="time"><%= format_time(news.created_on) %></span>
+<% project ||= @project %>
+<% if !project %>
+<span class="project"><%= link_to_project(news.project) %></span>
+<% end %>
+<span class="headline"><%= link_to h(news.title), news_path(news) %></span>
+<span class="comments"><%= "(#{l(:label_x_comments, :count => news.comments_count)})" if news.comments_count > 0 %></span>
+</dt><dd>
 <% unless news.summary.blank? %><span class="summary"><%=h news.summary %></span><br /><% end %>
-<span class="author"><%= authoring news.created_on, news.author %></span></p>
+</dd>
+</div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/views/projects/settings/_overview.rhtml	Mon Apr 04 10:29:54 2011 +0100
@@ -0,0 +1,30 @@
+
+<% form_for :project, @project,
+            :url => { :action => 'overview', :id => @project },
+            :html => {:id => 'overview-form'} do |f| %>
+
+<div class="box tabular">
+
+<p><%= l(:text_has_welcome_page_info, { :overview_link => link_to(l(:label_overview), { :controller => 'projects', :action => 'show' } ) } ) %></p>
+
+<% if @project.module_enabled? :wiki %>
+
+<p><%= link_to(l(:button_welcome_page_edit), {:controller => 'wiki', :action => 'edit', :project_id => @project, :id => Wiki.titleize("Overview")}, :class => 'icon icon-edit') %>
+
+<% else %>
+
+<p><%= l(:text_has_welcome_page_wiki_disabled, { :modules_link => link_to(l(:label_module_plural), { :controller => 'projects', :action => 'settings', :tab => 'modules' } ) } ) %></p>
+
+<% end %>
+
+<p><label for="has_welcome_page"><%= l(:label_has_welcome_page) %></label>
+<%= check_box_tag 'has_welcome_page', 1, @project.has_welcome_page? -%>
+<br/><em><%= l(:setting_has_welcome_page) %></em>
+
+</p>
+
+</div>
+
+<%= submit_tag l(:button_save) %>
+
+<% end %>
--- a/app/views/projects/show.rhtml	Mon Apr 04 10:28:08 2011 +0100
+++ b/app/views/projects/show.rhtml	Mon Apr 04 10:29:54 2011 +0100
@@ -4,6 +4,29 @@
 	<% end %>
 </div>
 
+<% if @project.has_welcome_page %>
+<% page = @project.wiki.find_page("Overview") %>
+<% end %>
+
+<% if page %>
+
+<div class="contextual" style="clear: right">
+<ul>
+<% @users_by_role.keys.sort.each do |role| %>
+<li><%=h role %>: <%= @users_by_role[role].sort.collect{|u| link_to_user u}.join(", ") %></li>
+<% end %>
+<% unless @project.homepage.blank? %><li><%=l(:field_homepage)%>: <%= auto_link(h(@project.homepage)) %></li><% end %>
+<% if @subprojects.any? %>
+	<li><%=l(:label_subproject_plural)%>:
+	    <%= @subprojects.collect{|p| link_to(h(p), :action => 'show', :id => p)}.join(", ") %></li>
+<% end %>
+</ul>
+</div>
+
+<%= render(:partial => "wiki/content", :locals => {:content => page.content_for_version()}) %>
+
+<% else %>
+
 <h2><%=l(:label_overview)%></h2> 
 	
 <div class="splitcontentleft">
@@ -23,7 +46,8 @@
 	<% end %>
 	</ul>	
 
-  <% if User.current.allowed_to?(:view_issues, @project) %>
+  <% if User.current.allowed_to?(:view_issues, @project) and @open_issues_by_tracker.values.any? %>
+
   <div class="issues box">    
     <h3><%=l(:label_issue_tracking)%></h3>
     <ul>
@@ -78,6 +102,8 @@
     <%= call_hook(:view_projects_show_sidebar_bottom, :project => @project) %>
 <% end %>
 
+<% end %>
+
 <% content_for :header_tags do %>
 <%= auto_discovery_link_tag(:atom, {:controller => 'activities', :action => 'index', :id => @project, :format => 'atom', :key => User.current.rss_key}) %>
 <% end %>
--- a/app/views/welcome/index.rhtml	Mon Apr 04 10:28:08 2011 +0100
+++ b/app/views/welcome/index.rhtml	Mon Apr 04 10:29:54 2011 +0100
@@ -9,24 +9,18 @@
 <div class="splitcontentleft">
   <%= textilizable Setting.welcome_text %>
   
-  <% if @news.any? %>
-  <div class="news box">
-	<h3><%=l(:label_news_latest)%></h3>
-		<%= render :partial => 'news/news', :collection => @news %>
-		<%= link_to l(:label_news_view_all), :controller => 'news' %>
-  </div>
-  <% end %>
   <%= call_hook(:view_welcome_index_left, :projects => @projects) %>
 </div>
 
 <div class="splitcontentright">
-  <% if not @tipsoftheday.empty? %>
-    <div class="newsoftheday box">
-          <h3><%=l(:label_tipoftheday)%></h3>
-          <%= textilizable @tipsoftheday %>
-    </div>
+  <% if @site_news.any? %>
+  <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>
@@ -34,12 +28,14 @@
 		<% for project in @projects %>
 		  <% @project = project %>
 			<li class="latest">
-			<%= link_to_project project %> (<%= format_time(project.created_on) %>)
+			<span class="title"><%= link_to_project project %></span>
+			<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' %>
 	</div>
 	<% end %>
     <%= call_hook(:view_welcome_index_right, :projects => @projects) %>
--- a/config/locales/en.yml	Mon Apr 04 10:28:08 2011 +0100
+++ b/config/locales/en.yml	Mon Apr 04 10:29:54 2011 +0100
@@ -373,6 +373,7 @@
   setting_rest_api_enabled: Enable REST web service
   setting_cache_formatted_text: Cache formatted text
   setting_default_notification_option: Default notification option
+  setting_has_welcome_page: Select this to replace the project overview page with your welcome page
   
   permission_add_project: Create project
   permission_add_subprojects: Create subprojects
@@ -463,6 +464,7 @@
     other: "{{count}} projects"
   label_project_all: All Projects
   label_project_latest: Latest projects
+  label_projects_more: More projects
   label_managers: Managed by
   label_issue: Issue
   label_issue_new: New issue
@@ -559,6 +561,8 @@
   label_news_new: Add news
   label_news_plural: News
   label_news_latest: Latest news
+  label_news_site_latest: Site news
+  label_news_more: More news
   label_news_view_all: View all news
   label_news_added: News added
   label_settings: Settings
@@ -752,6 +756,7 @@
   label_added_time_by: "Added by {{author}} {{age}} ago"
   label_updated_time_by: "Updated by {{author}} {{age}} ago"
   label_updated_time: "Updated {{value}} ago"
+  label_time_ago: "{{age}} ago"
   label_jump_to_a_project: Jump to a project...
   label_file_plural: Downloads
   label_changeset_plural: Changesets
@@ -819,6 +824,8 @@
   label_project_copy_notifications: Send email notifications during the project copy
   label_principal_search: "Search by name:"
   label_user_search: "Search for user:"
+  label_welcome_page: "Welcome page"
+  label_has_welcome_page: "Use your own welcome page"
   
   button_login: Login
   button_submit: Submit
@@ -864,6 +871,7 @@
   button_quote: Quote
   button_duplicate: Duplicate
   button_show: Show
+  button_welcome_page_edit: Create or edit welcome page
   
   status_active: active
   status_registered: registered
@@ -945,6 +953,8 @@
   text_settings_repo_is_internal: Currently the repository hosted at this site is the primary repository for this project.
   text_settings_repo_is_external: Currently the repository hosted at this site is a read-only copy of an external repository.
   text_settings_repo_need_help: Please <a href="/projects/soundsoftware-site/wiki/Help">contact us</a> if you need help deciding how best to set this up.<br>We can also import complete revision history from other systems into a new primary repository for you if you wish.
+  text_has_welcome_page_info: <b>Welcome page</b><p>You can replace the standard {{overview_link}} page for this project with your own welcome page.<br>This page will be editable using the project Wiki.
+  text_has_welcome_page_wiki_disabled: <b>Note:</b> You must enable the Wiki module in the {{modules_link}} tab before you can create or edit this page.
 
  
   default_role_manager: Manager
--- a/config/routes.rb	Mon Apr 04 10:28:08 2011 +0100
+++ b/config/routes.rb	Mon Apr 04 10:29:54 2011 +0100
@@ -138,6 +138,7 @@
     :copy => [:get, :post],
     :settings => :get,
     :modules => :post,
+    :overview => :post,
     :archive => :post,
     :unarchive => :post
   } do |project|
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/db/migrate/20110331152140_add_has_welcome_page_to_projects.rb	Mon Apr 04 10:29:54 2011 +0100
@@ -0,0 +1,9 @@
+class AddHasWelcomePageToProjects < ActiveRecord::Migration
+  def self.up
+    add_column :projects, :has_welcome_page, :boolean
+  end
+
+  def self.down
+    remove_column :projects, :has_welcome_page
+  end
+end
--- a/extra/soundsoftware/reposman-soundsoftware.rb	Mon Apr 04 10:28:08 2011 +0100
+++ b/extra/soundsoftware/reposman-soundsoftware.rb	Mon Apr 04 10:29:54 2011 +0100
@@ -346,14 +346,5 @@
     log("\trepository #{repos_path} created");
   end
 
-  if project.respond_to?(:repository) and project.repository.is_external?
-    external_url = project.repository.external_url;
-    log("\tproject #{project.identifier} has external repository url #{external_url}");
-    if !external_url.match(/^https?:/)
-      # wot about git, svn/svn+ssh, etc? should we just check for a scheme at all?
-      log("\tthis is not an http(s) url: ignoring");
-    end
-  end
-
 end
   
--- a/lib/redmine.rb	Mon Apr 04 10:28:08 2011 +0100
+++ b/lib/redmine.rb	Mon Apr 04 10:29:54 2011 +0100
@@ -48,7 +48,7 @@
   map.permission :view_project, {:projects => [:show], :activities => [:index]}, :public => true
   map.permission :search_project, {:search => :index}, :public => true
   map.permission :add_project, {:projects => [:new, :create]}, :require => :loggedin
-  map.permission :edit_project, {:projects => [:settings, :edit, :update]}, :require => :member
+  map.permission :edit_project, {:projects => [:settings, :edit, :update, :overview]}, :require => :member
   map.permission :select_project_modules, {:projects => :modules}, :require => :member
   map.permission :manage_members, {:projects => :settings, :members => [:new, :edit, :destroy, :autocomplete_for_member]}, :require => :member
   map.permission :manage_versions, {:projects => :settings, :versions => [:new, :create, :edit, :update, :close_completed, :destroy]}, :require => :member
@@ -185,6 +185,7 @@
 
 Redmine::MenuManager.map :project_menu do |menu|
   menu.push :overview, { :controller => 'projects', :action => 'show' }
+  menu.push :news, { :controller => 'news', :action => 'index' }, :param => :project_id, :caption => :label_news_plural
   menu.push :activity, { :controller => 'activities', :action => 'index' }
   menu.push :roadmap, { :controller => 'versions', :action => 'index' }, :param => :project_id,
               :if => Proc.new { |p| p.shared_versions.any? }
@@ -193,7 +194,6 @@
               :html => { :accesskey => Redmine::AccessKeys.key_for(:new_issue) }
   menu.push :gantt, { :controller => 'gantts', :action => 'show' }, :param => :project_id, :caption => :label_gantt
   menu.push :calendar, { :controller => 'calendars', :action => 'show' }, :param => :project_id, :caption => :label_calendar
-  menu.push :news, { :controller => 'news', :action => 'index' }, :param => :project_id, :caption => :label_news_plural
   menu.push :documents, { :controller => 'documents', :action => 'index' }, :param => :project_id, :caption => :label_document_plural
   menu.push :wiki, { :controller => 'wiki', :action => 'show', :id => nil }, :param => :project_id,
               :if => Proc.new { |p| p.wiki && !p.wiki.new_record? }
--- a/public/stylesheets/application.css	Mon Apr 04 10:28:08 2011 +0100
+++ b/public/stylesheets/application.css	Mon Apr 04 10:29:54 2011 +0100
@@ -294,16 +294,19 @@
 div#issue-changesets div.changeset { border-bottom: 1px solid #ddd; }
 div#issue-changesets p { margin-top: 0; margin-bottom: 1em;}
 
-div#activity dl, #search-results { margin-left: 2em; }
+div#activity dl, div#news dl, #search-results { margin-left: 2em; }
 div#activity .box dl { margin-left: 0; }
-div#activity dd, #search-results dd { margin-bottom: 1em; padding-left: 18px; font-size: 0.9em; }
-div#activity dt, #search-results dt { margin-bottom: 0px; padding-left: 20px; line-height: 18px; background-position: 0 50%; background-repeat: no-repeat; }
-div#activity dt.me .time { border-bottom: 1px solid #999; }
-div#activity dt .time { color: #777; font-size: 80%; }
+div#activity dd, div#news dd, #search-results dd { margin-bottom: 1em; padding-left: 18px; font-size: 0.9em; }
+div#activity dt, div#news dt, #search-results dt { margin-bottom: 0px; padding-left: 20px; line-height: 18px; background-position: 0 50%; background-repeat: no-repeat; }
+div#activity dt.me .time, div#news dt.me .time { border-bottom: 1px solid #999; }
+div#activity dt .time, div#news dt .time, .projects .latest .time { color: #777; font-size: 80%; }
 div#activity dd .description, #search-results dd .description { font-style: italic; }
-div#activity span.project:after, #search-results span.project:after { content: " -"; }
+div#activity span.project:after, div#news span.project:after, #search-results span.project:after { content: " -"; }
 div#activity dd span.description, #search-results dd span.description { display:block; color: #808080; }
 
+.projects .latest .title { margin-right: 0.5em; }
+.tipoftheday .tip { margin-left: 2em; margin-top: 0.5em; }
+
 #search-results dd { margin-bottom: 1em; padding-left: 20px; margin-left:0px; }
 
 div#search-results-counts { display: block; padding-left: 0; margin-left: 0; }