Skip to content

Commit c4106ad

Browse files
committed
Initial commit
0 parents  commit c4106ad

File tree

12 files changed

+275
-0
lines changed

12 files changed

+275
-0
lines changed

README.rdoc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
= redmine_copy_project
2+
3+
Description goes here

app/views/projects/copy.html.erb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<h2><%=l(:label_project_new)%></h2>
2+
3+
<%= labelled_form_for @project, :url => { :action => "copy" } do |f| %>
4+
<%= render :partial => 'form', :locals => { :f => f } %>
5+
6+
<fieldset class="box tabular"><legend><%= l(:button_copy) %></legend>
7+
<p>
8+
<label><%= l(:label_all_tasks_author) %></label><%= select_tag :issues_author, options_for_select([["<< #{l(:label_me)} >>", User.current.id]] + @source_project.members.map{ |x| [x.name, x.id]}) %>
9+
</p>
10+
<p>
11+
<label><%= l(:label_all_tasks_date) %></label><%= text_field_tag :issues_date, Time.zone.now.strftime('%Y-%m-%d') %><%= calendar_for('issues_task') %>
12+
</p>
13+
<label class="block"><%= check_box_tag 'only[]', 'members', true %> <%= l(:label_member_plural) %> (<%= @source_project.members.count %>)</label>
14+
<label class="block"><%= check_box_tag 'only[]', 'versions', true %> <%= l(:label_version_plural) %> (<%= @source_project.versions.count %>)</label>
15+
<label class="block"><%= check_box_tag 'only[]', 'issue_categories', true %> <%= l(:label_issue_category_plural) %> (<%= @source_project.issue_categories.count %>)</label>
16+
<label class="block"><%= check_box_tag 'only[]', 'issues', true %> <%= l(:label_issue_plural) %> (<%= @source_project.issues.count %>)</label>
17+
<label class="block"><%= check_box_tag 'only[]', 'queries', true %> <%= l(:label_query_plural) %> (<%= @source_project.queries.count %>)</label>
18+
<label class="block"><%= check_box_tag 'only[]', 'boards', true %> <%= l(:label_board_plural) %> (<%= @source_project.boards.count %>)</label>
19+
<label class="block"><%= check_box_tag 'only[]', 'wiki', true %> <%= l(:label_wiki_page_plural) %> (<%= @source_project.wiki.nil? ? 0 : @source_project.wiki.pages.count %>)</label>
20+
<%= hidden_field_tag 'only[]', '' %>
21+
<br />
22+
<label class="block"><%= check_box_tag 'notifications', 1, params[:notifications] %> <%= l(:label_project_copy_notifications) %></label>
23+
</fieldset>
24+
25+
<%= submit_tag l(:button_copy) %>
26+
<% end %>

app/views/projects/show.html.erb

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<div class="contextual">
2+
<% if User.current.allowed_to?(:add_subprojects, @project) %>
3+
<%= link_to l(:label_subproject_new), new_project_path(:parent_id => @project), :class => 'icon icon-add' %>
4+
<% end %>
5+
<% if User.current.allowed_to?(:copy_projects, @project) %>
6+
<%= link_to l(:button_copy), copy_project_path(@project), :class => 'icon icon-add' %>
7+
<% end %>
8+
<% if User.current.allowed_to?(:close_project, @project) %>
9+
<% if @project.active? %>
10+
<%= link_to l(:button_close), close_project_path(@project), :data => {:confirm => l(:text_are_you_sure)}, :method => :post, :class => 'icon icon-lock' %>
11+
<% else %>
12+
<%= link_to l(:button_reopen), reopen_project_path(@project), :data => {:confirm => l(:text_are_you_sure)}, :method => :post, :class => 'icon icon-unlock' %>
13+
<% end %>
14+
<% end %>
15+
</div>
16+
17+
<h2><%=l(:label_overview)%></h2>
18+
19+
<% unless @project.active? %>
20+
<p class="warning"><span class="icon icon-lock"><%= l(:text_project_closed) %></span></p>
21+
<% end %>
22+
23+
<div class="splitcontentleft">
24+
<% if @project.description.present? %>
25+
<div class="wiki">
26+
<%= textilizable @project.description %>
27+
</div>
28+
<% end %>
29+
<ul>
30+
<% unless @project.homepage.blank? %>
31+
<li><%=l(:field_homepage)%>: <%= link_to h(@project.homepage), @project.homepage %></li>
32+
<% end %>
33+
<% if @subprojects.any? %>
34+
<li><%=l(:label_subproject_plural)%>:
35+
<%= @subprojects.collect{|p| link_to p, project_path(p)}.join(", ").html_safe %></li>
36+
<% end %>
37+
<% @project.visible_custom_field_values.each do |custom_value| %>
38+
<% if !custom_value.value.blank? %>
39+
<li><%=h custom_value.custom_field.name %>: <%=h show_value(custom_value) %></li>
40+
<% end %>
41+
<% end %>
42+
</ul>
43+
44+
<% if User.current.allowed_to?(:view_issues, @project) %>
45+
<div class="issues box">
46+
<h3><%=l(:label_issue_tracking)%></h3>
47+
<ul>
48+
<% for tracker in @trackers %>
49+
<li><%= link_to h(tracker.name), project_issues_path(@project, :set_filter => 1, :tracker_id => tracker.id) %>:
50+
<%= l(:label_x_open_issues_abbr_on_total, :count => @open_issues_by_tracker[tracker].to_i,
51+
:total => @total_issues_by_tracker[tracker].to_i) %>
52+
</li>
53+
<% end %>
54+
</ul>
55+
<p>
56+
<%= link_to l(:label_issue_view_all), project_issues_path(@project, :set_filter => 1) %>
57+
<% if User.current.allowed_to?(:view_calendar, @project, :global => true) %>
58+
| <%= link_to l(:label_calendar), project_calendar_path(@project) %>
59+
<% end %>
60+
<% if User.current.allowed_to?(:view_gantt, @project, :global => true) %>
61+
| <%= link_to l(:label_gantt), project_gantt_path(@project) %>
62+
<% end %>
63+
</p>
64+
</div>
65+
<% end %>
66+
<%= call_hook(:view_projects_show_left, :project => @project) %>
67+
</div>
68+
69+
<div class="splitcontentright">
70+
<%= render :partial => 'members_box' %>
71+
72+
<% if @news.any? && authorize_for('news', 'index') %>
73+
<div class="news box">
74+
<h3><%=l(:label_news_latest)%></h3>
75+
<%= render :partial => 'news/news', :collection => @news %>
76+
<p><%= link_to l(:label_news_view_all), project_news_index_path(@project) %></p>
77+
</div>
78+
<% end %>
79+
<%= call_hook(:view_projects_show_right, :project => @project) %>
80+
</div>
81+
82+
<% content_for :sidebar do %>
83+
<% if @total_hours.present? %>
84+
<h3><%= l(:label_spent_time) %></h3>
85+
<p><span class="icon icon-time"><%= l_hours(@total_hours) %></span></p>
86+
<p>
87+
<% if User.current.allowed_to?(:log_time, @project) %>
88+
<%= link_to l(:button_log_time), new_project_time_entry_path(@project) %> |
89+
<% end %>
90+
<%= link_to(l(:label_details), project_time_entries_path(@project)) %> |
91+
<%= link_to(l(:label_report), report_project_time_entries_path(@project)) %></p>
92+
<% end %>
93+
<%= call_hook(:view_projects_show_sidebar_bottom, :project => @project) %>
94+
<% end %>
95+
96+
<% content_for :header_tags do %>
97+
<%= auto_discovery_link_tag(:atom, {:controller => 'activities', :action => 'index', :id => @project, :format => 'atom', :key => User.current.rss_key}) %>
98+
<% end %>
99+
100+
<% html_title(l(:label_overview)) -%>

config/locales/en.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
en:
2+
label_all_tasks_author: Author of all tasks
3+
label_all_tasks_date: Date of all tasks

config/locales/ru.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
ru:
2+
label_all_tasks_author: Автор всех задач
3+
label_all_tasks_date: Дата для всех задач

config/routes.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Plugin's routes
2+
# See: http://guides.rubyonrails.org/routing.html

init.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Redmine::Plugin.register :redmine_copy_projects do
2+
name 'Redmine Copy Projects plugin'
3+
author 'Redmine CRM'
4+
description 'Allows user to copy project'
5+
version '0.0.1'
6+
url 'http://redminecrm.com'
7+
author_url 'mailto:[email protected]'
8+
9+
permission :copy_projects, :projects => [:new, :create]
10+
11+
end
12+
13+
require 'redmine_copy_projects'

lib/redmine_copy_projects.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
ActionDispatch::Reloader.to_prepare do
2+
require_dependency 'redmine_copy_projects/patches/role_patch'
3+
require_dependency 'redmine_copy_projects/patches/projects_controller_patch'
4+
end
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
require_dependency 'role'
2+
3+
module RedmineCopyProjects
4+
module Patches
5+
6+
module ApplicationControllerPatch
7+
def self.included(base) # :nodoc:
8+
base.send(:include, InstanceMethods)
9+
base.class_eval do
10+
unloadable # Send unloadable so it will not be unloaded in development
11+
alias_method_chain :require_admin, :copy_projects
12+
end
13+
end
14+
end
15+
16+
module InstanceMethods
17+
def require_admin_with_copy_projects
18+
unless action_name == :show && controller_name == :projects && User.current.allowed_to(:copy_projects, nil)
19+
require_admin_without_copy_projects
20+
end
21+
end
22+
end
23+
24+
end
25+
end
26+
27+
unless ApplicationController.included_modules.include?(RedmineCopyProjects::Patches::ApplicationControllerPatch)
28+
ApplicationController.send(:include, RedmineCopyProjects::Patches::ApplicationControllerPatch)
29+
end
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
require_dependency 'role'
2+
3+
module RedmineCopyProjects
4+
module Patches
5+
6+
module ProjectsControllerPatch
7+
def self.included(base) # :nodoc:
8+
base.send(:include, InstanceMethods)
9+
base.class_eval do
10+
unloadable # Send unloadable so it will not be unloaded in development
11+
alias_method_chain :copy, :copy_projects
12+
skip_before_filter :require_admin, :only => [ :copy ]
13+
end
14+
end
15+
end
16+
17+
module InstanceMethods
18+
def copy_with_copy_projects
19+
@issue_custom_fields = IssueCustomField.sorted.all
20+
@trackers = Tracker.sorted.all
21+
@source_project = Project.find(params[:id])
22+
if request.get?
23+
@project = Project.copy_from(@source_project)
24+
@project.identifier = Project.next_identifier if Setting.sequential_project_identifiers?
25+
else
26+
Mailer.with_deliveries(params[:notifications] == '1') do
27+
@project = Project.new
28+
@project.safe_attributes = params[:project]
29+
if validate_parent_id && @project.copy(@source_project, :only => params[:only])
30+
if params[:issues_author] && params[:issues_date]
31+
author = User.find(params[:issues_author])
32+
@project.issues.each do |issue|
33+
issue.update_attributes(author: author, created_on: params[:issues_date])
34+
end
35+
end
36+
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
37+
flash[:notice] = l(:notice_successful_create)
38+
redirect_to settings_project_path(@project)
39+
elsif !@project.new_record?
40+
# Project was created
41+
# But some objects were not copied due to validation failures
42+
# (eg. issues from disabled trackers)
43+
# TODO: inform about that
44+
redirect_to settings_project_path(@project)
45+
end
46+
end
47+
end
48+
rescue ActiveRecord::RecordNotFound
49+
# source_project not found
50+
render_404
51+
end
52+
end
53+
54+
end
55+
end
56+
57+
unless ProjectsController.included_modules.include?(RedmineCopyProjects::Patches::ProjectsControllerPatch)
58+
ProjectsController.send(:include, RedmineCopyProjects::Patches::ProjectsControllerPatch)
59+
end

0 commit comments

Comments
 (0)