Project

General

Profile

Feature #1330 » 1330-copy-wiki-page.patch

Takenori TAKAKI, 2023-07-20 08:08

View differences:

app/controllers/wiki_controller.rb
36 36
  before_action :find_wiki, :authorize
37 37
  before_action :find_existing_or_new_page, :only => [:show, :edit]
38 38
  before_action :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy, :destroy_version]
39
  before_action :find_copy_from, :only => [:show, :update]
39 40
  before_action :find_attachments, :only => [:preview]
40 41
  accept_api_auth :index, :show, :update, :destroy
41 42

  
......
63 64
  end
64 65

  
65 66
  def new
66
    @page = WikiPage.new(:wiki => @wiki, :title => params[:title])
67
    @page = WikiPage.new(:wiki => @wiki, :title => (params[:title] || params[:copy_from]))
67 68
    unless User.current.allowed_to?(:edit_wiki_pages, @project)
68 69
      render_403
69 70
      return
......
72 73
      @page.title = '' unless editable?
73 74
      @page.validate
74 75
      if @page.errors[:title].blank?
75
        path = project_wiki_page_path(@project, @page.title, :parent => params[:parent])
76
        if params[:copy_from]
77
          copy_to_project = Project.find(params[:copy_to_project_id])
78
          path = project_wiki_page_path(copy_to_project, @page.title, :parent => params[:parent], :copy_from => params[:copy_from], :copy_from_project_id => @project.id)
79
        else
80
          path = project_wiki_page_path(@project, @page.title, :parent => params[:parent])
81
        end
76 82
        respond_to do |format|
77 83
          format.html {redirect_to path}
78 84
          format.js   {render :js => "window.location = #{path.to_json}"}
79 85
        end
80 86
      end
87
    else
88
      if params[:copy_from]
89
        page_title_org = @page.title
90
        suffix = 1
91
        while @page.validate == false && @page.errors[:title].present?
92
          @page.title = page_title_org + "_#{suffix}"
93
          suffix += 1
94
        end
95
      end
81 96
    end
82 97
  end
83 98

  
......
136 151

  
137 152
    @content = @page.content_for_version(params[:version])
138 153
    @content ||= WikiContent.new(:page => @page)
154
    if @copy_from
155
      @content.text = @copy_from.content.try(:text)
156
    end
139 157
    @content.text = initial_page_content(@page) if @content.text.blank?
140 158
    # don't keep previous comment
141 159
    @content.comments = nil
......
179 197
    @content.author = User.current
180 198

  
181 199
    if @page.save_with_content(@content)
200
      if @copy_from && params[:copy_attachments]
201
        @page.attachments = @copy_from.attachments.collect do |attachment|
202
          attachment.copy(:container => @page)
203
        end
204
      end
182 205
      attachments = Attachment.attach_files(@page, params[:attachments] || (params[:wiki_page] && params[:wiki_page][:uploads]))
183 206
      render_attachment_warning_if_needed(@page)
184 207
      call_hook(:controller_wiki_edit_after_save, {:params => params, :page => @page})
......
373 396
    end
374 397
  end
375 398

  
399
  def find_copy_from
400
    @copy_from = if params[:copy_from_project_id] && params[:copy_from]
401
                   Project.find(params[:copy_from_project_id]).wiki.try(:find_page, params[:copy_from]) rescue nil
402
                 else
403
                   nil
404
                 end
405
  end
406

  
376 407
  def redirect_to_page(page)
377 408
    if page.project && page.project.visible?
378 409
      redirect_to :action => action_name, :project_id => page.project, :id => page.title
app/helpers/wiki_helper.rb
46 46
    end
47 47
  end
48 48

  
49
  def wiki_page_project_options_for_select(page)
50
    projects = Project.allowed_to(:add_wiki_pages).joins(:wiki).preload(:wiki).to_a
51
    projects.select! {|p| p.enabled_module_names.include?('wiki') }
52
    projects << page.project unless projects.include?(page.project)
53

  
54
    project_tree_options_for_select(projects, :selected => page.project)
55
  end
56

  
49 57
  def wiki_page_breadcrumb(page)
50 58
    breadcrumb(
51 59
      page.ancestors.reverse.collect do |parent|
app/views/wiki/_copy_modal.html.erb
1
<h3 class="title"><%=l(:label_wiki_page_copy)%></h3>
2

  
3
<%= labelled_form_for :page, @page,
4
            :url => project_copy_wiki_page_path(@project),
5
            :method => 'post',
6
            :remote => true do |f| %>
7

  
8
  <%= render_error_messages @page.errors.full_messages_for(:title) %>
9
  <%= hidden_field_tag 'copy_from_project_id', @project.id %>
10
  <%= hidden_field_tag 'copy_from', params[:copy_from] %>
11

  
12
  <div class="box tabular">
13
    <p>
14
      <label for="copy_to_project_id"><%=l(:label_project)%><span class="required"> *</span></label>
15
      <%= select_tag :copy_to_project_id, wiki_page_project_options_for_select(@page), :label => :label_project %></p>
16
    <p>
17
      <%= f.text_field :title, :name => 'title', :size => 60, :required => true %>
18
      <em class="info"><%= l(:text_unallowed_characters) %>: , . / ? ; : |</em>
19
    </p>
20
    <% if params[:parent].present? %>
21
    <p id="copy_parent_page">
22
      <label class="inline">
23
        <%= check_box_tag 'parent', params[:parent], true %>
24
        <%= l(:field_parent_title) %>: <%= params[:parent] %>
25
      </label>
26
    </p>
27
    <% end %>
28
  </div>
29
  <p class="buttons">
30
    <%= submit_tag l(:label_next), :name => nil %>
31
    <%= submit_tag l(:button_cancel), :name => nil, :onclick => "hideModal(this);", :type => 'button' %>
32
  </p>
33
<% end %>
34
<%= javascript_tag do %>
35
$('#copy_to_project_id').change(function() {
36
  if ($('#copy_from_project_id').val()==$(this).val()) {
37
    $('#copy_parent_page').show();
38
  }else{
39
    $('#copy_parent_page').hide();
40
  }
41
});
42
<% end %>
app/views/wiki/edit.html.erb
11 11
<%= hidden_field_tag 'section_hash', @section_hash %>
12 12
<% end %>
13 13
<%= error_messages_for 'content' %>
14
<%= hidden_field_tag 'copy_from_project_id', params[:copy_from_project_id] if params[:copy_from_project_id] %>
15
<%= hidden_field_tag 'copy_from', params[:copy_from] if params[:copy_from] %>
14 16

  
15 17
<div class="box tabular">
16 18
<%= text_area_tag 'content[text]', @text, :cols => 100, :rows => 25, :accesskey => accesskey(:edit),
......
34 36
<% end %>
35 37

  
36 38
<p><label><%= l(:field_comments) %></label><%= f.text_field :comments, :size => 120, :maxlength => 1024 %></p>
39
<% if @copy_from && @copy_from.attachments.any? %>
40
<p>
41
  <label for="copy_attachments"><%= l(:label_copy_attachments) %></label>
42
  <%= check_box_tag 'copy_attachments', '1', true %>
43
</p>
44
<% end %>
37 45
<fieldset>
38 46
<legend><%=l(:label_attachment_plural)%></legend>
39 47
<% if @page.attachments.any? && @page.safe_attribute?('deleted_attachment_ids') %>
app/views/wiki/new.js.erb
1
$('#ajax-modal').html('<%= escape_javascript(render :partial => 'wiki/new_modal') %>');
1
$('#ajax-modal').html('<%= escape_javascript(render :partial => params['copy_from'] ? 'wiki/copy_modal' : 'wiki/new_modal') %>');
2 2
showModal('ajax-modal', '600px');
app/views/wiki/show.html.erb
23 23

  
24 24
    <% if User.current.allowed_to?(:edit_wiki_pages, @project) %>
25 25
      <%= link_to l(:label_wiki_page_new), new_project_wiki_page_path(@project, :parent => @page.title), :remote => true, :class => 'icon icon-add' %>
26
      <%= 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' %>
26 27
    <% end %>
27 28
  <% end %>
28 29
</div>
config/locales/en.yml
857 857
  label_wiki_page: Wiki page
858 858
  label_wiki_page_plural: Wiki pages
859 859
  label_wiki_page_new: New wiki page
860
  label_wiki_page_copy: Copy wiki page
860 861
  label_index_by_title: Index by title
861 862
  label_index_by_date: Index by date
862 863
  label_current_version: Current version
config/locales/ja.yml
1199 1199
  mail_body_settings_updated: ! '下記の設定が変更されました:'
1200 1200
  field_remote_ip: IPアドレス
1201 1201
  label_wiki_page_new: 新しいWikiページ
1202
  label_wiki_page_copy: Wikiページのコピー
1202 1203
  label_relations: 関係
1203 1204
  button_filter: フィルタ
1204 1205
  mail_body_password_updated: パスワードが変更されました。
config/routes.rb
190 190
    end
191 191

  
192 192
    match 'wiki/index', :controller => 'wiki', :action => 'index', :via => :get
193
    match 'wiki/:copy_from/copy', :to => 'wiki#new', :as => 'copy_wiki_page', via: [:get, :post]
193 194
    resources :wiki, :except => [:index, :create], :as => 'wiki_page' do
194 195
      member do
195 196
        get 'rename'
test/functional/wiki_controller_test.rb
1279 1279
    assert_response :success
1280 1280
    assert_select 'head>meta[name="robots"]', false
1281 1281
  end
1282

  
1283
  def test_get_new_with_copy_from
1284
    @request.session[:user_id] = 2
1285

  
1286
    get :new, :params => {:project_id => 'ecookbook', :copy_from => 'CookBook_documentation'}
1287
    assert_response :success
1288
    assert_select 'input[name=?][value=?]', 'title', 'CookBook_documentation_1'
1289
  end
1290

  
1291
  def test_post_new_with_copy_from_should_redirect_to_edit_wity_copy_params
1292
    @request.session[:user_id] = 2
1293

  
1294
    post :new, :params => {:project_id => 'ecookbook', :title => 'CookBook documentation 1', :copy_from => 'CookBook_documentation', :copy_to_project_id => 'ecookbook'}
1295
    assert_redirected_to '/projects/ecookbook/wiki/CookBook_documentation_1?copy_from=CookBook_documentation&copy_from_project_id=1'
1296
  end
1297

  
1298
  def test_show_with_copy_from_should_copy_content
1299
    @request.session[:user_id] = 2
1300

  
1301
    get :show, :params => {:project_id => 1, :id => 'CookBook_documentation_1', :copy_from => 'CookBook_documentation', :copy_from_project_id => 1}
1302
    assert_response :success
1303
    assert_select 'textarea[name=?]', 'content[text]', :text => /h1. CookBook documentation/
1304
    assert_select 'textarea[name=?]', 'content[text]', :text => /{{child_pages}}/
1305
    assert_select 'textarea[name=?]', 'content[text]', :text => /Some updated \[\[documentation\]\] here with gzipped history/
1306
  end
1307

  
1308
  def test_update_with_copy_from_and_copy_attachments_should_copy_attachments
1309
    @request.session[:user_id] = 2
1310

  
1311
    assert_difference 'WikiPage.count' do
1312
      assert_difference 'WikiContent.count' do
1313
        assert_difference 'Attachment.count', 2 do
1314
          post :update, :params => {
1315
            :project_id => 1,
1316
            :id => 'CookBook_documentation_1',
1317
            :content => {
1318
              :comments => 'Copy Wiki Page',
1319
              :text => 'h1. CookBook documentation',
1320
              :varsion => 0
1321
            },
1322
            :copy_from => 'CookBook_documentation',
1323
            :copy_from_project_id => 1,
1324
            :copy_attachments => '1'
1325
          }
1326
        end
1327
      end
1328
    end
1329
  end
1282 1330
end
(1-1/3)