# HG changeset patch # User Chris Cannam # Date 1358946685 0 # Node ID 1b1138f6f55ee01ccaa3b80f40da04cd90b325d5 # Parent b9e34a051f82f5ae4e0e2dfff7825b20808b8905# Parent e60f4ccfdc70c5a8cb241c86f8e470fe3bf3f585 Merge from branch live diff -r b9e34a051f82 -r 1b1138f6f55e app/controllers/my_controller.rb --- a/app/controllers/my_controller.rb Wed Nov 21 17:56:50 2012 +0000 +++ b/app/controllers/my_controller.rb Wed Jan 23 13:11:25 2013 +0000 @@ -21,6 +21,7 @@ helper :issues helper :users helper :custom_fields + helper :projects BLOCKS = { 'issuesassignedtome' => :label_assigned_to_me_issues, 'issuesreportedbyme' => :label_reported_issues, @@ -30,11 +31,12 @@ 'tipoftheday' => :label_tipoftheday, 'calendar' => :label_calendar, 'documents' => :label_document_plural, - 'timelog' => :label_spent_time + 'timelog' => :label_spent_time, + 'myprojects' => :label_my_projects }.merge(Redmine::Views::MyPage::Block.additional_blocks).freeze - DEFAULT_LAYOUT = { 'left' => ['tipoftheday', 'activitymyprojects'], - 'right' => ['issueswatched'] + DEFAULT_LAYOUT = { 'left' => ['myprojects', 'activitymyprojects'], + 'right' => ['tipoftheday', 'issueswatched'] }.freeze verify :xhr => true, diff -r b9e34a051f82 -r 1b1138f6f55e app/controllers/projects_controller.rb --- a/app/controllers/projects_controller.rb Wed Nov 21 17:56:50 2012 +0000 +++ b/app/controllers/projects_controller.rb Wed Jan 23 13:11:25 2013 +0000 @@ -58,11 +58,6 @@ @project_pages = Paginator.new self, @project_count, @limit, params['page'] @offset ||= @project_pages.current.offset @projects = Project.visible_roots.all(:offset => @offset, :limit => @limit, :order => sort_clause) - if User.current.logged? - # seems sort_by gives us case-sensitive ordering, which we don't want -# @user_projects = User.current.projects.sort_by(&:name) - @user_projects = User.current.projects.all(:order => :name) - end render :template => 'projects/index.html.erb', :layout => !request.xhr? } format.api { diff -r b9e34a051f82 -r 1b1138f6f55e app/controllers/repositories_controller.rb --- a/app/controllers/repositories_controller.rb Wed Nov 21 17:56:50 2012 +0000 +++ b/app/controllers/repositories_controller.rb Wed Jan 23 13:11:25 2013 +0000 @@ -143,15 +143,14 @@ @content = @repository.cat(@path, @rev) (show_error_not_found; return) unless @content - if 'raw' == params[:format] || - (@content.size && @content.size > Setting.file_max_size_displayed.to_i.kilobyte) || - ! is_entry_text_data?(@content, @path) + if 'raw' == params[:format] # Force the download send_opt = { :filename => filename_for_content_disposition(@path.split('/').last) } send_type = Redmine::MimeType.of(@path) send_opt[:type] = send_type.to_s if send_type send_data @content, send_opt else + @display_raw = ((@content.size && @content.size > Setting.file_max_size_displayed.to_i.kilobyte) || !is_entry_text_data?(@content, @path)) # Prevent empty lines when displaying a file with Windows style eol # TODO: UTF-16 # Is this needs? AttachmentsController reads file simply. diff -r b9e34a051f82 -r 1b1138f6f55e app/helpers/activities_helper.rb --- a/app/helpers/activities_helper.rb Wed Nov 21 17:56:50 2012 +0000 +++ b/app/helpers/activities_helper.rb Wed Jan 23 13:11:25 2013 +0000 @@ -1,14 +1,52 @@ module ActivitiesHelper + def date_of_event(e) + if e.respond_to? :updated_at + e.updated_at + elsif e.respond_to? :updated_on + e.updated_on + elsif e.respond_to? :created_on + e.created_on + elsif e.respond_to? :committed_on + e.committed_on + else + nil + end + end + 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) + + # Score each project for which there are any events, by giving + # each event a score based on how long ago it was (the more recent + # the better). + + projhash = Hash.new + + events.each do |e| + if e.respond_to?(:project) + p = e.project + d = date_of_event e + if !d.nil? + dd = Date.parse d.to_s + age = Date.today - dd + score = (age < 14 ? 15-age : 1) + if projhash.key? p + projhash[p] += score + else + projhash[p] = score + end + end + end + end + + # pick N highest values and use cutoff value as selection threshold + threshold = projhash.values.sort.last(count).first + + # select projects above threshold and pick N from them randomly + busy = projhash.keys.select { |k| projhash[k] >= threshold }.sample(count) + + # return projects rather than just ids busy.map { |pid| Project.find(pid) } end diff -r b9e34a051f82 -r 1b1138f6f55e app/helpers/projects_helper.rb --- a/app/helpers/projects_helper.rb Wed Nov 21 17:56:50 2012 +0000 +++ b/app/helpers/projects_helper.rb Wed Jan 23 13:11:25 2013 +0000 @@ -269,4 +269,38 @@ sharing = 'none' unless Version::VERSION_SHARINGS.include?(sharing) l("label_version_sharing_#{sharing}") end + + def score_maturity(project) + nr_changes = (project.repository.nil? ? 0 : project.repository.changesets.count) + downloadables = [project.attachments, + project.versions.collect { |v| v.attachments }, + project.documents.collect { |d| d.attachments }].flatten + nr_downloadables = downloadables.count + nr_downloads = downloadables.map do |d| d.downloads end.sum + nr_members = project.members.count + nr_publications = if project.respond_to? :publications + then project.publications.count else 0 end + Math.log(1 + nr_changes) + + Math.log(1 + nr_downloadables) + + Math.log(1 + nr_downloads) + + Math.sqrt(nr_members > 1 ? (nr_members - 1) : 0) + + Math.sqrt(nr_publications) + end + + def all_maturity_scores() + phash = Hash.new + pp = Project.visible(User.anonymous) + pp.each do |p| + phash[p] = score_maturity p + end + phash + end + + def mature_projects(count) + phash = all_maturity_scores + scores = phash.values.sort + threshold = scores[scores.length / 2] + if threshold == 0 then threshold = 1 end + phash.keys.select { |k| phash[k] > threshold }.sample(count) + end end diff -r b9e34a051f82 -r 1b1138f6f55e app/views/activities/_busy.html.erb --- a/app/views/activities/_busy.html.erb Wed Nov 21 17:56:50 2012 +0000 +++ b/app/views/activities/_busy.html.erb Wed Jan 23 13:11:25 2013 +0000 @@ -1,7 +1,8 @@ <% events = @events_by_day %> <% if (events.nil?) activity = Redmine::Activity::Fetcher.new(User.anonymous) - events = activity.events(Date.today - 14, Date.today + 1) + days = Setting.activity_days_default.to_i + events = activity.events(Date.today - days, Date.today + 1) end %> @@ -31,11 +32,11 @@ <% 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 %> @@ -45,4 +46,5 @@ <% end %> + <% end %> diff -r b9e34a051f82 -r 1b1138f6f55e app/views/layouts/base.html.erb --- a/app/views/layouts/base.html.erb Wed Nov 21 17:56:50 2012 +0000 +++ b/app/views/layouts/base.html.erb Wed Jan 23 13:11:25 2013 +0000 @@ -64,6 +64,9 @@ <% unless page_header_title[1].empty? %> style="margin-top: 0px; " <% end %> + <% if !@project.nil? and @project.name.length > 35 %> + class="long-title" + <% end %> ><% if display_main_menu?(@project) %> <%= link_to_project(@project) %> <% else %> diff -r b9e34a051f82 -r 1b1138f6f55e app/views/my/blocks/_myprojects.html.erb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/views/my/blocks/_myprojects.html.erb Wed Jan 23 13:11:25 2013 +0000 @@ -0,0 +1,16 @@ +<% @user_projects = User.current.projects.all(:order => :name) %> + +<% if @user_projects.empty? %> +
<%= render :partial => 'link_to_functions' %>
-<%= render :partial => 'common/file', :locals => {:filename => @path, :content => @content} %> +<% if @display_raw %> + <% if @content.size && @content.size > Setting.file_max_size_displayed.to_i.kilobyte %> + <%= l(:text_data_too_large) %> + <% else %> + <%= l(:text_binary_data) %> + <% end %> +<% else %> + <%= render :partial => 'common/file', :locals => {:filename => @path, :content => @content} %> +<% end %> <% content_for :header_tags do %> <%= stylesheet_link_tag "scm" %> diff -r b9e34a051f82 -r 1b1138f6f55e app/views/welcome/index.html.erb --- a/app/views/welcome/index.html.erb Wed Nov 21 17:56:50 2012 +0000 +++ b/app/views/welcome/index.html.erb Wed Jan 23 13:11:25 2013 +0000 @@ -23,7 +23,7 @@You can replace the standard {{overview_link}} page for this project with your own welcome page.
This page will be editable using the project Wiki.
text_has_welcome_page_wiki_disabled: Note: You must enable the Wiki module in the {{modules_link}} tab before you can create or edit this page.
-
+ text_binary_data: Binary data
+ text_data_too_large: Binary data, or file too large to display
default_role_manager: Manager
default_role_developer: Developer
diff -r b9e34a051f82 -r 1b1138f6f55e extra/soundsoftware/reposman-soundsoftware.rb
--- a/extra/soundsoftware/reposman-soundsoftware.rb Wed Nov 21 17:56:50 2012 +0000
+++ b/extra/soundsoftware/reposman-soundsoftware.rb Wed Jan 23 13:11:25 2013 +0000
@@ -222,7 +222,7 @@
log('No project found, perhaps you forgot to "Enable WS for repository management"', :exit => true)
end
-log("retrieved #{projects.size} projects", :level => 1)
+log("found #{projects.size} projects at " + Time.now.inspect);
def set_owner_and_rights(project, repos_path, &block)
if mswin?
@@ -253,13 +253,13 @@
end
projects.each do |project|
- log("treating project #{project.name}", :level => 1)
+ log("inspecting project #{project.name}", :level => 1)
if project.identifier.empty?
- log("\tno identifier for project #{project.name}")
+ log("\tno identifier for project #{project.name}!")
next
elsif not project.identifier.match(/^[a-z0-9\-]+$/)
- log("\tinvalid identifier for project #{project.name} : #{project.identifier}");
+ log("\tinvalid identifier for project #{project.name} : #{project.identifier}!");
next;
end
@@ -282,31 +282,31 @@
if project.respond_to?(:repository)
repos_url = project.repository.url;
- log("\texisting url for project #{project.identifier} is #{repos_url}");
+ log("\texisting url for project #{project.identifier} is #{repos_url}", :level => 2);
if repos_url.match(/^file:\//) || repos_url.match(/^\//)
repos_url = repos_url.gsub(/^file:\/*/, "/");
- log("\tthis is a local file path, at #{repos_url}");
+ log("\tthis is a local file path, at #{repos_url}", :level => 2);
if repos_url.slice(0, $repos_base.length) != $repos_base
- log("\tit is in the wrong place: replacing it");
# leave repos_path set to our original suggestion
+ log("\tpreparing to replace incorrect repo location #{repos_url} for #{project.name} with #{repos_path}");
create_repos = true
else
if !File.directory?(repos_url)
- log("\tit doesn't exist; we should create it");
+ log("\tpreparing to create repo for #{project.name} at #{repos_url}");
repos_path = repos_url
create_repos = true
else
- log("\tit exists and is in the right place");
+ log("\tit exists and is in the right place", :level => 2);
end
end
else
- log("\tthis is a remote path, leaving alone");
+ log("\tthis is a remote path, leaving alone", :level => 2);
end
else
- log("\tproject #{project.identifier} has no repository registered")
+ log("\tpreparing to set repo location and create for #{project.name} at #{repos_url}")
# if File.directory?(repos_path)
# log("\trepository path #{repos_path} already exists, not creating")
# else
@@ -360,3 +360,5 @@
end
end
+log("project review completed at " + Time.now.inspect);
+
diff -r b9e34a051f82 -r 1b1138f6f55e public/stylesheets/application.css
--- a/public/stylesheets/application.css Wed Nov 21 17:56:50 2012 +0000
+++ b/public/stylesheets/application.css Wed Jan 23 13:11:25 2013 +0000
@@ -332,7 +332,7 @@
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 dt .time, div#news dt .time, .projects .latest .time, .projects .busy .managers { color: #777; font-size: 80%; }
div#activity dd .description, #search-results dd .description { font-style: italic; }
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; }
@@ -363,7 +363,7 @@
margin-left: 0;
}
-.projects .latest .title { margin-right: 0.5em; }
+.projects .latest .title, .projects .busy .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; }
@@ -414,12 +414,12 @@
ul.projects { margin: 0; padding-left: 1em; }
ul.projects.root { margin: 0; padding: 0; }
-ul.projects ul.projects { border-left: 3px solid #e0e0e0; }
+/*ul.projects ul.projects { border-left: 3px solid #e0e0e0; } */
ul.projects li.root { list-style-type:none; margin-bottom: 1em; }
-ul.projects li.child { list-style-type:none; margin-top: 1em;}
-ul.projects div.root a.project { font-weight: bold; font-size: 16px; margin: 0 0 10px 0; }
+ul.projects li.child { list-style-type:none; }
+ul.projects div.root a.project { font-weight: bold; }
-li.latest { margin-bottom: 0.5em; }
+li.latest, li.busy { margin-bottom: 0.5em; }
#tracker_project_ids ul { margin: 0; padding-left: 1em; }
#tracker_project_ids li { list-style-type:none; }
diff -r b9e34a051f82 -r 1b1138f6f55e public/themes/soundsoftware/stylesheets/application.css
--- a/public/themes/soundsoftware/stylesheets/application.css Wed Nov 21 17:56:50 2012 +0000
+++ b/public/themes/soundsoftware/stylesheets/application.css Wed Jan 23 13:11:25 2013 +0000
@@ -77,6 +77,8 @@
.odd {background-color:#fdf7e4;}
.even {background-color: #fdfaf0;}
+.box .more { margin-left: 40px; }
+
#content .tabs { margin-bottom: 0; }
table.list th { background-color: #fdfaf0; border-bottom: 1px solid #a9b680; }
@@ -96,7 +98,7 @@
table.projects .level2 .firstcol { padding-left: 2em; }
table.projects .level3 .firstcol { padding-left: 3em; }
-ul.projects .public, ul.projects .private { padding-left: 0.5em; color: #3e442c; font-size: 0.95em }
+ul.projects .public, ul.projects .private { padding-left: 0.5em; color: #3e442c; font-size: 0.9em }
table.files tr.active td { padding-top: 0.5em; padding-bottom: 0.5em; }
table.files .file .active { font-weight: bold; }
@@ -108,6 +110,7 @@
#header { position: absolute; z-index: 0; top: 0; width: 100%; background: #fdfbf5; border-bottom: 2px solid #a9b680; /* height:80px; */ padding: 20px 0 0.5em 0; margin-bottom: 0; }
#header a { color: #be5700; }
#header h1 { color: #525a38; margin-top: 25px; font-size: 3em; font-weight: normal; margin-left: 10px; }
+#header h1#project-title.long-title { font-size: 2em; line-height: 0.95em }
#header #project-title a, #header #project-title a:hover { color: #525a38; text-decoration: none; }
.header-general h1 {
background: url('soundsoftware-logo-code-title-only-transparent.png') no-repeat 0 0;
diff -r b9e34a051f82 -r 1b1138f6f55e vendor/plugins/redmine_bibliography/app/models/publication.rb
--- a/vendor/plugins/redmine_bibliography/app/models/publication.rb Wed Nov 21 17:56:50 2012 +0000
+++ b/vendor/plugins/redmine_bibliography/app/models/publication.rb Wed Jan 23 13:11:25 2013 +0000
@@ -19,6 +19,25 @@
before_save :set_initial_author_order
+ named_scope :visible, lambda {|*args| { :include => :projects,
+ :conditions => Project.allowed_to_condition(args.shift || User.current, :view_publication, *args) } }
+
+ acts_as_activity_provider :type => 'publication',
+ :timestamp => "#{Publication.table_name}.created_at",
+ :find_options => {
+ :include => :projects,
+ :conditions => "#{Project.table_name}.id = projects_publications.project_id"
+ }
+
+ acts_as_event :title => Proc.new {|o| o.title },
+ :datetime => :created_at,
+ :type => 'publications',
+ :author => nil,
+ #todo - need too move the cache from the helper to the model
+ :description => Proc.new {|o| o.print_entry(:ieee)},
+ :url => Proc.new {|o| {:controller => 'publications', :action => 'show', :id => o.id }}
+
+
# Ensure error message uses proper text instead of
# bibtex_entry.entry_type (#268). There has to be a better way to
# do this!
diff -r b9e34a051f82 -r 1b1138f6f55e vendor/plugins/redmine_bibliography/app/views/activities/_recent.html.erb
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vendor/plugins/redmine_bibliography/app/views/activities/_recent.html.erb Wed Jan 23 13:11:25 2013 +0000
@@ -0,0 +1,92 @@
+<% events = @events_by_day %>
+<% 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|
+
+ if e.class != Publication
+ user.member_of? e.project
+ else
+ e.projects.map {|p| user.member_of? p }.any?
+ end
+ }
+
+ end
+
+ events = events.first(max)
+
+ end
+%>
+
+
<%= l(:label_date_from_to, :start => format_date(@date_to - @days), :end => format_date(@date_to-1)) %>
+ +<% @activity.event_types.each do |t| %>
+<%= check_box_tag "show_#{t}", 1, @activity.scope.include?(t) %>
+
+
+<% end %>
<%= submit_tag l(:button_apply), :class => 'button-small', :name => nil %>
+<% end %> +<% end %> + +<% html_title(l(:label_activity), @author) -%> diff -r b9e34a051f82 -r 1b1138f6f55e vendor/plugins/redmine_bibliography/init.rb --- a/vendor/plugins/redmine_bibliography/init.rb Wed Nov 21 17:56:50 2012 +0000 +++ b/vendor/plugins/redmine_bibliography/init.rb Wed Jan 23 13:11:25 2013 +0000 @@ -40,15 +40,22 @@ settings :default => { 'menu' => 'Publications' }, :partial => 'settings/bibliography' project_module :redmine_bibliography do + permission :view_publication, {:publications => :show}, :public => :true permission :publications, { :publications => :index }, :public => true permission :edit_publication, {:publications => [:edit, :update]} permission :add_publication, {:publications => [:new, :create]} permission :delete_publication, {:publications => :destroy} + end # extending the Project Menu menu :project_menu, :publications, { :controller => 'publications', :action => 'index', :path => nil }, :after => :activity, :param => :project_id, :caption => Proc.new { Setting.plugin_redmine_bibliography['menu'] }, :if => Proc.new { !Setting.plugin_redmine_bibliography['menu'].blank? } + activity_provider :publication, :class_name => 'Publication', :default => true + end + + + diff -r b9e34a051f82 -r 1b1138f6f55e vendor/plugins/redmine_tags/app/views/projects/_my.html.erb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_tags/app/views/projects/_my.html.erb Wed Jan 23 13:11:25 2013 +0000 @@ -0,0 +1,1 @@ +<%= render_my_project_hierarchy_with_tags(@user_projects) %> diff -r b9e34a051f82 -r 1b1138f6f55e vendor/plugins/redmine_tags/app/views/projects/_tagcloud.html.erb --- a/vendor/plugins/redmine_tags/app/views/projects/_tagcloud.html.erb Wed Nov 21 17:56:50 2012 +0000 +++ b/vendor/plugins/redmine_tags/app/views/projects/_tagcloud.html.erb Wed Jan 23 13:11:25 2013 +0000 @@ -1,6 +1,6 @@ diff -r b9e34a051f82 -r 1b1138f6f55e vendor/plugins/redmine_tags/app/views/projects/index.html.erb --- a/vendor/plugins/redmine_tags/app/views/projects/index.html.erb Wed Nov 21 17:56:50 2012 +0000 +++ b/vendor/plugins/redmine_tags/app/views/projects/index.html.erb Wed Jan 23 13:11:25 2013 +0000 @@ -13,7 +13,9 @@ <% if User.current.logged? %> - <%= render :partial => 'my_projects' %> +