Merge branch 'release/3.0' into dev

pull/922/merge
Sebastian Schuster 11 years ago
commit 1c1cc3253a
  1. 10
      app/assets/javascripts/application.js.erb
  2. 46
      app/assets/javascripts/jquery.menu_expand.js
  3. 86
      app/assets/javascripts/select_list_move.js
  4. 32
      app/assets/javascripts/specific/main_menu.js.erb
  5. 8
      app/assets/stylesheets/content/_forms.css.sass
  6. 2
      app/controllers/api/v2/planning_elements_controller.rb
  7. 17
      app/helpers/application_helper.rb
  8. 2
      app/views/categories/destroy.html.erb
  9. 2
      app/views/layouts/base.html.erb
  10. 1
      app/views/my/_sidebar.html.erb
  11. 26
      app/views/queries/_columns.html.erb
  12. 8
      app/views/work_packages/_edit.html.erb
  13. 2
      config/locales/de.yml
  14. 2
      config/locales/en.yml
  15. 4
      doc/CHANGELOG.md
  16. 40
      spec/features/categories/categories_page.rb
  17. 78
      spec/features/categories/delete_spec.rb

@ -41,7 +41,6 @@
//= require jquery
//= require jquery.ui.all
//= require jquery-ui-i18n
//= require jquery.menu_expand
//= require jquery.atwho
//= require jquery_ujs
//= require jquery_noconflict
@ -135,6 +134,14 @@ jQuery(document).ready(function ($) {
$.datepicker.setDefaults(defaults);
}
$('#show_more_wp_properties').live('click', function(el){
$(this).find('.icon').toggleClass('icon-arrow-right6-3 icon-arrow-right6-1');
Effect.toggle("work_package_descr_fields", "appear", {duration:0.3});
enable_textarea_auto_completion(jQuery("#work_package_description"));
return false;
});
});
function checkAll (id, checked) {
@ -1272,6 +1279,7 @@ var activateFlash = function() {
flashMessage.show();
}
jQuery(document).ready(initMainMenuExpandStatus);
jQuery(document).ready(activateError);
jQuery(document).ready(function () {
activateFlash();

@ -1,46 +0,0 @@
//-- 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.
//++
/*
* Expands Redmine's current menu
*/
(function($) {
$.menu_expand = function(options) {
var opts = $.extend({
menu: '#main-menu',
selectedClass: '.selected'
}, options);
if (options.item !== undefined) {
options.item.toggleClass("open").siblings("ul").show();
}
else {
$(opts.menu +' '+ opts.selectedClass).toggleClass("open").siblings("ul").show();
}
}})(jQuery);

@ -26,82 +26,42 @@
// See doc/COPYRIGHT.rdoc for more details.
//++
var NS4 = (navigator.appName == "Netscape" && parseInt(navigator.appVersion) < 5);
function moveOptions(sourceId, destId) {
var sourceSelection = jQuery('#' + sourceId);
var destSelection = jQuery('#' + destId);
function addOption(theSel, theText, theValue)
{
var newOpt = new Option(theText, theValue);
var selLength = theSel.length;
theSel.options[selLength] = newOpt;
}
var selectedOptions = sourceSelection.find('option:selected');
function swapOptions(theSel, index1, index2)
{
var text, value;
text = theSel.options[index1].text;
value = theSel.options[index1].value;
theSel.options[index1].text = theSel.options[index2].text;
theSel.options[index1].value = theSel.options[index2].value;
theSel.options[index2].text = text;
theSel.options[index2].value = value;
}
selectedOptions.each(function() {
var option = jQuery('<option>', { value: this.value,
text: this.text });
function deleteOption(theSel, theIndex)
{
var selLength = theSel.length;
if(selLength>0)
{
theSel.options[theIndex] = null;
}
destSelection.append(option);
this.remove();
});
}
function moveOptions(theSelFrom, theSelTo)
{
var selLength = theSelFrom.length;
var selectedText = new Array();
var selectedValues = new Array();
var selectedCount = 0;
var i;
for(i=selLength-1; i>=0; i--)
{
if(theSelFrom.options[i].selected)
{
selectedText[selectedCount] = theSelFrom.options[i].text;
selectedValues[selectedCount] = theSelFrom.options[i].value;
deleteOption(theSelFrom, i);
selectedCount++;
}
function swapOptions(option1, option2) {
if (option1.length == 1 && option2.length == 1) {
option2.after(option1);
}
}
for(i=selectedCount-1; i>=0; i--)
{
addOption(theSelTo, selectedText[i], selectedValues[i]);
}
function moveOptionUp(selectionId) {
var selection = jQuery('#' + selectionId);
var selectedOptions = selection.find('option:selected');
if(NS4) history.go(0);
swapOptions(selectedOptions.prev(), selectedOptions);
}
function moveOptionUp(theSel) {
var index = theSel.selectedIndex;
if (index > 0) {
swapOptions(theSel, index-1, index);
theSel.selectedIndex = index-1;
}
}
function moveOptionDown(selectionId) {
var selection = jQuery('#' + selectionId);
var selectedOptions = selection.find('option:selected');
function moveOptionDown(theSel) {
var index = theSel.selectedIndex;
if (index < theSel.length - 1) {
swapOptions(theSel, index, index+1);
theSel.selectedIndex = index+1;
}
swapOptions(selectedOptions, selectedOptions.next());
}
function selectAllOptions(id)
{
function selectAllOptions(id) {
jQuery("#" + id + " option").attr('selected',true);
}

@ -1,8 +1,32 @@
function setExpandStatus(expanderObject) {
var expander = jQuery(expanderObject);
var menuItemWrapper = jQuery(expander).parent();
var expanded = jQuery(menuItemWrapper).hasClass('open');
var span = expander.find('span.hidden-for-sighted');
var title = expanded ? I18n.t('js.label_menu_collapse') : I18n.t('js.label_menu_expand');
expander.attr('title', title);
span.text(title);
}
function initMainMenuExpandStatus() {
jQuery('#main-menu .toggler').each(function(index) {
var menu_expander = jQuery(this);
var menu_item = menu_expander.closest('li').find('a.selected');
if (menu_item.length == 1) {
menu_expander.trigger('click');
} else {
setExpandStatus(menu_expander);
}
});
}
jQuery(document).ready(function($) {
// rejigger the main-menu sub-menu functionality.
$("#main-menu .toggler").remove(); // remove the togglers so they're inserted properly later.
var toggler = $('<a class="toggler"><span class="icon6 icon-toggler icon-arrow-right5-2"/><span class="hidden-for-sighted">' + I18n.t("js.label_menu_item_toggle") + '</span></a>')
var toggler = $('<a class="toggler"><span class="icon6 icon-toggler icon-arrow-right5-2"/><span class="hidden-for-sighted"></span></a>')
.click(function(event) {
var target = $(this);
@ -12,8 +36,13 @@ jQuery(document).ready(function($) {
menuParent.mySlide();
if (menuItemWrapper.hasClass('open')) {
menuParent.show();
menuParent.find('li > a:first').focus();
} else {
menuParent.hide();
}
setExpandStatus(target);
}
return false;
});
@ -28,7 +57,6 @@ jQuery(document).ready(function($) {
// 3. reinsert the <span class="toggler"> so that it sits outside of the above
.after(toggler);
// project menu
// Users of some old IEs are out of luck ATM. A userData implementation

@ -165,6 +165,14 @@
margin-bottom: 20px
padding: 30px 20px
legend.change_properties
padding-right: 20px
#show_more_wp_properties
float: left
margin-left: 115px
margin-top: -48px
background-color: $content_form_bg_color
hr.form_separator
border: 0
border-bottom: 1px solid $content_form_separator_color

@ -58,7 +58,7 @@ module Api
def create
@planning_element = @project.work_packages.build
@planning_element.update_attributes(permitted_params.planning_element)
@planning_element.update_attributes(permitted_params.planning_element.except :note)
# The planning_element inherits from workpackage, which requires an author.
# Using the current_user also satisfies this demand for API-calls

@ -178,20 +178,21 @@ module ApplicationHelper
#
def link_to_project(project, options={}, html_options = nil, show_icon = false)
link = ''
project_link_name = project.name
if show_icon && User.current.member_of?(project)
link << icon_wrapper("icon-context icon-star1",I18n.t(:description_my_project))
project_link_name = icon_wrapper("icon-context icon-star1",I18n.t(:description_my_project).html_safe + "&nbsp;".html_safe) + project_link_name
end
if project.active?
# backwards compatibility
if options.delete(:action) == 'settings'
link << link_to(project.name, settings_project_path(project, options), html_options)
link << link_to(project_link_name, settings_project_path(project, options), html_options)
else
link << link_to(project.name, project_path(project, options), html_options)
link << link_to(project_link_name, project_path(project, options), html_options)
end
else
link << project.name
link << project_link_name
end
link.html_safe
@ -1033,14 +1034,6 @@ module ApplicationHelper
end
end
# Expands the current menu item using JavaScript based on the params
def expand_current_menu
javascript_tag do
raw "jQuery.menu_expand({ item: jQuery('#main-menu .selected').parents('#main-menu li').last().find('a').first() });"
end
end
def disable_accessibility_css!
@accessibility_css_disabled = true
end

@ -29,7 +29,7 @@ See doc/COPYRIGHT.rdoc for more details.
<h2><%= Category.model_name.human %>: <%=h @category.name %></h2>
<%= form_tag({}) do %>
<%= form_tag({}, {:method => :delete}) do %>
<div class="box">
<p><strong><%= l(:text_work_package_category_destroy_question, @issue_count) %></strong></p>
<p><label><%= radio_button_tag 'todo', 'nullify', true %> <%= l(:text_work_package_category_destroy_assignments) %></label><br />

@ -105,8 +105,6 @@ See doc/COPYRIGHT.rdoc for more details.
</div>
</div>
</div>
<%= expand_current_menu %>
<% end %>
<% if show_decoration %>

@ -29,7 +29,6 @@ See doc/COPYRIGHT.rdoc for more details.
<% content_for :main_menu do %>
<%= render_menu :my_menu %>
<%= expand_current_menu %>
<% end %>
<h3><%=l(:label_my_account_data)%></h3>

@ -37,12 +37,14 @@ See doc/COPYRIGHT.rdoc for more details.
:multiple => true, :size => 10, :style => "width:150px" %>
</td>
<td class="table-buttons" align="center" valign="middle">
<input type="button" value="&#8594;"
onclick="moveOptions(this.form.available_columns, this.form.selected_columns);"
title="<%= l(:label_add_columns) %>"/><br />
<input type="button" value="&#8592;"
onclick="moveOptions(this.form.selected_columns, this.form.available_columns);"
title="<%= l(:label_remove_columns) %>" />
<%= link_to icon_wrapper('icon icon-arrow-right5', l(:label_add_columns)), {},
{ title: l(:label_add_columns),
onclick: "moveOptions('available_columns', 'selected_columns'); return false;" } %>
<br />
<%= link_to icon_wrapper('icon icon-arrow-right5-1', l(:label_remove_columns)), {},
{ title: l(:label_remove_columns),
style: "margin-right: 5px",
onclick: "moveOptions('selected_columns', 'available_columns'); return false;" } %>
</td>
<td>
<%= label_tag "selected_columns", l(:description_selected_columns) %>
@ -52,10 +54,14 @@ See doc/COPYRIGHT.rdoc for more details.
:id => 'selected_columns', :multiple => true, :size => 10, :style => "width:150px" %>
</td>
<td class="table-buttons" align="center" valign="middle">
<input type="button" value="&#8593;" onclick="moveOptionUp(this.form.selected_columns);"
title="<%= l(:label_sort_higher) %>" /><br />
<input type="button" value="&#8595;" onclick="moveOptionDown(this.form.selected_columns);"
title="<%= l(:label_sort_lower) %>" />
<%= link_to icon_wrapper('icon icon-arrow-right5-3', l(:label_sort_higher)), {},
{ title: l(:label_sort_higher),
onclick: "moveOptionUp('selected_columns'); return false;" } %>
<br />
<%= link_to icon_wrapper('icon icon-arrow-right5-2', l(:label_sort_lower)), {},
{ title: l(:label_sort_lower),
style: "margin-right: 3px",
onclick: "moveOptionDown('selected_columns'); return false;" } %>
</td>
</tr>
</table>

@ -40,14 +40,12 @@ See doc/COPYRIGHT.rdoc for more details.
<% if edit_allowed || !allowed_statuses.empty? %>
<fieldset class="tabular">
<legend>
<legend class="change_properties">
<%= l(:label_change_properties) %>
</legend>
<% if !work_package.new_record? && !work_package.errors.any? && edit_allowed %>
<small>
(<%= link_to l(:label_more), {}, :onclick => 'Effect.toggle("work_package_descr_fields", "appear", {duration:0.3}); enable_textarea_auto_completion(jQuery("#work_package_description")); return false;' %>)
</small>
<%= link_to icon_wrapper('icon icon-arrow-right6-3', l(:label_more)), {}, :title => l(:label_more), :class => 'no-decoration-on-hover', :id => 'show_more_wp_properties' %>
<% end %>
</legend>
<% edit_form = (edit_allowed ? 'form' : 'form_update') %>
<%= render :partial => edit_form,

@ -601,6 +601,8 @@ de:
label_collapse_all: "Alle zuklappen"
label_expand_all: "Alle aufklappen"
label_menu_item_toggle: "Untermenüpunkte ein-/ausblenden"
label_menu_collapse: "ausblenden"
label_menu_expand: "einblenden"
tl_toolbar:
zooms: "Zoomstufe"
outlines: "Hierarchie-Stufe"

@ -597,6 +597,8 @@ en:
label_collapse_all: "Collapse all"
label_expand_all: "Expand all"
label_menu_item_toggle: "Show/hide submenu items"
label_menu_collapse: "collapse"
label_menu_expand: "expand"
tl_toolbar:
zooms: "Zoom level"
outlines: "Hierarchy level"

@ -29,13 +29,17 @@ See doc/COPYRIGHT.rdoc for more details.
# Changelog
* `#1390` Fix: Deleting Issue Categories from a project - route not defined
* `#2701` Fix: [Groups] Error message not displayed correctly.
* `#3217` Fix: [Project settings] Page not found when adding/deleting members and clicking pagination
* `#3725` Fix: Trying to delete a Project without checking "Yes" results in Error
* `#3798` Fix: Typo leading to internal server error
* `#4105` Fix: Remove links from fieldset
* `#4123` Fix: [Accessibility] Link comprehensibility
* `#4175` Fix: Wrong escaping in destroy info
* `#4186` Long work package subject covers up edit buttons
* `#4245` When adding a block to MyPage the other blocks are gone
* `#4337` Fix: HTTP 500 when creating WP with note via API
* `#4654` Activity: Wrong id of work package when time spent
* `#4722` Wrong weekday in date picker
* `#4755` Wrong message "project identifier can't be edited"

@ -0,0 +1,40 @@
#-- 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.
#++
class CategoriesPage
include Rails.application.routes.url_helpers
include Capybara::DSL
def initialize(project=nil)
@project = project
end
def visit_settings
visit(settings_project_path(@project) + "/categories")
end
end

@ -0,0 +1,78 @@
#-- 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.
#++
require 'spec_helper'
require 'features/categories/categories_page'
describe 'Deletion' do
let(:current_user) { FactoryGirl.create :admin }
let(:category) { FactoryGirl.create :category }
let(:categories_page) { CategoriesPage.new(category.project) }
let(:delete_button) { 'div#tab-content-categories a.icon-delete' }
let(:confirm_deletion_button) { 'input[type="submit"]' }
before { User.stub(:current).and_return current_user }
shared_context 'delete category' do
before do
categories_page.visit_settings
expect(page).to have_selector(delete_button)
find(delete_button).click
end
end
shared_examples_for 'deleted category' do
it { expect(page).to have_selector('div#tab-content-categories p.nodata') }
it { expect(page).to have_no_selector(delete_button) }
end
describe 'w/o work package' do
include_context 'delete category'
it_behaves_like 'deleted category'
end
describe 'with work package' do
let!(:work_package) { FactoryGirl.create :work_package,
project: category.project,
category: category }
include_context 'delete category'
before do
expect(page).to have_selector(confirm_deletion_button)
find(confirm_deletion_button).click
end
it_behaves_like 'deleted category'
end
end
Loading…
Cancel
Save