diff --git a/CHANGELOG b/CHANGELOG index ef98fc8..c058237 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +0.0.6 (2012-05-30): + * patched to work with redmine 2.0 + * UI updated to enforce breakline properly utilised 0.0.5 (2011-01-23): * added js exapnd all button * Fixed missing spent time link diff --git a/README.rdoc b/README.rdoc index 23f893f..6b206ce 100644 --- a/README.rdoc +++ b/README.rdoc @@ -11,13 +11,14 @@ propagates the tree view to the project show page's subprojects list. * Anton-zaytsev * Shadowbq * cforce +* danmunn ==Changelog For the complete changelog see the CHANGELOG-file in the Projects Tree View plugin directory. ==Latest stable release -The currently available, latest stable release of the plugin is version 0.0.3. +The currently available, latest stable release of the plugin is version 0.0.6. ==Compatibility diff --git a/app/views/admin/projects.rhtml b/app/views/admin/projects.rhtml deleted file mode 100644 index 38a9f3b..0000000 --- a/app/views/admin/projects.rhtml +++ /dev/null @@ -1,97 +0,0 @@ -
-<%= link_to l(:label_project_new), {:controller => 'projects', :action => 'new'}, :class => 'icon icon-add' %> -
- -

<%=l(:label_project_plural)%>

- -<% form_tag({}, :method => :get) do %> -
<%= l(:label_filter_plural) %> - -<%= select_tag 'status', project_status_options_for_select(@status), :class => "small", :onchange => "this.form.submit(); return false;" %> - -<%= text_field_tag 'name', params[:name], :size => 30 %> -<%= submit_tag l(:button_apply), :class => "small", :name => nil %> -
-<% end %> -  - -
- - - - - - - - - -<% ancestors = [] %> -<% for project in @projects %> - <% rowid = "" %> - <% classes = "" %> - <% spanicon = "" %> - <% openonclick = "" %> - <% showchildren = false %> - <% project_id_lsd = "%04d" % project.id %> - <% project.children.each do |child| %> - <% if @projects.include?(child) %> - <% showchildren = true %> - <% break %> - <% end %> - <% end %> - <% if(!project.children.empty? && showchildren) %> - <% classes += " closed parent " + cycle("odd", "even") %> - <% rowid = "id=\""+project_id_lsd+"span\"" %> - <% openonclick = "onclick=\"showHide('"+project_id_lsd+"','"+project_id_lsd+"span')\""%> - <% spanicon = "  " %> - <% else %> - <% classes += " child" %> - <% end %> - <% if(project.parent_id == nil) %> - <% ancestors.clear %> - <% ancestors << project.id %> - <% else %> - <% while (ancestors.any? && !(project.parent_id == ancestors.last)) %> - <% ancestors.pop %> - <% end %> - <% classes += " hide" %> - <% if( !(ancestors.detect {|pid| pid == project.parent_id })) %> - <% prvclasses = "closed show parent " + cycle("odd", "even") %> - <% ancestors.each do |pid| %> - <% prvclasses += " " + "%04d" % pid %> - <% end %> - <% project_parent_id_lsd = "%04d" % project.parent.id %> - <% openonclick = "onclick=\"showHide('"+project_parent_id_lsd+"','"+project_parent_id_lsd+"span')\"" %> - " > - - - - - <% ancestors << project.parent_id %> - <% end %> - <% ancestors.each do |pid| %> - <% classes += " " + "%04d" % pid %> - <% end %> - <% ancestors << project.id %> - <% end %> - > - - - - - - -<% end %> - -
<%=l(:label_project)%><%=l(:field_description)%><%=l(:field_is_public)%><%=l(:field_created_on)%>
<%= "" %><%="  " %><%= h("") %> class="empty">  >Project is private.
<%= "" %><%= spanicon %><%= project.active? ? link_to(h(project.name), {:controller => 'projects', :action => 'show', :id => project}, :class => "project") : h(project.name) %> ><%= textilizable project.short_description, :project => project %><%= image_tag 'true.png' if project.is_public? %><%= format_date(project.created_on) %> - <%= link_to(l(:button_archive), { :controller => 'projects', :action => 'archive', :id => project, :status => params[:status] }, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-lock') if project.active? %> - <%= link_to(l(:button_unarchive), { :controller => 'projects', :action => 'unarchive', :id => project, :status => params[:status] }, :method => :post, :class => 'icon icon-unlock') if !project.active? && (project.parent.nil? || project.parent.active?) %> - <%= link_to(l(:button_copy), { :controller => 'projects', :action => 'copy', :id => project }, :class => 'icon icon-copy') %> - <%= link_to(l(:button_delete), project_destroy_confirm_path(project), :class => 'icon icon-del') %> -
- -<%=l(:expand_all)%> - -
- -<% html_title(l(:label_project_plural)) -%> diff --git a/app/views/projects/index.html.erb b/app/views/projects/index.html.erb new file mode 100644 index 0000000..c6b0799 --- /dev/null +++ b/app/views/projects/index.html.erb @@ -0,0 +1,74 @@ +<% content_for :header_tags do %> + <%= javascript_include_tag 'projects_tree_view', :plugin => 'projects_tree_view' %> + <%= stylesheet_link_tag 'projects_tree_view', :plugin => 'projects_tree_view' %> + <%= auto_discovery_link_tag(:atom, {:action => 'index', :format => 'atom', :key => User.current.rss_key}) %> +<% end %> + +
+ <%= link_to(l(:label_project_new), {:controller => 'projects', :action => 'new'}, :class => 'icon icon-add') + ' |' if User.current.allowed_to?(:add_project, nil, :global => true) %> + <%= link_to(l(:label_issue_view_all), { :controller => 'issues' }) + ' |' if User.current.allowed_to?(:view_issues, nil, :global => true) %> + <%= link_to(l(:label_overall_spent_time), time_entries_path) + ' |' if User.current.allowed_to?(:view_time_entries, nil, :global => true) %> + <%= link_to l(:label_overall_activity), { :controller => 'activities', :action => 'index', :id => nil } %> +
+ +

<%= l(:label_project_plural)%>

+ +

+<%= link_to(l(:expand_all), "#", :onclick => 'expandAll()')%> / <%= link_to l(:collapse_all), "#", :onclick => 'collapseAll()' %> +

+ + + <% show_project_progress = Setting.plugin_projects_tree_view['show_project_progress'] %> + + + + + + <% if show_project_progress %> + + <% end %> + + + + + <% ancestors = [] %> + <% plevel = 0 %> + <% project_tree(@projects) do |project, level| %> + <% project_id = "%04d" % project.id %> + <% (plevel - level).times { ancestors.pop } if (level < plevel) %> + <% has_children = !project.children.empty? %> + "> + + + + <% if show_project_progress %> + + <% end %> + + + <% ancestors << project_id if has_children %> + <% plevel = level %> + <% end %> + +
<%= l(:label_project)%><%= l(:field_description)%><%= l(:field_go_to)%><%= l(:field_versions)%><%= l(:field_created_on)%>
+ <% if has_children %> + )">  + <% end %> + <%= project.active? ? link_to_project(project, {:action => 'show'}) : h(project.name) %> + "> <%= textilizable project.short_description.gsub(/\!.+\!/,""), :project => project %><%= favorite_project_modules_links(project) %><%= render_project_progress(project) %><%= format_date(project.created_on) %>
+ +

+<%= link_to(l(:expand_all), "#", :onclick => 'expandAll()')%> / <%= link_to l(:collapse_all), "#", :onclick => 'collapseAll()' %> +

+ +<% if User.current.logged? %> +

+<%= l(:label_my_projects) %> +

+<% end %> + +<% other_formats_links do |f| %> + <%= f.link_to 'Atom', :url => {:key => User.current.rss_key} %> +<% end %> + +<% html_title(l(:label_project_plural)) -%> diff --git a/app/views/projects/index.rhtml b/app/views/projects/index.rhtml deleted file mode 100644 index b3ebaea..0000000 --- a/app/views/projects/index.rhtml +++ /dev/null @@ -1,101 +0,0 @@ -<% content_for :header_tags do %> - <%= auto_discovery_link_tag(:atom, {:action => 'index', :format => 'atom', :key => User.current.rss_key}) %> -<% end %> -
- <% if authorize_global_implemented %> - <%= link_to(l(:label_project_new), {:controller => 'projects', :action => 'new'}, :class => 'icon icon-add') + ' |' if User.current.allowed_to?(:add_project, nil, :global => true) %> - <% else %> - <%= link_to(l(:label_project_new), {:controller => 'projects', :action => 'new'}, :class => 'icon icon-add') + ' |' if User.current.admin? %> - <% end %> - <%= link_to(l(:label_issue_view_all), { :controller => 'issues' }) + ' |' if User.current.allowed_to?(:view_issues, nil, :global => true) %> - <%= link_to(l(:label_overall_spent_time), { :controller => 'time_entries' }) + ' |' if User.current.allowed_to?(:view_time_entries, nil, :global => true) %> - <%= link_to l(:label_overall_activity), { :controller => 'activities', :action => 'index' }%> -
- -

<%=l(:label_project_plural)%>

- - - - - - - - - - - - - <% ancestors = [] %> - <% for project in @projects %> - <% rowid = "" %> - <% classes = "" %> - <% spanicon = "" %> - <% openonclick = "" %> - <% showchildren = false %> - <% project_id_lsd = "%04d" % project.id %> - <% project.children.each do |child| %> - <% if @projects.include?(child) %> - <% showchildren = true %> - <% break %> - <% end %> - <% end %> - <% if(!project.children.empty? && showchildren) %> - <% classes += " closed parent " + cycle("odd", "even") %> - <% rowid = "id=\""+project_id_lsd+"span\"" %> - <% openonclick = "onclick=\"showHide('"+project_id_lsd+"','"+project_id_lsd+"span')\""%> - <% spanicon = "  " %> - <% else %> - <% classes += " child" %> - <% end %> - <% if(project.parent_id == nil) %> - <% ancestors.clear %> - <% ancestors << project.id %> - <% else %> - <% while (ancestors.any? && !(project.parent_id == ancestors.last)) %> - <% ancestors.pop %> - <% end %> - <% classes += " hide" %> - <% if( !(ancestors.detect {|pid| pid == project.parent_id })) %> - <% prvclasses = "closed show parent " + cycle("odd", "even") %> - <% ancestors.each do |pid| %> - <% prvclasses += " " + "%04d" % pid %> - <% end %> - <% project_parent_id_lsd = "%04d" % project.parent.id %> - <% openonclick = "onclick=\"showHide('"+project_parent_id_lsd+"','"+project_parent_id_lsd+"span')\"" %> - " > - - - - - <% ancestors << project.parent_id %> - <% end %> - <% ancestors.each do |pid| %> - <% classes += " " + "%04d" % pid %> - <% end %> - <% ancestors << project.id %> - <% end %> - > - - - - - - - <% end %> - -
<%=l(:label_project)%><%=l(:field_description)%><%=l(:field_go_to)%><%=l(:field_versions)%><%=l(:field_created_on)%>
<%= "" %><%="  " %><%= h("") %> class="empty">  >Project is private.
<%= "" %><%= spanicon %><%= project.active? ? link_to(h(project.name), {:controller => 'projects', :action => 'show', :id => project}, :class => "project") : h(project.name) %> class="empty <%=User.current.member_of?(project) ? 'my-project' : nil%>">  ><%= textilizable project.short_description.gsub(/\!.+\!/,""), :project => project %><%= favorite_project_modules_links(project) %><%= format_date(project.created_on) %>
- -<%=l(:expand_all)%> - - -<% if User.current.logged? %> -

-<%= l(:label_my_projects) %> -

-<% end %> - -<% other_formats_links do |f| %> - <%= f.link_to 'Atom', :url => {:key => User.current.rss_key} %> -<% end %> - -<% html_title(l(:label_project_plural)) -%> diff --git a/app/views/settings/_project_tree_settings.html.erb b/app/views/settings/_project_tree_settings.html.erb new file mode 100644 index 0000000..fb7087e --- /dev/null +++ b/app/views/settings/_project_tree_settings.html.erb @@ -0,0 +1,4 @@ +

+ <%= content_tag(:label, l(:show_progress)) %> + <%= check_box_tag('settings[show_project_progress]', true, @settings['show_project_progress'])%> +

diff --git a/assets/javascripts/projects_tree_view.js b/assets/javascripts/projects_tree_view.js index 5f11259..3ff6fbc 100644 --- a/assets/javascripts/projects_tree_view.js +++ b/assets/javascripts/projects_tree_view.js @@ -1,104 +1,69 @@ /* Function to allow the projects to show up as a tree */ - Event.observe(window, 'load', function() { - if ($('expand_all')) { - $('expand_all').observe('click', function() { - $$('table.list tr').each(function(e) { e.addClassName('open'); e.removeClassName('hide'); }); - }); - } - }); +function toggleOddEven() { + var isEven = false; + $('table.list tr.project:not(.hide)').each(function() { + var e = $(this); + e.removeClass('odd'); + e.removeClass('even'); + e.addClass(isEven ? 'even' : 'odd'); + isEven = !isEven; + }) +} + +function expandProjectTree(id) { + $('table.list tr.child.' + id).each(function() { + var e = $(this); + e.removeClass('hide'); + if (e.hasClass('open')) { + expandProjectTree(e.context.id); + } + }) +} + +function collapseProjectTree(id) { + $('table.list tr.child.' + id).each(function() { + var e = $(this); + e.addClass('hide'); + collapseProjectTree(e.context.id); + }) +} + +function toggleShowHide(id) { + var e = $('#' + id); -function showHide(EL,PM) -{ - var els = document.getElementsByTagName('tr'); - var elsLen = els.length; - var pattern = new RegExp("(^|\\s)"+EL+"(\\s|$)"); - var cpattern = new RegExp("span"); - var expand = new RegExp("open"); - var collapse = new RegExp("closed"); - var hide = new RegExp("hide"); - var spanid = PM; - var classid = new RegExp("junk"); - var oddeventoggle = 0; - for (i = 0; i < elsLen; i++) - { - - if(cpattern.test(els[i].id)) - { - var tmpspanid = spanid; - var tmpclassid = classid; - spanid = els[i].id; - classid = spanid; - classid = classid.match(/(\w+)span/)[1]; - classid = new RegExp(classid); - if(tmpclassid.test(els[i].className) && (tmpspanid.toString() != PM.toString())) - { - if(collapse.test(document.getElementById(tmpspanid).className)) - { - spanid = tmpspanid; - classid = tmpclassid; - } - } - } - - if ( pattern.test(els[i].className) ) { + if (e.hasClass('open')) { + collapseProjectTree(id); + e.removeClass('open'); + } else { + expandProjectTree(id); + e.addClass('open'); + } - var cnames = els[i].className; - - cnames = cnames.replace(/hide/g,''); - - if (expand.test(document.getElementById(PM).className)) - { - cnames += ' hide'; - } - else - { - /* classid test function is buggy and matches incorrect ids 5 matches 50. */ - if((spanid.toString() != PM.toString()) && - (classid.test(els[i].className))) - { - if(collapse.test(document.getElementById(spanid).className)) - { - cnames += ' hide'; - } - } - } - - els[i].className = cnames; - - } - - if(!(hide.test(els[i].className))) - { - var cnames = els[i].className; - cnames = cnames.replace(/odd/g,''); - cnames = cnames.replace(/even/g,''); - - if(oddeventoggle == 0) - { - cnames += ' odd'; - } - else - { - cnames += ' even'; - } - - oddeventoggle ^= 1; - els[i].className = cnames; - } - } - if (collapse.test(document.getElementById(PM).className)) - { - var cnames = document.getElementById(PM).className; - cnames = cnames.replace(/closed/,'open'); - document.getElementById(PM).className = cnames; - } - else - { - var cnames = document.getElementById(PM).className; - cnames = cnames.replace(/open/,'closed'); - document.getElementById(PM).className = cnames; - } + toggleOddEven(); } +function expandAll() { + $('table.list tr.project').each(function() { + var e = $(this); + e.removeClass('hide'); + if (!e.hasClass('leaf')) { + e.addClass('open'); + } + }); + + toggleOddEven(); +} + +function collapseAll() { + $('table.list tr.project').each(function() { + var e = $(this); + e.removeClass('open'); + if (!e.hasClass('root')) { + e.addClass('hide'); + } + }); + + toggleOddEven(); +} diff --git a/assets/stylesheets/projects_tree_view.css b/assets/stylesheets/projects_tree_view.css index 6bf1e9a..44ade45 100644 --- a/assets/stylesheets/projects_tree_view.css +++ b/assets/stylesheets/projects_tree_view.css @@ -1,11 +1,9 @@ tr.parent { border: 1px solid #f8f8f8; } tr.parent td.name { white-space: nowrap; width: 300px; } -tr.child { border: 1px solid #f8f8f8; } -tr.child td.name { white-space: nowrap; width: 300px; } -tr.parent span.expander {background-image: url(../images/bullet_toggle_plus.png); padding-left: 8px; margin-left: 0; cursor: pointer;} -span.empty { text-align:right; width: 100%; cursor: pointer;} -tr.parent.open span.expander {background-image: url(../images/bullet_toggle_minus.png); cursor: pointer;} -tr.parent.open {background-color:#ffffbb;} -tr.hide { - display:none; - } +tr.child { border: 1px solid #f8f8f8; } +tr.child td.name { white-space: nowrap; width: 300px; } +tr.leaf td.name a { margin-left: 16px; } +tr.parent span.expander { background-image: url(../images/bullet_toggle_plus.png); padding-left: 8px; margin-left: 0; cursor: pointer; } +span.empty { text-align:right; width: 100%; cursor: pointer; } +tr.parent.open span.expander { background-image: url(../images/bullet_toggle_minus.png); cursor: pointer; } +tr.hide { display:none; } diff --git a/config/locales/en.yml b/config/locales/en.yml index 04710ce..a9d3ada 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -5,3 +5,5 @@ en: field_go_to: Go to module subprojects: sub projects expand_all: "Expand All" + collapse_all: "Collapse All" + show_progress: "Show project progress" diff --git a/config/locales/ja.yml b/config/locales/ja.yml new file mode 100644 index 0000000..a2f9ffa --- /dev/null +++ b/config/locales/ja.yml @@ -0,0 +1,8 @@ +ja: + + field_versions: "バージョン" + field_go_to: "モジュール" + subprojects: "サブプロジェクト" + expand_all: "すべて表示する" + collapse_all: "サブプロジェクトを隠す" + show_progress: "プロジェクトの進捗を表示する" diff --git a/init.rb b/init.rb index eee09a0..a917d14 100644 --- a/init.rb +++ b/init.rb @@ -1,22 +1,22 @@ require 'redmine' +require 'projects_tree_view_projects_helper_patch' + # Patches to the Redmine core. -require 'dispatcher' -require 'projectstreeview_projects_helper_patch' +Rails.configuration.to_prepare do + require_dependency 'projects_helper' + ProjectsHelper.send(:include, ProjectsTreeView::ProjectsHelperPatch) +end Redmine::Plugin.register :projects_tree_view do name 'Projects Tree View plugin' - author 'Chris Peterson' + author 'Chris Peterson and Github community' description 'This is a Redmine plugin which will turn the projects page into a tree view' - version '0.0.4' -end - -class ProjectsTreeViewListener < Redmine::Hook::ViewListener + url 'https://github.com/cforce/projects_tree_view' + version '0.0.8' + requires_redmine :version_or_higher => '2.1.0' - # Adds javascript and stylesheet tags - def view_layouts_base_html_head(context) - javascript_include_tag('projects_tree_view', :plugin => :projects_tree_view) + - stylesheet_link_tag('projects_tree_view', :plugin => :projects_tree_view) - end - + settings :default => { + 'show_project_progress' => true + }, :partial => 'settings/project_tree_settings' end diff --git a/lib/projects_tree_view_projects_helper_patch.rb b/lib/projects_tree_view_projects_helper_patch.rb new file mode 100644 index 0000000..b154e54 --- /dev/null +++ b/lib/projects_tree_view_projects_helper_patch.rb @@ -0,0 +1,65 @@ +module ProjectsTreeView + module ProjectsHelperPatch + extend ActiveSupport::Concern + + module ClassMethods + end + + def render_project_progress(project) + s = '' + cond = project.project_condition(false) + + open_issues = Issue.visible.count(:include => [:project, :status, :tracker], :conditions => ["(#{cond}) AND #{IssueStatus.table_name}.is_closed=?", false]) + + if open_issues > 0 + issues_closed_pourcent = (1 - open_issues.to_f/project.issues.count) * 100 + s << "
Issues: " + + link_to("#{open_issues} open", :controller => 'issues', :action => 'index', :project_id => project, :set_filter => 1) + + " / #{project.issues.count} total
" + + progress_bar(issues_closed_pourcent, :width => '30em', :legend => '%0.0f%' % issues_closed_pourcent) + end + project_versions = project_open(project) + + unless project_versions.empty? + s << "
" + project_versions.reverse_each do |version| + unless version.completed? + s << "
" + link_to_version(version) + ": " + + link_to_if(version.open_issues_count > 0, l(:label_x_open_issues_abbr, :count => version.open_issues_count), :controller => 'issues', :action => 'index', :project_id => version.project, :status_id => 'o', :fixed_version_id => version, :set_filter => 1) + + " / " + link_to_if(version.closed_issues_count > 0, l(:label_x_closed_issues_abbr, :count => version.closed_issues_count), :controller => 'issues', :action => 'index', :project_id => version.project, :status_id => 'c', :fixed_version_id => version, :set_filter => 1) + ". " + s << due_date_distance_in_words(version.effective_date) if version.effective_date + s << "

" + + progress_bar([version.closed_pourcent, version.completed_pourcent], :width => '30em', :legend => ('%0.0f%' % version.completed_pourcent)) + end + end + s << "
" + end + s.html_safe + end + + def favorite_project_modules_links(project) + links = [] + menu_items_for(:project_menu, project) do |node| + links << link_to(extract_node_details(node, project)[0], extract_node_details(node, project)[1]) unless node.name == :overview + end + links.join(", ").html_safe + end + + def project_open(project) + trackers = project.trackers.find(:all, :order => 'position') + #retrieve_selected_tracker_ids(trackers, trackers.select {|t| t.is_in_roadmap?}) + with_subprojects = Setting.display_subprojects_issues? + project_ids = with_subprojects ? project.self_and_descendants.collect(&:id) : [project.id] + + versions = project.shared_versions || [] + versions += project.rolled_up_versions.visible if with_subprojects + versions = versions.uniq.sort + completed_versions = versions.select {|version| version.closed? || version.completed? } + versions -= completed_versions + + issues_by_version = {} + versions.reject! {|version| !project_ids.include?(version.project_id) && issues_by_version[version].blank?} + versions + end + end +end diff --git a/lib/projectstreeview_projects_helper_patch.rb b/lib/projectstreeview_projects_helper_patch.rb deleted file mode 100644 index 14e96d4..0000000 --- a/lib/projectstreeview_projects_helper_patch.rb +++ /dev/null @@ -1,67 +0,0 @@ -require_dependency 'projects_helper' - -module ProjectstreeviewProjectsHelperPatch - def self.included(base) # :nodoc: - base.extend(ClassMethods) - - base.send(:include, InstanceMethods) - end - - module ClassMethods - end - - module InstanceMethods - - ### - # Compatibility helpers - ### - - # Redmine Core trunk@r2734 (0.9-devel) - # Returns true if the method is defined, else it returns false - def users_by_role_implemented - return ProjectsController.method_defined?("users_by_role") - end - - # Redmine Core trunk@r2750 (0.9-devel) - # Returns true if the method is defined, else it returns false - def authorize_global_implemented - return ApplicationController.method_defined?("authorize_global") - end - - def render_project_progress(project) - s = '' - if project.issues.open.count > 0 - issues_closed_pourcent = (1 - project.issues.open.count.to_f/project.issues.count) * 100 - s << "
Issues: " + - link_to("#{project.issues.open.count} open", :controller => 'issues', :action => 'index', :project_id => project, :set_filter => 1) + - " / #{project.issues.count} total
" + - progress_bar(issues_closed_pourcent, :width => '30em', :legend => '%0.0f%' % issues_closed_pourcent) - end - unless project.versions.open.empty? - s << "
" - project.versions.open.reverse_each do |version| - unless version.completed? - s << link_to_version(version) + ": " + - link_to_if(version.open_issues_count > 0, l(:label_x_open_issues_abbr, :count => version.open_issues_count), :controller => 'issues', :action => 'index', :project_id => version.project, :status_id => 'o', :fixed_version_id => version, :set_filter => 1) + - " / " + link_to_if(version.closed_issues_count > 0, l(:label_x_closed_issues_abbr, :count => version.closed_issues_count), :controller => 'issues', :action => 'index', :project_id => version.project, :status_id => 'c', :fixed_version_id => version, :set_filter => 1) + "" + ". " - s << due_date_distance_in_words(version.effective_date) if version.effective_date - s << "
" + - progress_bar([version.closed_pourcent, version.completed_pourcent], :width => '30em', :legend => ('%0.0f%' % version.completed_pourcent)) - end - end - s << "
" - end - end - - def favorite_project_modules_links(project) - links = [] - menu_items_for(:project_menu, project) do |node| - links << link_to(extract_node_details(node, project)[0], extract_node_details(node, project)[1]) unless node.name == :overview - end - links.join(", ") - end - - - end # Close the module ProjectstreeviewProjectsHelperPatch::InstanceMethods -end # Close the module ProjectstreeviewProjectsHelperPatch -ProjectsHelper.send(:include, ProjectstreeviewProjectsHelperPatch)