Merge pull request #560 from opf/bugfix/2363_with_main_item_selection

pull/577/head
Hagen Schink 11 years ago
commit fa94735246
  1. 3
      app/controllers/wiki_controller.rb
  2. 67
      app/controllers/wiki_menu_items_controller.rb
  3. 6
      app/models/project.rb
  4. 6
      app/models/wiki_menu_item.rb
  5. 11
      app/models/wiki_page.rb
  6. 45
      app/views/wiki_menu_items/select_main_menu_item.html.erb
  7. 1
      config/locales/de.yml
  8. 1
      config/locales/en.yml
  9. 2
      config/routes.rb
  10. 32
      features/step_definitions/wiki_menu_item_steps.rb
  11. 4
      features/wiki/wiki_index.feature
  12. 27
      features/wiki_menu_items/wiki_menu_items.feature
  13. 2
      lib/redmine.rb
  14. 28
      spec/controllers/wiki_controller_spec.rb
  15. 71
      spec/controllers/wiki_menu_items_controller_spec.rb
  16. 5
      spec/factories/wiki_menu_item_factory.rb
  17. 39
      spec/models/wiki_page_spec.rb

@ -303,7 +303,8 @@ class WikiController < ApplicationController
end
end
@page.destroy
redirect_to :action => 'index', :project_id => @project
redirect_to @wiki.pages.any? ? {:action => 'index', :project_id => @project} : project_path(@project)
end
# Export wiki to a single html file

@ -48,7 +48,13 @@ class WikiMenuItemsController < ApplicationController
get_data_from_params(params)
if wiki_menu_setting == 'no_item'
@wiki_menu_item.destroy unless @wiki_menu_item.nil?
unless @wiki_menu_item.nil?
if @wiki_menu_item.is_only_main_item?
redirect_to(select_main_menu_item_project_wiki_path(@project, @page.id)) and return
else
@wiki_menu_item.destroy
end
end
else
@wiki_menu_item.wiki_id = @page.wiki.id
@wiki_menu_item.name = params[:wiki_menu_item][:name]
@ -58,18 +64,7 @@ class WikiMenuItemsController < ApplicationController
@wiki_menu_item.parent_id = parent_wiki_menu_item
elsif wiki_menu_setting == 'main_item'
@wiki_menu_item.parent_id = nil
if params[:wiki_menu_item][:new_wiki_page] == "1"
@wiki_menu_item.new_wiki_page = true
elsif params[:wiki_menu_item][:new_wiki_page] == "0"
@wiki_menu_item.new_wiki_page = false
end
if params[:wiki_menu_item][:index_page] == "1"
@wiki_menu_item.index_page = true
elsif params[:wiki_menu_item][:index_page] == "0"
@wiki_menu_item.index_page = false
end
assign_wiki_menu_item_params @wiki_menu_item
end
end
@ -83,10 +78,27 @@ class WikiMenuItemsController < ApplicationController
end
end
def select_main_menu_item
wiki_page_title = params[:id]
@possible_wiki_pages = @project.wiki.pages.all(:include => :parent).reject{|page| page.title == wiki_page_title || page.menu_item.present? && page.menu_item.is_main_item?}
end
def replace_main_menu_item
current_page = WikiPage.find params[:id]
current_menu_item = current_page.menu_item
if page = WikiPage.find_by_id(params[:wiki_page][:id])
create_main_menu_item_for_wiki_page(page, current_menu_item.options)
end
current_menu_item.destroy
redirect_to action: :edit, id: current_page.title
end
private
def get_data_from_params(params)
@project = Project.find(params[:project_id])
@page_title = params[:id]
wiki_id = @project.wiki.id
@ -102,4 +114,31 @@ class WikiMenuItemsController < ApplicationController
@page.nearest_parent_menu_item(:is_main_item => true).try :id
end
end
def assign_wiki_menu_item_params(menu_item)
if params[:wiki_menu_item][:new_wiki_page] == "1"
menu_item.new_wiki_page = true
elsif params[:wiki_menu_item][:new_wiki_page] == "0"
menu_item.new_wiki_page = false
end
if params[:wiki_menu_item][:index_page] == "1"
menu_item.index_page = true
elsif params[:wiki_menu_item][:index_page] == "0"
menu_item.index_page = false
end
end
def create_main_menu_item_for_wiki_page(page, options={})
wiki = page.wiki
menu_item = if item = page.menu_item
item.tap {|item| item.parent_id = nil}
else
wiki.wiki_menu_items.build(title: page.title, name: page.pretty_title)
end
menu_item.options = options
menu_item.save
end
end

@ -718,6 +718,12 @@ class Project < ActiveRecord::Base
enabled_modules.collect(&:name)
end
def disable_module(module_name)
if module_enabled? module_name
self.enabled_module_names = enabled_module_names - [module_name.to_s]
end
end
safe_attributes 'name',
'description',
'summary',

@ -39,7 +39,7 @@ class WikiMenuItem < ActiveRecord::Base
:order => 'id ASC'}
}
attr_accessible :name, :title
attr_accessible :name, :title, :wiki_id
validates_presence_of :title
validates_format_of :title, :with => /\A[^,\.\/\?\;\|\:]*\z/
@ -84,4 +84,8 @@ class WikiMenuItem < ActiveRecord::Base
def is_sub_item?
!parent_id.nil?
end
def is_only_main_item?
self.class.main_items(wiki.id) == [self]
end
end

@ -67,10 +67,17 @@ class WikiPage < ActiveRecord::Base
:joins => "LEFT JOIN #{WikiContent.table_name} ON #{WikiContent.table_name}.page_id = #{WikiPage.table_name}.id"
}
scope :main_pages, lambda {|wiki_id|
{ conditions: {wiki_id: wiki_id, parent_id: nil} }
}
# Wiki pages that are protected by default
DEFAULT_PROTECTED_PAGES = %w(sidebar)
after_destroy :delete_wiki_menu_item
after_destroy do |wiki_page|
wiki_page.wiki.project.disable_module(:wiki) and wiki_page.wiki.destroy if is_only_wiki_page?
end
def check_and_mark_as_protected
if new_record? && DEFAULT_PROTECTED_PAGES.include?(title.to_s.downcase)
@ -249,6 +256,10 @@ class WikiPage < ActiveRecord::Base
def validate_same_project
errors.add(:parent_title, :not_same_project) if parent && (parent.wiki_id != wiki_id)
end
def is_only_wiki_page?
wiki.pages.reject {|page| page == self}.empty?
end
end
class WikiDiff < Redmine::Helpers::Diff

@ -0,0 +1,45 @@
<%#-- copyright
OpenProject is a project management system.
Copyright (C) 2012-2013 the OpenProject Foundation (OPF)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License version 3.
OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
Copyright (C) 2006-2013 Jean-Philippe Lang
Copyright (C) 2010-2013 the ChiliProject Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
See doc/COPYRIGHT.rdoc for more details.
++#%>
<h2><%= t(:label_select_main_menu_item) %></h2>
<%= labelled_tabular_form_for :wiki_page, url: { action: 'replace_main_menu_item' } do |f| %>
<div class="box">
<p>
<%= f.select :id,
"<option value=''></option>".html_safe + wiki_page_options_for_select(@possible_wiki_pages),
{label: WikiPage.human_attribute_name(:title) },
{size: "#{@possible_wiki_pages.size + 1}", id: 'main-menu-item-select'} %>
</p>
</div>
<%= submit_tag t(:button_save) %>
<% end %>

@ -601,6 +601,7 @@ de:
label_calendar: "Kalender"
label_calendar_show: "Kalender anzeigen"
label_category: "Kategorie"
label_select_main_menu_item: Neuen Hauptmenüpunkt auwählen
label_change_plural: "Änderungen"
label_change_properties: "Eigenschaften ändern"
label_change_status: "Statuswechsel"

@ -596,6 +596,7 @@ en:
label_calendar: "Calendar"
label_calendar_show: "Show Calendar"
label_category: "Category"
label_select_main_menu_item: Select new main menu item
label_change_plural: "Changes"
label_change_properties: "Change properties"
label_change_status: "Change status"

@ -201,6 +201,8 @@ OpenProject::Application.routes.draw do
post :protect
post :add_attachment
get :list_attachments
get :select_main_menu_item, to: 'wiki_menu_items#select_main_menu_item'
post :replace_main_menu_item, to: 'wiki_menu_items#replace_main_menu_item'
end
end
# as routes for index and show are swapped

@ -0,0 +1,32 @@
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2013 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See doc/COPYRIGHT.rdoc for more details.
#++
Given /^the wiki menu item of the wiki page "(.*?)" of project "(.*?)" has been deleted$/ do |item_name, project_name|
project = Project.find_by_name project_name
WikiPage.where(title: item_name, wiki_id: project.wiki.id).first.delete_wiki_menu_item
end

@ -64,7 +64,3 @@ Feature: Viewing the wiki index page
When I go to the wiki index page below the "ParentWikiPage" page of the project called "project1"
Then I should see "Index by title" within "#content"
And there should be no menu item selected

@ -29,13 +29,14 @@
Feature: Wiki menu items
Background:
Given there is 1 project with the following:
| name | Awesome Project |
| identifier | awesome-project |
| name | Awesome Project |
| identifier | awesome-project |
And there is a role "member"
And the role "member" may have the following rights:
| view_wiki_pages |
| edit_wiki_pages |
| manage_wiki_menu |
| view_wiki_pages |
| edit_wiki_pages |
| delete_wiki_pages |
| manage_wiki_menu |
And there is 1 user with the following:
| login | bob |
And the user "bob" is a "member" in the project "Awesome Project"
@ -116,3 +117,19 @@ Feature: Wiki menu items
And I choose "Do not show this wikipage in project navigation"
And I press "Save"
Then I should not see "Wiki" within "#main-menu"
@javascript
Scenario: When I delete the last wiki page with a menu item I can select a new menu item and the menu item is replaced
Given the project "Awesome Project" has a wiki menu item with the following:
| title | AwesomePage |
| name | AwesomePage |
And the wiki menu item of the wiki page "Wiki" of project "Awesome Project" has been deleted
When I go to the wiki page "AwesomePage" for the project called "Awesome Project"
And I click on "More functions"
And I click on "Configure menu item"
And I choose "Do not show this wikipage in project navigation"
And I press "Save"
And I select "Wiki" from "main-menu-item-select"
And I press "Save"
Then I should not see "AwesomePage" within "#main-menu"
Then I should see "Wiki" within "#main-menu"

@ -152,7 +152,7 @@ Redmine::AccessControl.map do |map|
map.project_module :wiki do |map|
map.permission :manage_wiki, {:wikis => [:edit, :destroy]}, :require => :member
map.permission :manage_wiki_menu, {:wiki_menu_items => [:edit, :update]}, :require => :member
map.permission :manage_wiki_menu, {:wiki_menu_items => [:edit, :update, :select_main_menu_item, :replace_main_menu_item]}, :require => :member
map.permission :rename_wiki_pages, {:wiki => :rename}, :require => :member
map.permission :change_wiki_parent_page, {:wiki => [:edit_parent_page, :update_parent_page]},
:require => :member

@ -49,7 +49,7 @@ describe WikiController do
# creating pages
@existing_page = FactoryGirl.create(:wiki_page, :wiki_id => @project.wiki.id,
:title => 'ExisitingPage')
:title => 'ExistingPage')
# creating page contents
FactoryGirl.create(:wiki_content, :page_id => @existing_page.id,
@ -187,7 +187,31 @@ describe WikiController do
end
end
end
end
describe 'destroy' do
describe 'successful action' do
context 'when it is not the only wiki page' do
let(:wiki) { @project.wiki }
before do
another_wiki_page = FactoryGirl.create :wiki_page, wiki: wiki
end
it 'redirects to wiki#index' do
delete :destroy, project_id: @project, id: @existing_page
response.should redirect_to action: 'index', project_id: @project
end
end
context 'when it is the only wiki page' do
it 'redirects to projects#show' do
delete :destroy, project_id: @project, id: @existing_page
response.should redirect_to project_path(@project)
end
end
end
end
end # describe 'actions'
describe 'view related stuff' do
render_views

@ -35,20 +35,8 @@ describe WikiMenuItemsController do
let(:project) { FactoryGirl.create(:project).reload } # a wiki is created for project, but the object doesn't know of it (FIXME?)
let(:wiki) { project.wiki }
# wiki pages
let(:wiki_page) { FactoryGirl.create(:wiki_page, :wiki => wiki) } # first wiki page without child pages
let!(:top_level_wiki_menu_item) { FactoryGirl.create(:wiki_menu_item, :wiki => wiki, :title => wiki_page.title) }
let(:another_wiki_page) { FactoryGirl.create(:wiki_page, :wiki => wiki) } # second wiki page with two child pages
let!(:another_wiki_page_top_level_wiki_menu_item) { FactoryGirl.create(:wiki_menu_item, :wiki => wiki, :title => another_wiki_page.title) }
# child pages of another_wiki_page
let(:child_page) { FactoryGirl.create(:wiki_page, :parent => another_wiki_page, :wiki => wiki) }
let!(:child_page_wiki_menu_item) { FactoryGirl.create(:wiki_menu_item, :wiki => wiki, :title => child_page.title) }
let(:another_child_page) { FactoryGirl.create(:wiki_page, :parent => another_wiki_page, :wiki => wiki) }
let!(:another_child_page_wiki_menu_item) { FactoryGirl.create(:wiki_menu_item, :wiki => wiki, :title => another_child_page.title, :parent => top_level_wiki_menu_item) }
let(:grand_child_page) { FactoryGirl.create(:wiki_page, :parent => child_page, :wiki => wiki) }
let!(:grand_child_page_wiki_menu_item) { FactoryGirl.create(:wiki_menu_item, :wiki => wiki, :title => grand_child_page.title) }
let!(:top_level_wiki_menu_item) { FactoryGirl.create(:wiki_menu_item, :with_menu_item_options, :wiki => wiki, :title => wiki_page.title) }
before :each do
# log in user
@ -56,6 +44,19 @@ describe WikiMenuItemsController do
end
describe :edit do
# more wiki pages with menu items
let(:another_wiki_page) { FactoryGirl.create(:wiki_page, :wiki => wiki) } # second wiki page with two child pages
let!(:another_wiki_page_top_level_wiki_menu_item) { FactoryGirl.create(:wiki_menu_item, :wiki => wiki, :title => another_wiki_page.title) }
# child pages of another_wiki_page
let(:child_page) { FactoryGirl.create(:wiki_page, :parent => another_wiki_page, :wiki => wiki) }
let!(:child_page_wiki_menu_item) { FactoryGirl.create(:wiki_menu_item, :wiki => wiki, :title => child_page.title) }
let(:another_child_page) { FactoryGirl.create(:wiki_page, :parent => another_wiki_page, :wiki => wiki) }
let!(:another_child_page_wiki_menu_item) { FactoryGirl.create(:wiki_menu_item, :wiki => wiki, :title => another_child_page.title, :parent => top_level_wiki_menu_item) }
let(:grand_child_page) { FactoryGirl.create(:wiki_page, :parent => child_page, :wiki => wiki) }
let!(:grand_child_page_wiki_menu_item) { FactoryGirl.create(:wiki_menu_item, :wiki => wiki, :title => grand_child_page.title) }
context 'when no parent wiki menu item has been configured yet' do
context 'and it is a child page' do
before { get :edit, project_id: project.id, id: child_page.title }
@ -91,4 +92,48 @@ describe WikiMenuItemsController do
end
end
end
shared_context 'when there is one more wiki page with a child page' do
let!(:another_wiki_page) { FactoryGirl.create(:wiki_page, :wiki => wiki) } # second wiki page with two child pages
let!(:child_page) { FactoryGirl.create(:wiki_page, :parent => another_wiki_page, :wiki => wiki) }
end
describe :select_main_menu_item do
include_context 'when there is one more wiki page with a child page'
before { get :select_main_menu_item, project_id: project, id: wiki_page.title }
subject { assigns['possible_wiki_pages'] }
context 'when selecting a new wiki page to replace the current main menu item' do
it { should include another_wiki_page }
it { should include child_page }
it { should_not include wiki_page }
end
end
describe :replace_main_menu_item do
include_context 'when there is one more wiki page with a child page'
let(:selected_page) { child_page }
let(:new_menu_item) { selected_page.menu_item }
before do
post :replace_main_menu_item, project_id: project,
id: wiki_page.id,
wiki_page: { id: selected_page.id }
end
it 'destroys the current wiki menu item' do
wiki_page.menu_item.should be_nil
end
it 'creates a new main menu item for the selected wiki page' do
selected_page.menu_item.should be_present
selected_page.menu_item.parent.should be_nil
end
it 'transfers the menu item options to the selected wiki page' do
new_menu_item.options.should == { index_page: true, new_wiki_page: true }
end
end
end

@ -32,5 +32,10 @@ FactoryGirl.define do
sequence(:name) {|n| "Item No. #{n}" }
sequence(:title) {|n| "Wiki Title #{n}" }
trait :with_menu_item_options do
index_page true
new_wiki_page true
end
end
end

@ -29,9 +29,11 @@
require 'spec_helper'
describe WikiPage do
let(:project) { FactoryGirl.create(:project).reload } # a wiki is created for project, but the object doesn't know of it (FIXME?)
let(:wiki) { project.wiki }
let(:wiki_page) { FactoryGirl.create(:wiki_page, :wiki => wiki) }
describe '#nearest_parent_menu_item' do
let(:wiki_page) { FactoryGirl.create(:wiki_page) }
let(:wiki) { wiki_page.wiki }
let!(:wiki_page_wiki_menu_item) { FactoryGirl.create(:wiki_menu_item, :wiki => wiki, :title => wiki_page.title) }
let(:child_page) { FactoryGirl.create(:wiki_page, :parent => wiki_page, :wiki => wiki) }
let!(:child_page_wiki_menu_item) { FactoryGirl.create(:wiki_menu_item, :wiki => wiki, :title => child_page.title, :parent => wiki_page_wiki_menu_item) }
@ -50,4 +52,37 @@ describe WikiPage do
end
end
end
describe '#destroy' do
context 'when the only wiki page is destroyed' do
before do
wiki_page.destroy
project.reload
end
it 'deactivates the wiki module' do
project.module_enabled?(:wiki).should be_false
end
it 'destroys the project wiki' do
project.wiki.should be_nil
end
end
context 'when one of two wiki pages is destroyed' do
before do
another_wiki_page = FactoryGirl.create(:wiki_page, :wiki => wiki)
wiki_page.destroy
project.reload
end
it 'does not deactivate the wiki module' do
project.module_enabled?(:wiki).should be_true
end
it 'does not destroy the project wiki' do
project.wiki.should be_present
end
end
end
end

Loading…
Cancel
Save