diff --git a/app/controllers/wiki_controller.rb b/app/controllers/wiki_controller.rb index 2669c60e6..36110ad3a 100644 --- a/app/controllers/wiki_controller.rb +++ b/app/controllers/wiki_controller.rb @@ -36,6 +36,7 @@ class WikiController < ApplicationController before_action :find_wiki, :authorize before_action :find_existing_or_new_page, :only => [:show, :edit] before_action :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy, :destroy_version] + before_action :find_copy_from, :only => [:show, :update] before_action :find_attachments, :only => [:preview] accept_api_auth :index, :show, :update, :destroy @@ -63,7 +64,7 @@ class WikiController < ApplicationController end def new - @page = WikiPage.new(:wiki => @wiki, :title => params[:title]) + @page = WikiPage.new(:wiki => @wiki, :title => (params[:title] || params[:copy_from])) unless User.current.allowed_to?(:edit_wiki_pages, @project) render_403 return @@ -72,12 +73,26 @@ class WikiController < ApplicationController @page.title = '' unless editable? @page.validate if @page.errors[:title].blank? - path = project_wiki_page_path(@project, @page.title, :parent => params[:parent]) + if params[:copy_from] + copy_to_project = Project.find(params[:copy_to_project_id]) + path = project_wiki_page_path(copy_to_project, @page.title, :parent => params[:parent], :copy_from => params[:copy_from], :copy_from_project_id => @project.id) + else + path = project_wiki_page_path(@project, @page.title, :parent => params[:parent]) + end respond_to do |format| format.html {redirect_to path} format.js {render :js => "window.location = #{path.to_json}"} end end + else + if params[:copy_from] + page_title_org = @page.title + suffix = 1 + while @page.validate == false && @page.errors[:title].present? + @page.title = page_title_org + "_#{suffix}" + suffix += 1 + end + end end end @@ -136,6 +151,9 @@ class WikiController < ApplicationController @content = @page.content_for_version(params[:version]) @content ||= WikiContent.new(:page => @page) + if @copy_from + @content.text = @copy_from.content.try(:text) + end @content.text = initial_page_content(@page) if @content.text.blank? # don't keep previous comment @content.comments = nil @@ -179,6 +197,11 @@ class WikiController < ApplicationController @content.author = User.current if @page.save_with_content(@content) + if @copy_from && params[:copy_attachments] + @page.attachments = @copy_from.attachments.collect do |attachment| + attachment.copy(:container => @page) + end + end attachments = Attachment.attach_files(@page, params[:attachments] || (params[:wiki_page] && params[:wiki_page][:uploads])) render_attachment_warning_if_needed(@page) call_hook(:controller_wiki_edit_after_save, {:params => params, :page => @page}) @@ -373,6 +396,14 @@ class WikiController < ApplicationController end end + def find_copy_from + @copy_from = if params[:copy_from_project_id] && params[:copy_from] + Project.find(params[:copy_from_project_id]).wiki.try(:find_page, params[:copy_from]) rescue nil + else + nil + end + end + def redirect_to_page(page) if page.project && page.project.visible? redirect_to :action => action_name, :project_id => page.project, :id => page.title diff --git a/app/helpers/wiki_helper.rb b/app/helpers/wiki_helper.rb index 0b5f3b8f4..730e9c773 100644 --- a/app/helpers/wiki_helper.rb +++ b/app/helpers/wiki_helper.rb @@ -46,6 +46,14 @@ module WikiHelper end end + def wiki_page_project_options_for_select(page) + projects = Project.allowed_to(:add_wiki_pages).joins(:wiki).preload(:wiki).to_a + projects.select! {|p| p.enabled_module_names.include?('wiki') } + projects << page.project unless projects.include?(page.project) + + project_tree_options_for_select(projects, :selected => page.project) + end + def wiki_page_breadcrumb(page) breadcrumb( page.ancestors.reverse.collect do |parent| diff --git a/app/views/wiki/_copy_modal.html.erb b/app/views/wiki/_copy_modal.html.erb new file mode 100644 index 000000000..a23a6c77e --- /dev/null +++ b/app/views/wiki/_copy_modal.html.erb @@ -0,0 +1,42 @@ +

<%=l(:label_wiki_page_copy)%>

+ +<%= labelled_form_for :page, @page, + :url => project_copy_wiki_page_path(@project), + :method => 'post', + :remote => true do |f| %> + + <%= render_error_messages @page.errors.full_messages_for(:title) %> + <%= hidden_field_tag 'copy_from_project_id', @project.id %> + <%= hidden_field_tag 'copy_from', params[:copy_from] %> + +
+

+ + <%= select_tag :copy_to_project_id, wiki_page_project_options_for_select(@page), :label => :label_project %>

+

+ <%= f.text_field :title, :name => 'title', :size => 60, :required => true %> + <%= l(:text_unallowed_characters) %>: , . / ? ; : | +

+ <% if params[:parent].present? %> +

+ +

+ <% end %> +
+

+ <%= submit_tag l(:label_next), :name => nil %> + <%= submit_tag l(:button_cancel), :name => nil, :onclick => "hideModal(this);", :type => 'button' %> +

+<% end %> +<%= javascript_tag do %> +$('#copy_to_project_id').change(function() { + if ($('#copy_from_project_id').val()==$(this).val()) { + $('#copy_parent_page').show(); + }else{ + $('#copy_parent_page').hide(); + } +}); +<% end %> diff --git a/app/views/wiki/edit.html.erb b/app/views/wiki/edit.html.erb index 7e9cf42af..fb82e873a 100644 --- a/app/views/wiki/edit.html.erb +++ b/app/views/wiki/edit.html.erb @@ -11,6 +11,8 @@ <%= hidden_field_tag 'section_hash', @section_hash %> <% end %> <%= error_messages_for 'content' %> +<%= hidden_field_tag 'copy_from_project_id', params[:copy_from_project_id] if params[:copy_from_project_id] %> +<%= hidden_field_tag 'copy_from', params[:copy_from] if params[:copy_from] %>
<%= text_area_tag 'content[text]', @text, :cols => 100, :rows => 25, :accesskey => accesskey(:edit), @@ -34,6 +36,12 @@ <% end %>

<%= f.text_field :comments, :size => 120, :maxlength => 1024 %>

+<% if @copy_from && @copy_from.attachments.any? %> +

+ + <%= check_box_tag 'copy_attachments', '1', true %> +

+<% end %>
<%=l(:label_attachment_plural)%> <% if @page.attachments.any? && @page.safe_attribute?('deleted_attachment_ids') %> diff --git a/app/views/wiki/new.js.erb b/app/views/wiki/new.js.erb index c12b35340..009e79cf8 100644 --- a/app/views/wiki/new.js.erb +++ b/app/views/wiki/new.js.erb @@ -1,2 +1,2 @@ -$('#ajax-modal').html('<%= escape_javascript(render :partial => 'wiki/new_modal') %>'); +$('#ajax-modal').html('<%= escape_javascript(render :partial => params['copy_from'] ? 'wiki/copy_modal' : 'wiki/new_modal') %>'); showModal('ajax-modal', '600px'); diff --git a/app/views/wiki/show.html.erb b/app/views/wiki/show.html.erb index 6a0245809..5405b04a5 100644 --- a/app/views/wiki/show.html.erb +++ b/app/views/wiki/show.html.erb @@ -23,6 +23,7 @@ <% if User.current.allowed_to?(:edit_wiki_pages, @project) %> <%= link_to l(:label_wiki_page_new), new_project_wiki_page_path(@project, :parent => @page.title), :remote => true, :class => 'icon icon-add' %> + <%= link_to l(:button_copy), project_copy_wiki_page_path(@project, :copy_from => @page.title, :parent => @page.parent.try(:title)), :remote => true, :class => 'icon icon-copy' %> <% end %> <% end %>
diff --git a/config/locales/en.yml b/config/locales/en.yml index 5397a521d..cedb01a36 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -857,6 +857,7 @@ en: label_wiki_page: Wiki page label_wiki_page_plural: Wiki pages label_wiki_page_new: New wiki page + label_wiki_page_copy: Copy wiki page label_index_by_title: Index by title label_index_by_date: Index by date label_current_version: Current version diff --git a/config/locales/ja.yml b/config/locales/ja.yml index aab7542a3..5925f10d7 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -1199,6 +1199,7 @@ ja: mail_body_settings_updated: ! '下記の設定が変更されました:' field_remote_ip: IPアドレス label_wiki_page_new: 新しいWikiページ + label_wiki_page_copy: Wikiページのコピー label_relations: 関係 button_filter: フィルタ mail_body_password_updated: パスワードが変更されました。 diff --git a/config/routes.rb b/config/routes.rb index 00eadf679..e10b2a819 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -190,6 +190,7 @@ Rails.application.routes.draw do end match 'wiki/index', :controller => 'wiki', :action => 'index', :via => :get + match 'wiki/:copy_from/copy', :to => 'wiki#new', :as => 'copy_wiki_page', via: [:get, :post] resources :wiki, :except => [:index, :create], :as => 'wiki_page' do member do get 'rename' diff --git a/test/functional/wiki_controller_test.rb b/test/functional/wiki_controller_test.rb index 3765ac867..51d5d7813 100644 --- a/test/functional/wiki_controller_test.rb +++ b/test/functional/wiki_controller_test.rb @@ -1279,4 +1279,52 @@ class WikiControllerTest < Redmine::ControllerTest assert_response :success assert_select 'head>meta[name="robots"]', false end + + def test_get_new_with_copy_from + @request.session[:user_id] = 2 + + get :new, :params => {:project_id => 'ecookbook', :copy_from => 'CookBook_documentation'} + assert_response :success + assert_select 'input[name=?][value=?]', 'title', 'CookBook_documentation_1' + end + + def test_post_new_with_copy_from_should_redirect_to_edit_wity_copy_params + @request.session[:user_id] = 2 + + post :new, :params => {:project_id => 'ecookbook', :title => 'CookBook documentation 1', :copy_from => 'CookBook_documentation', :copy_to_project_id => 'ecookbook'} + assert_redirected_to '/projects/ecookbook/wiki/CookBook_documentation_1?copy_from=CookBook_documentation©_from_project_id=1' + end + + def test_show_with_copy_from_should_copy_content + @request.session[:user_id] = 2 + + get :show, :params => {:project_id => 1, :id => 'CookBook_documentation_1', :copy_from => 'CookBook_documentation', :copy_from_project_id => 1} + assert_response :success + assert_select 'textarea[name=?]', 'content[text]', :text => /h1. CookBook documentation/ + assert_select 'textarea[name=?]', 'content[text]', :text => /{{child_pages}}/ + assert_select 'textarea[name=?]', 'content[text]', :text => /Some updated \[\[documentation\]\] here with gzipped history/ + end + + def test_update_with_copy_from_and_copy_attachments_should_copy_attachments + @request.session[:user_id] = 2 + + assert_difference 'WikiPage.count' do + assert_difference 'WikiContent.count' do + assert_difference 'Attachment.count', 2 do + post :update, :params => { + :project_id => 1, + :id => 'CookBook_documentation_1', + :content => { + :comments => 'Copy Wiki Page', + :text => 'h1. CookBook documentation', + :varsion => 0 + }, + :copy_from => 'CookBook_documentation', + :copy_from_project_id => 1, + :copy_attachments => '1' + } + end + end + end + end end