Conflicts: app/controllers/api/v2/planning_elements_controller.rbpull/541/head
commit
30a4a008aa
@ -1,57 +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. |
|
||||||
#++ |
|
||||||
|
|
||||||
module Api |
|
||||||
module V2 |
|
||||||
|
|
||||||
class PlanningElementStatusesController < PlanningElementStatusesController |
|
||||||
unloadable |
|
||||||
helper :timelines |
|
||||||
|
|
||||||
include ::Api::V2::ApiController |
|
||||||
|
|
||||||
accept_key_auth :index, :show |
|
||||||
|
|
||||||
def index |
|
||||||
@planning_element_statuses = PlanningElementStatus.active |
|
||||||
respond_to do |format| |
|
||||||
format.api |
|
||||||
end |
|
||||||
end |
|
||||||
|
|
||||||
def show |
|
||||||
@planning_element_status = PlanningElementStatus.active.find(params[:id]) |
|
||||||
respond_to do |format| |
|
||||||
format.api |
|
||||||
end |
|
||||||
end |
|
||||||
end |
|
||||||
|
|
||||||
end |
|
||||||
end |
|
||||||
|
|
@ -1,50 +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. |
|
||||||
#++ |
|
||||||
|
|
||||||
class PlanningElementStatusesController < ApplicationController |
|
||||||
unloadable |
|
||||||
helper :timelines |
|
||||||
|
|
||||||
before_filter :disable_api |
|
||||||
|
|
||||||
accept_key_auth :index, :show |
|
||||||
|
|
||||||
def index |
|
||||||
@planning_element_statuses = PlanningElementStatus.active |
|
||||||
respond_to do |format| |
|
||||||
format.html { render_404 } |
|
||||||
end |
|
||||||
end |
|
||||||
|
|
||||||
def show |
|
||||||
@planning_element_status = PlanningElementStatus.active.find(params[:id]) |
|
||||||
respond_to do |format| |
|
||||||
format.html { render_404 } |
|
||||||
end |
|
||||||
end |
|
||||||
end |
|
@ -0,0 +1,97 @@ |
|||||||
|
#-- encoding: UTF-8 |
||||||
|
#-- 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. |
||||||
|
#++ |
||||||
|
module WorkPackage::AskBeforeDestruction |
||||||
|
extend ActiveSupport::Concern |
||||||
|
|
||||||
|
DestructionRegistration = Struct.new(:klass, :check, :action) |
||||||
|
|
||||||
|
def self.included(base) |
||||||
|
base.extend(ClassMethods) |
||||||
|
|
||||||
|
base.class_attribute :registered_associated_to_ask_before_destruction |
||||||
|
end |
||||||
|
|
||||||
|
module ClassMethods |
||||||
|
def cleanup_action_required_before_destructing?(work_packages) |
||||||
|
!associated_to_ask_before_destruction_of(work_packages).empty? |
||||||
|
end |
||||||
|
|
||||||
|
def cleanup_associated_before_destructing_if_required(work_packages, user, to_do = { :action => 'destroy' }) |
||||||
|
cleanup_required = cleanup_action_required_before_destructing?(work_packages) |
||||||
|
|
||||||
|
(!cleanup_required || |
||||||
|
(cleanup_required && |
||||||
|
cleanup_each_associated_class(work_packages, user, to_do))) |
||||||
|
end |
||||||
|
|
||||||
|
def associated_classes_to_address_before_destruction_of(work_packages) |
||||||
|
associated = [] |
||||||
|
|
||||||
|
registered_associated_to_ask_before_destruction.each do |registration| |
||||||
|
associated << registration.klass if registration.check.call(work_packages) |
||||||
|
end |
||||||
|
|
||||||
|
associated |
||||||
|
end |
||||||
|
|
||||||
|
private |
||||||
|
|
||||||
|
def associated_to_ask_before_destruction_of(work_packages) |
||||||
|
associated = {} |
||||||
|
|
||||||
|
registered_associated_to_ask_before_destruction.each do |registration| |
||||||
|
associated[registration.klass] = registration.action if registration.check.call(work_packages) |
||||||
|
end |
||||||
|
|
||||||
|
associated |
||||||
|
end |
||||||
|
|
||||||
|
def associated_to_ask_before_destruction(klass, check, action) |
||||||
|
self.registered_associated_to_ask_before_destruction ||= [] |
||||||
|
|
||||||
|
registration = DestructionRegistration.new(klass, check, action) |
||||||
|
|
||||||
|
self.registered_associated_to_ask_before_destruction << registration |
||||||
|
end |
||||||
|
|
||||||
|
def cleanup_each_associated_class(work_packages, user, to_do) |
||||||
|
ret = false |
||||||
|
|
||||||
|
self.transaction do |
||||||
|
associated_to_ask_before_destruction_of(work_packages).each do |klass, method| |
||||||
|
ret = method.call(work_packages, user, to_do) |
||||||
|
end |
||||||
|
|
||||||
|
raise ActiveRecord::Rollback unless ret |
||||||
|
end |
||||||
|
|
||||||
|
ret |
||||||
|
end |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,45 @@ |
|||||||
|
<h2><%= l(:label_confirmation) %></h2> |
||||||
|
|
||||||
|
<%= error_messages_for work_packages.first %> |
||||||
|
|
||||||
|
<%= form_tag work_packages_bulk_path, :method => :delete do %> |
||||||
|
<% work_packages.each do |work_package| %> |
||||||
|
<%= hidden_field_tag 'ids[]', work_package.id %> |
||||||
|
<% end %> |
||||||
|
|
||||||
|
<div class="box"> |
||||||
|
|
||||||
|
<%= work_package_associations_to_address(associated) %> |
||||||
|
|
||||||
|
<p class="bold"> |
||||||
|
<%= l(:text_destroy_what_to_do) %> |
||||||
|
</p> |
||||||
|
|
||||||
|
<%= fields_for :to_do do |f| %> |
||||||
|
<p> |
||||||
|
|
||||||
|
<%= f.radio_button 'action', 'destroy' %> |
||||||
|
<%= f.label 'action_destroy', l(:text_destroy) %> |
||||||
|
|
||||||
|
</p> |
||||||
|
<p> |
||||||
|
|
||||||
|
<%= f.radio_button 'action' , 'nullify' %> |
||||||
|
<%= f.label 'action_nullify', l(:text_assign_to_project) %> |
||||||
|
|
||||||
|
</p> |
||||||
|
<p> |
||||||
|
|
||||||
|
<%= f.radio_button 'action', 'reassign', :onclick => 'if(jQuery("#to_do_action_reassign").prop("checked")) { jQuery("#to_do_reassign_to_id").focus(); }' %> |
||||||
|
<%= f.label 'action_reassign', l(:text_reassign) %> |
||||||
|
|
||||||
|
<%= f.label 'reassign_to_id', l(:text_reassign_to) %> |
||||||
|
<%= f.text_field 'reassign_to_id', :value => params[:reassign_to_id], :size => 6, :onfocus => 'jQuery("#to_do_action_reassign").prop("checked", true);' %> |
||||||
|
|
||||||
|
</p> |
||||||
|
<% end %> |
||||||
|
</div> |
||||||
|
|
||||||
|
<%= submit_tag l(:button_apply) %> |
||||||
|
|
||||||
|
<% 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. |
||||||
|
#++ |
||||||
|
|
||||||
|
class MigrateRemainingCoreSettings < ActiveRecord::Migration |
||||||
|
REPLACED = { |
||||||
|
"tracker" => "type", |
||||||
|
"issue_status_updated" => "status_updated", |
||||||
|
"issue_status" => "status", |
||||||
|
"issue_field" => "field" |
||||||
|
} |
||||||
|
def self.up |
||||||
|
# Delete old plugin settings no longer needed |
||||||
|
ActiveRecord::Base.connection.execute <<-SQL |
||||||
|
DELETE FROM #{settings_table} |
||||||
|
WHERE name = #{quote_value('plugin_redmine_favicon')} |
||||||
|
OR name = #{quote_value('plugin_chiliproject_help_link')} |
||||||
|
SQL |
||||||
|
# Rename Tracker to Type |
||||||
|
Setting['work_package_list_default_columns'] = replace(Setting['work_package_list_default_columns'], REPLACED) |
||||||
|
# Rename IssueStatus in notified events |
||||||
|
Setting['notified_events'] = replace(Setting['notified_events'], REPLACED) |
||||||
|
# Rename IssueStatus and IssueField in work_package_done_ratio |
||||||
|
Setting['work_package_done_ratio'] = replace(Setting['work_package_done_ratio'], REPLACED) |
||||||
|
end |
||||||
|
|
||||||
|
def self.down |
||||||
|
# the above delete part is inherently not reversable |
||||||
|
# Rename Type to Tracker |
||||||
|
Setting['work_package_list_default_columns'] = replace(Setting['work_package_list_default_columns'], REPLACED.invert) |
||||||
|
# Rename Status to IssueStatus in notified events |
||||||
|
Setting['notified_events'] = replace(Setting['notified_events'], REPLACED.invert) |
||||||
|
# Rename back to IssueStatus and IssueField in work_package_done_ratio |
||||||
|
Setting['work_package_done_ratio'] = replace(Setting['work_package_done_ratio'], REPLACED.invert) |
||||||
|
end |
||||||
|
|
||||||
|
private |
||||||
|
|
||||||
|
def replace(value,mapping) |
||||||
|
if value.respond_to? :map |
||||||
|
value.map { |s| mapping[s].nil? ? s : mapping[s] } |
||||||
|
else |
||||||
|
mapping[value].nil? ? value : mapping[value] |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
def settings_table |
||||||
|
@settings_table ||= ActiveRecord::Base.connection.quote_table_name('settings') |
||||||
|
end |
||||||
|
|
||||||
|
def quote_value s |
||||||
|
ActiveRecord::Base.connection.quote(s) |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,157 @@ |
|||||||
|
#-- copyright |
||||||
|
# OpenProject is a project management system. |
||||||
|
# |
||||||
|
# Copyright (C) 2012-2013 the OpenProject Team |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License version 3. |
||||||
|
# |
||||||
|
# See doc/COPYRIGHT.rdoc for more details. |
||||||
|
#++ |
||||||
|
|
||||||
|
require_relative 'migration_utils/timelines' |
||||||
|
|
||||||
|
class MigrateTimelinesOptions < ActiveRecord::Migration |
||||||
|
include Migration::Utils |
||||||
|
|
||||||
|
COLUMN = 'options' |
||||||
|
|
||||||
|
OPTIONS = { |
||||||
|
# already done in 20131015064141_migrate_timelines_end_date_property_in_options.rb |
||||||
|
#'end_date' => 'due_date', |
||||||
|
'planning_element_types' => 'type', |
||||||
|
'project_type' => 'type', |
||||||
|
'project_status' => 'status', |
||||||
|
} |
||||||
|
|
||||||
|
def up |
||||||
|
say_with_time_silently "Check for historical comparisons" do |
||||||
|
comparisons = timelines_with_historical_comparisons |
||||||
|
|
||||||
|
unless comparisons.empty? |
||||||
|
affected_ids = comparisons.collect(&:id) |
||||||
|
|
||||||
|
raise "Error: Cannot migrate timelines options!"\ |
||||||
|
"\n\n"\ |
||||||
|
"Timelines exist that use historical comparison. This is not\n"\ |
||||||
|
"supported in future versions of timelines.\n\n"\ |
||||||
|
"The affected timelines ids are: #{affected_ids}\n\n"\ |
||||||
|
"You may use the rake task "\ |
||||||
|
"'migrations:timelines:remove_timelines_historical_comparison_from_options' "\ |
||||||
|
"to prepare the\n"\ |
||||||
|
"current schema for this migration."\ |
||||||
|
"\n\n\n" |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
say_with_time_silently "Update timelines options" do |
||||||
|
update_column_values('timelines', |
||||||
|
[COLUMN], |
||||||
|
update_options(migrate_timelines_options(OPTIONS, |
||||||
|
pe_id_map, |
||||||
|
pe_type_id_map)), |
||||||
|
nil) |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
def down |
||||||
|
say_with_time_silently "Restore timelines options" do |
||||||
|
update_column_values('timelines', |
||||||
|
[COLUMN], |
||||||
|
update_options(migrate_timelines_options(OPTIONS.invert, |
||||||
|
pe_id_map.invert, |
||||||
|
pe_type_id_map.invert)), |
||||||
|
nil) |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
private |
||||||
|
|
||||||
|
PE_TYPE_KEY = 'planning_element_types' |
||||||
|
PE_TIME_TYPE_KEY = 'planning_element_time_types' |
||||||
|
VERTICAL_PE_TYPES = 'vertical_planning_elements' |
||||||
|
|
||||||
|
def migrate_timelines_options(options, pe_id_map, pe_type_id_map) |
||||||
|
Proc.new do |timelines_opts| |
||||||
|
timelines_opts = rename_columns timelines_opts, options |
||||||
|
timelines_opts = migrate_planning_element_types timelines_opts, pe_type_id_map |
||||||
|
timelines_opts = migrate_planning_element_time_types timelines_opts, pe_type_id_map |
||||||
|
timelines_opts = migrate_vertical_planning_elements timelines_opts, pe_id_map |
||||||
|
|
||||||
|
timelines_opts |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
def migrate_planning_element_types(timelines_opts, pe_type_id_map) |
||||||
|
pe_types = [] |
||||||
|
|
||||||
|
pe_types = timelines_opts[PE_TYPE_KEY].delete_if { |t| t.nil? } if timelines_opts.has_key? PE_TYPE_KEY |
||||||
|
|
||||||
|
pe_types = pe_types.empty? ? new_ids_of_former_pes |
||||||
|
: pe_types.map { |p| pe_type_id_map[p] } |
||||||
|
|
||||||
|
timelines_opts[PE_TYPE_KEY] = pe_types |
||||||
|
|
||||||
|
timelines_opts |
||||||
|
end |
||||||
|
|
||||||
|
def migrate_planning_element_time_types(timelines_opts, pe_type_id_map) |
||||||
|
return timelines_opts unless timelines_opts.has_key? PE_TIME_TYPE_KEY |
||||||
|
|
||||||
|
pe_time_types = timelines_opts[PE_TIME_TYPE_KEY] |
||||||
|
|
||||||
|
pe_time_types.map! { |p| pe_type_id_map[p] } |
||||||
|
|
||||||
|
timelines_opts[PE_TIME_TYPE_KEY] = pe_time_types |
||||||
|
|
||||||
|
timelines_opts |
||||||
|
end |
||||||
|
|
||||||
|
def migrate_vertical_planning_elements(timelines_opts, pe_id_map) |
||||||
|
return timelines_opts unless timelines_opts.has_key? VERTICAL_PE_TYPES |
||||||
|
|
||||||
|
vertical_pes = timelines_opts[VERTICAL_PE_TYPES].split(',') |
||||||
|
.map { |p| p.strip } |
||||||
|
|
||||||
|
unless vertical_pes.empty? |
||||||
|
mapped_pes = vertical_pes.map { |v| pe_id_map[v] } |
||||||
|
.compact |
||||||
|
|
||||||
|
timelines_opts[VERTICAL_PE_TYPES] = mapped_pes.join(',') |
||||||
|
end |
||||||
|
|
||||||
|
timelines_opts |
||||||
|
end |
||||||
|
|
||||||
|
def new_ids_of_former_pes |
||||||
|
@new_ids_of_former_pes ||= pe_types_ids_with_new_ids.each_with_object([]) do |i, l| |
||||||
|
l << i['new_id'] |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
def pe_type_id_map |
||||||
|
@pe_type_id_map ||= pe_types_ids_with_new_ids.each_with_object({}) do |r, h| |
||||||
|
h[r['id']] = r['new_id'] |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
def pe_types_ids_with_new_ids |
||||||
|
select_all <<-SQL |
||||||
|
SELECT id, new_id |
||||||
|
FROM legacy_planning_element_types |
||||||
|
SQL |
||||||
|
end |
||||||
|
|
||||||
|
def pe_id_map |
||||||
|
@pe_id_map ||= pe_ids_with_new_ids.each_with_object({}) do |r, h| |
||||||
|
h[r['id']] = r['new_id'] |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
def pe_ids_with_new_ids |
||||||
|
select_all <<-SQL |
||||||
|
SELECT id, new_id |
||||||
|
FROM legacy_planning_elements |
||||||
|
SQL |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,66 @@ |
|||||||
|
#-- copyright |
||||||
|
# OpenProject is a project management system. |
||||||
|
# |
||||||
|
# Copyright (C) 2012-2013 the OpenProject Team |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License version 3. |
||||||
|
# |
||||||
|
# See doc/COPYRIGHT.rdoc for more details. |
||||||
|
#++ |
||||||
|
|
||||||
|
require 'yaml' |
||||||
|
|
||||||
|
require_relative 'utils' |
||||||
|
|
||||||
|
module Migration |
||||||
|
module Utils |
||||||
|
TimelineWithHistoricalComparison = Struct.new(:id, :from_date, :to_date) |
||||||
|
|
||||||
|
OPTIONS_COLUMN = 'options' |
||||||
|
HISTORICAL_DATE_FROM = 'compare_to_historical_one' |
||||||
|
HISTORICAL_DATE_TO = 'compare_to_historical_two' |
||||||
|
|
||||||
|
def timelines_with_historical_comparisons |
||||||
|
timelines = select_all <<-SQL |
||||||
|
SELECT id, options |
||||||
|
FROM timelines |
||||||
|
WHERE options LIKE '%comparison: historical%' |
||||||
|
SQL |
||||||
|
|
||||||
|
timelines.each_with_object([]) do |r, l| |
||||||
|
options = YAML.load(r[OPTIONS_COLUMN]) |
||||||
|
from_date = options[HISTORICAL_DATE_FROM] |
||||||
|
to_date = options[HISTORICAL_DATE_TO] |
||||||
|
|
||||||
|
l << TimelineWithHistoricalComparison.new(r['id'], from_date, to_date) |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
def update_options(callback) |
||||||
|
Proc.new do |row| |
||||||
|
timelines_opts = YAML.load(row[OPTIONS_COLUMN]) |
||||||
|
|
||||||
|
migrated_options = callback.call(timelines_opts.clone) unless callback.nil? |
||||||
|
|
||||||
|
row[OPTIONS_COLUMN] = YAML.dump(HashWithIndifferentAccess.new(migrated_options)) |
||||||
|
|
||||||
|
UpdateResult.new(row, true) |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
def rename_columns(timelines_opts, options) |
||||||
|
return timelines_opts unless timelines_opts.has_key? 'columns' |
||||||
|
|
||||||
|
columns = timelines_opts['columns'] |
||||||
|
|
||||||
|
columns.map! do |c| |
||||||
|
options.has_key?(c) ? options[c] : c |
||||||
|
end |
||||||
|
|
||||||
|
timelines_opts['columns'] = columns.uniq |
||||||
|
|
||||||
|
timelines_opts |
||||||
|
end |
||||||
|
end |
||||||
|
end |
Binary file not shown.
@ -1,29 +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. |
|
||||||
#++ |
|
||||||
|
|
||||||
InstanceFinder.register(PlanningElementStatus, Proc.new { |name| PlanningElementStatus.find_by_name(name) }) |
|
@ -0,0 +1,92 @@ |
|||||||
|
# encoding: utf-8 |
||||||
|
|
||||||
|
#-- 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 [Uu]ser "([^\"]*)" is a "([^\"]*)" (?:in|of) the [Pp]roject "([^\"]*)"$/ do |user, role, project| |
||||||
|
u = User.find_by_login(user) |
||||||
|
r = Role.find_by_name(role) |
||||||
|
p = Project.find_by_name(project) || Project.find_by_identifier(project) |
||||||
|
as_admin do |
||||||
|
Member.new.tap do |m| |
||||||
|
m.user = u |
||||||
|
m.privacy_unnecessary = true if plugin_loaded?("redmine_dtag_privacy") |
||||||
|
m.roles << r |
||||||
|
m.project = p |
||||||
|
end.save! |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
Given /^there is a [rR]ole "([^\"]*)"$/ do |name, table = Cucumber::Ast::Table.new([])| |
||||||
|
FactoryGirl.create(:role, :name => name) unless Role.find_by_name(name) |
||||||
|
end |
||||||
|
|
||||||
|
Given /^there is a [rR]ole "([^\"]*)" with the following permissions:?$/ do |name, table| |
||||||
|
FactoryGirl.create(:role, :name => name, :permissions => table.raw.flatten) unless Role.find_by_name(name) |
||||||
|
end |
||||||
|
|
||||||
|
Given /^there are the following roles:$/ do |table| |
||||||
|
table.raw.flatten.each do |name| |
||||||
|
FactoryGirl.create(:role, :name => name) unless Role.find_by_name(name) |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
Given /^the [rR]ole "([^\"]*)" may have the following [rR]ights:$/ do |role, table| |
||||||
|
r = Role.find_by_name(role) |
||||||
|
raise "No such role was defined: #{role}" unless r |
||||||
|
as_admin do |
||||||
|
available_perms = Redmine::AccessControl.permissions.collect(&:name) |
||||||
|
r.permissions = [] |
||||||
|
|
||||||
|
table.raw.each do |_perm| |
||||||
|
perm = _perm.first |
||||||
|
unless perm.blank? |
||||||
|
perm = perm.gsub(" ", "_").underscore.to_sym |
||||||
|
if available_perms.include?(:"#{perm}") |
||||||
|
r.permissions << perm |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
r.save! |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
Given /^the [rR]ole "(.+?)" has no (?:[Pp]ermissions|[Rr]ights)$/ do |role_name| |
||||||
|
role = Role.find_by_name(role_name) |
||||||
|
raise "No such role was defined: #{role_name}" unless role |
||||||
|
as_admin do |
||||||
|
role.permissions = [] |
||||||
|
role.save! |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
Given /^the user "(.*?)" is a "([^\"]*?)"$/ do |user, role| |
||||||
|
step %Q{the user "#{user}" is a "#{role}" in the project "#{get_project.name}"} |
||||||
|
end |
||||||
|
|
Binary file not shown.
@ -0,0 +1,68 @@ |
|||||||
|
#-- 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. |
||||||
|
#++ |
||||||
|
|
||||||
|
Feature: Deleting work packages |
||||||
|
Background: |
||||||
|
Given there is 1 user with: |
||||||
|
| login | manager | |
||||||
|
And there are the following types: |
||||||
|
| Name | Is milestone | |
||||||
|
| Phase1 | false | |
||||||
|
And there is a project named "ecookbook" |
||||||
|
And there is a role "manager" with the following permissions: |
||||||
|
| view_work_packages | |
||||||
|
| delete_work_packages | |
||||||
|
| view_time_entries | |
||||||
|
| edit_time_entries | |
||||||
|
And the user "manager" is a "manager" in the project "ecookbook" |
||||||
|
And there are the following work packages in project "ecookbook": |
||||||
|
| subject | |
||||||
|
| wp1 | |
||||||
|
| wp2 | |
||||||
|
And there is a time entry for "wp1" with 10 hours |
||||||
|
And I am already logged in as "manager" |
||||||
|
|
||||||
|
@javascript |
||||||
|
Scenario: Deleting a work package via the action menu |
||||||
|
|
||||||
|
When I go to the page of the work package "wp1" |
||||||
|
And I select "Delete" from the action menu |
||||||
|
And I confirm popups |
||||||
|
|
||||||
|
Then I should be on the bulk destroy page of work packages |
||||||
|
|
||||||
|
When I choose "Reassign" |
||||||
|
And I fill in the id of work package "wp2" into "work package" |
||||||
|
And I submit the form by the "Apply" button |
||||||
|
|
||||||
|
Then I should be on the work packages index page of the project called "ecookbook" |
||||||
|
|
||||||
|
When I go to the page of the work package "wp2" |
||||||
|
|
||||||
|
Then the work package should be shown with the following values: |
||||||
|
| Spent time | 10.00 hours | |
@ -0,0 +1,55 @@ |
|||||||
|
#-- encoding: UTF-8 |
||||||
|
#-- copyright |
||||||
|
# OpenProject is a project management system. |
||||||
|
# |
||||||
|
# Copyright (C) 2012-2013 the OpenProject Team |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License version 3. |
||||||
|
# |
||||||
|
# See doc/COPYRIGHT.rdoc for more details. |
||||||
|
#++ |
||||||
|
|
||||||
|
require_relative '../../db/migrate/migration_utils/timelines' |
||||||
|
|
||||||
|
namespace :migrations do |
||||||
|
namespace :timelines do |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
desc "Sets all timelines with historical comparison from 'historical' to 'none'" |
||||||
|
task :remove_timelines_historical_comparison_from_options => :environment do |task| |
||||||
|
setter = TimelinesHistoricalComparisonSetter.new |
||||||
|
|
||||||
|
setter.remove_timelines_historical_comparison_from_options |
||||||
|
end |
||||||
|
|
||||||
|
private |
||||||
|
|
||||||
|
class TimelinesHistoricalComparisonSetter < ActiveRecord::Migration |
||||||
|
include Migration::Utils |
||||||
|
|
||||||
|
def remove_timelines_historical_comparison_from_options |
||||||
|
say_with_time_silently "Set historical comparison to none for all timelines" do |
||||||
|
update_column_values('timelines', |
||||||
|
['options'], |
||||||
|
update_options(set_historical_comparison_to_none), |
||||||
|
historical_comparison_filter) |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
private |
||||||
|
|
||||||
|
def set_historical_comparison_to_none |
||||||
|
Proc.new do |timelines_opts| |
||||||
|
timelines_opts['comparison'] = 'none' |
||||||
|
timelines_opts |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
def historical_comparison_filter |
||||||
|
"options LIKE '%comparison: historical%'" |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
end |
@ -1,122 +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. |
|
||||||
#++ |
|
||||||
|
|
||||||
require File.expand_path('../../../../spec_helper', __FILE__) |
|
||||||
|
|
||||||
describe Api::V2::PlanningElementStatusesController do |
|
||||||
let(:current_user) { FactoryGirl.create(:admin) } |
|
||||||
|
|
||||||
before do |
|
||||||
User.stub(:current).and_return current_user |
|
||||||
end |
|
||||||
|
|
||||||
describe 'index.xml' do |
|
||||||
def fetch |
|
||||||
get 'index', :format => 'xml' |
|
||||||
end |
|
||||||
it_should_behave_like "a controller action with unrestricted access" |
|
||||||
|
|
||||||
describe 'with no planning element statuses available' do |
|
||||||
it 'assigns an empty planning_element_statuses array' do |
|
||||||
get 'index', :format => 'xml' |
|
||||||
assigns(:planning_element_statuses).should == [] |
|
||||||
end |
|
||||||
|
|
||||||
it 'renders the index builder template' do |
|
||||||
get 'index', :format => 'xml' |
|
||||||
response.should render_template('planning_element_statuses/index', :formats => ["api"]) |
|
||||||
end |
|
||||||
end |
|
||||||
|
|
||||||
describe 'with 3 planning element statuses available' do |
|
||||||
before do |
|
||||||
@created_planning_element_statuses = [ |
|
||||||
FactoryGirl.create(:planning_element_status), |
|
||||||
FactoryGirl.create(:planning_element_status), |
|
||||||
FactoryGirl.create(:planning_element_status) |
|
||||||
] |
|
||||||
end |
|
||||||
|
|
||||||
it 'assigns an array with all planning element statuses' do |
|
||||||
get 'index', :format => 'xml' |
|
||||||
assigns(:planning_element_statuses).should == @created_planning_element_statuses |
|
||||||
end |
|
||||||
|
|
||||||
it 'renders the index template' do |
|
||||||
get 'index', :format => 'xml' |
|
||||||
response.should render_template('planning_element_statuses/index', :formats => ["api"]) |
|
||||||
end |
|
||||||
end |
|
||||||
end |
|
||||||
|
|
||||||
describe 'show.xml' do |
|
||||||
describe 'with unknown planning element status' do |
|
||||||
if false # would like to write it this way |
|
||||||
it 'returns status code 404' do |
|
||||||
get 'show', :id => '1337', :format => 'xml' |
|
||||||
|
|
||||||
response.status.should == '404 Not Found' |
|
||||||
end |
|
||||||
|
|
||||||
it 'returns an empty body' do |
|
||||||
get 'show', :id => '1337', :format => 'xml' |
|
||||||
|
|
||||||
response.body.should be_empty |
|
||||||
end |
|
||||||
|
|
||||||
else # but have to write it that way |
|
||||||
it 'raises ActiveRecord::RecordNotFound errors' do |
|
||||||
lambda do |
|
||||||
get 'show', :id => '1337', :format => 'xml' |
|
||||||
end.should raise_error(ActiveRecord::RecordNotFound) |
|
||||||
end |
|
||||||
end |
|
||||||
end |
|
||||||
|
|
||||||
describe 'with an available planning element status' do |
|
||||||
before do |
|
||||||
@available_planning_element_status = FactoryGirl.create(:planning_element_status, :id => '1337') |
|
||||||
end |
|
||||||
|
|
||||||
def fetch |
|
||||||
get 'show', :id => '1337', :format => 'xml' |
|
||||||
end |
|
||||||
it_should_behave_like "a controller action with unrestricted access" |
|
||||||
|
|
||||||
it 'assigns the available planning element status' do |
|
||||||
get 'show', :id => '1337', :format => 'xml' |
|
||||||
assigns(:planning_element_status).should == @available_planning_element_status |
|
||||||
end |
|
||||||
|
|
||||||
it 'renders the show template' do |
|
||||||
get 'show', :id => '1337', :format => 'xml' |
|
||||||
response.should render_template('planning_element_statuses/show', :formats => ["api"]) |
|
||||||
end |
|
||||||
end |
|
||||||
end |
|
||||||
end |
|
@ -0,0 +1,289 @@ |
|||||||
|
#-- 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' |
||||||
|
|
||||||
|
describe WorkPackage do |
||||||
|
let(:work_package) { FactoryGirl.create(:work_package, :project => project, |
||||||
|
:status => status) } |
||||||
|
let(:work_package2) { FactoryGirl.create(:work_package, :project => project2, |
||||||
|
:status => status) } |
||||||
|
let(:user) { FactoryGirl.create(:user) } |
||||||
|
|
||||||
|
let(:type) { FactoryGirl.create(:type_standard) } |
||||||
|
let(:project) { FactoryGirl.create(:project, types: [type]) } |
||||||
|
let(:project2) { FactoryGirl.create(:project, types: [type]) } |
||||||
|
let(:role) { FactoryGirl.create(:role) } |
||||||
|
let(:role2) { FactoryGirl.create(:role) } |
||||||
|
let(:member) { FactoryGirl.create(:member, :principal => user, |
||||||
|
:roles => [role]) } |
||||||
|
let(:member2) { FactoryGirl.create(:member, :principal => user, |
||||||
|
:roles => [role2], |
||||||
|
:project => work_package2.project) } |
||||||
|
let(:status) { FactoryGirl.create(:status) } |
||||||
|
let(:priority) { FactoryGirl.create(:priority) } |
||||||
|
let(:time_entry) { FactoryGirl.build(:time_entry, :work_package => work_package, |
||||||
|
:project => work_package.project) } |
||||||
|
let(:time_entry2) { FactoryGirl.build(:time_entry, :work_package => work_package2, |
||||||
|
:project => work_package2.project) } |
||||||
|
|
||||||
|
describe :cleanup_action_required_before_destructing? do |
||||||
|
describe 'w/ the work package having a time entry' do |
||||||
|
before do |
||||||
|
work_package |
||||||
|
time_entry.save! |
||||||
|
end |
||||||
|
|
||||||
|
it "should be true" do |
||||||
|
WorkPackage.cleanup_action_required_before_destructing?(work_package).should be_true |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
describe 'w/ two work packages having a time entry' do |
||||||
|
before do |
||||||
|
work_package |
||||||
|
time_entry.save! |
||||||
|
time_entry2.save! |
||||||
|
end |
||||||
|
|
||||||
|
it "should be true" do |
||||||
|
WorkPackage.cleanup_action_required_before_destructing?([work_package, work_package2]).should be_true |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
describe 'w/o the work package having a time entry' do |
||||||
|
before do |
||||||
|
work_package |
||||||
|
end |
||||||
|
|
||||||
|
it "should be false" do |
||||||
|
WorkPackage.cleanup_action_required_before_destructing?(work_package).should be_false |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
describe :associated_classes_to_address_before_destructing? do |
||||||
|
describe 'w/ the work package having a time entry' do |
||||||
|
before do |
||||||
|
work_package |
||||||
|
time_entry.save! |
||||||
|
end |
||||||
|
|
||||||
|
it "should be have 'TimeEntry' as class to address" do |
||||||
|
WorkPackage.associated_classes_to_address_before_destruction_of(work_package).should == [TimeEntry] |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
describe 'w/o the work package having a time entry' do |
||||||
|
before do |
||||||
|
work_package |
||||||
|
end |
||||||
|
|
||||||
|
it "should be empty" do |
||||||
|
WorkPackage.associated_classes_to_address_before_destruction_of(work_package).should be_empty |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
describe :cleanup_associated_before_destructing_if_required do |
||||||
|
before do |
||||||
|
work_package.save! |
||||||
|
|
||||||
|
time_entry.hours = 10 |
||||||
|
time_entry.save! |
||||||
|
end |
||||||
|
|
||||||
|
describe 'w/o a cleanup beeing necessary' do |
||||||
|
let(:action) { WorkPackage.cleanup_associated_before_destructing_if_required(work_package, user, :action => 'reassign') } |
||||||
|
|
||||||
|
before do |
||||||
|
time_entry.destroy |
||||||
|
end |
||||||
|
|
||||||
|
it 'should return true' do |
||||||
|
action.should be_true |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
describe 'w/ "destroy" as action' do |
||||||
|
let(:action) { WorkPackage.cleanup_associated_before_destructing_if_required(work_package, user, :action => 'destroy') } |
||||||
|
|
||||||
|
it 'should return true' do |
||||||
|
action.should be_true |
||||||
|
end |
||||||
|
|
||||||
|
it 'should not touch the time_entry' do |
||||||
|
action |
||||||
|
|
||||||
|
time_entry.reload |
||||||
|
time_entry.work_package_id.should == work_package.id |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
describe 'w/o an action' do |
||||||
|
let(:action) { WorkPackage.cleanup_associated_before_destructing_if_required(work_package, user) } |
||||||
|
|
||||||
|
it 'should return true' do |
||||||
|
action.should be_true |
||||||
|
end |
||||||
|
|
||||||
|
it 'should not touch the time_entry' do |
||||||
|
action |
||||||
|
|
||||||
|
time_entry.reload |
||||||
|
time_entry.work_package_id.should == work_package.id |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
describe 'w/ "nullify" as action' do |
||||||
|
let(:action) { WorkPackage.cleanup_associated_before_destructing_if_required(work_package, user, :action => 'nullify') } |
||||||
|
|
||||||
|
it 'should return true' do |
||||||
|
action.should be_true |
||||||
|
end |
||||||
|
|
||||||
|
it 'should set the work_package_id of all time entries to nil' do |
||||||
|
action |
||||||
|
|
||||||
|
time_entry.reload |
||||||
|
time_entry.work_package_id.should be_nil |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
describe 'w/ "reassign" as action |
||||||
|
w/ reassigning to a valid work_package' do |
||||||
|
let(:action) { WorkPackage.cleanup_associated_before_destructing_if_required(work_package, user, :action => 'reassign', :reassign_to_id => work_package2.id) } |
||||||
|
|
||||||
|
before do |
||||||
|
work_package2.save! |
||||||
|
role2.permissions << :edit_time_entries |
||||||
|
role2.save! |
||||||
|
member2.save! |
||||||
|
end |
||||||
|
|
||||||
|
it 'should return true' do |
||||||
|
action.should be_true |
||||||
|
end |
||||||
|
|
||||||
|
it 'should set the work_package_id of all time entries to the new work package' do |
||||||
|
action |
||||||
|
|
||||||
|
time_entry.reload |
||||||
|
time_entry.work_package_id.should == work_package2.id |
||||||
|
end |
||||||
|
|
||||||
|
it "should set the project_id of all time entries to the new work package's project" do |
||||||
|
action |
||||||
|
|
||||||
|
time_entry.reload |
||||||
|
time_entry.project_id.should == work_package2.project_id |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
describe 'w/ "reassign" as action |
||||||
|
w/ reassigning to a work_package the user is not allowed to see' do |
||||||
|
let(:action) { WorkPackage.cleanup_associated_before_destructing_if_required(work_package, user, :action => 'reassign', :reassign_to_id => work_package2.id) } |
||||||
|
|
||||||
|
before do |
||||||
|
work_package2.save! |
||||||
|
end |
||||||
|
|
||||||
|
it 'should return true' do |
||||||
|
action.should be_false |
||||||
|
end |
||||||
|
|
||||||
|
it 'should not alter the work_package_id of all time entries' do |
||||||
|
action |
||||||
|
|
||||||
|
time_entry.reload |
||||||
|
time_entry.work_package_id.should == work_package.id |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
describe 'w/ "reassign" as action |
||||||
|
w/ reassigning to a non existing work package' do |
||||||
|
let(:action) { WorkPackage.cleanup_associated_before_destructing_if_required(work_package, user, :action => 'reassign', :reassign_to_id => 0) } |
||||||
|
|
||||||
|
it 'should return true' do |
||||||
|
action.should be_false |
||||||
|
end |
||||||
|
|
||||||
|
it 'should not alter the work_package_id of all time entries' do |
||||||
|
action |
||||||
|
|
||||||
|
time_entry.reload |
||||||
|
time_entry.work_package_id.should == work_package.id |
||||||
|
end |
||||||
|
|
||||||
|
it 'should set an error on work packages' do |
||||||
|
action |
||||||
|
|
||||||
|
work_package.errors.get(:base).should == [I18n.t(:'activerecord.errors.models.work_package.is_not_a_valid_target_for_time_entries', id: 0)] |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
describe 'w/ "reassign" as action |
||||||
|
w/o providing a reassignment id' do |
||||||
|
let(:action) { WorkPackage.cleanup_associated_before_destructing_if_required(work_package, user, :action => 'reassign') } |
||||||
|
|
||||||
|
it 'should return true' do |
||||||
|
action.should be_false |
||||||
|
end |
||||||
|
|
||||||
|
it 'should not alter the work_package_id of all time entries' do |
||||||
|
action |
||||||
|
|
||||||
|
time_entry.reload |
||||||
|
time_entry.work_package_id.should == work_package.id |
||||||
|
end |
||||||
|
|
||||||
|
it 'should set an error on work packages' do |
||||||
|
action |
||||||
|
|
||||||
|
work_package.errors.get(:base).should == [I18n.t(:'activerecord.errors.models.work_package.is_not_a_valid_target_for_time_entries', id: nil)] |
||||||
|
end |
||||||
|
|
||||||
|
end |
||||||
|
|
||||||
|
describe 'w/ an invalid option' do |
||||||
|
let(:action) { WorkPackage.cleanup_associated_before_destructing_if_required(work_package, user, :action => 'bogus') } |
||||||
|
|
||||||
|
it 'should return false' do |
||||||
|
action.should be_false |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
describe 'w/ nil as invalid option' do |
||||||
|
let(:action) { WorkPackage.cleanup_associated_before_destructing_if_required(work_package, user, nil) } |
||||||
|
|
||||||
|
it 'should return false' do |
||||||
|
action.should be_false |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
end |
@ -1,70 +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. |
|
||||||
#++ |
|
||||||
|
|
||||||
require File.expand_path('../../../../../spec_helper', __FILE__) |
|
||||||
|
|
||||||
describe 'api/v2/planning_element_statuses/_planning_element_status.api' do |
|
||||||
before do |
|
||||||
view.extend TimelinesHelper |
|
||||||
end |
|
||||||
|
|
||||||
# added to pass in locals |
|
||||||
def render |
|
||||||
params[:format] = 'xml' |
|
||||||
super(:partial => 'api/v2/planning_element_statuses/planning_element_status.api', :object => planning_element_status) |
|
||||||
end |
|
||||||
|
|
||||||
describe 'with an assigned planning_element_status' do |
|
||||||
let(:planning_element_status) { FactoryGirl.build(:planning_element_status, |
|
||||||
:id => 1, |
|
||||||
:name => 'Awesometastic Planning Element Status', |
|
||||||
:position => 100) } |
|
||||||
|
|
||||||
it 'renders a planning_element_status node' do |
|
||||||
render |
|
||||||
response.should have_selector('planning_element_status', :count => 1) |
|
||||||
end |
|
||||||
|
|
||||||
describe 'planning_element_status node' do |
|
||||||
it 'contains an id element containing the planning element status id' do |
|
||||||
render |
|
||||||
response.should have_selector('planning_element_status id', :text => '1') |
|
||||||
end |
|
||||||
|
|
||||||
it 'contains a name element containing the planning element status name' do |
|
||||||
render |
|
||||||
response.should have_selector('planning_element_status name', :text => 'Awesometastic Planning Element Status') |
|
||||||
end |
|
||||||
|
|
||||||
it 'contains an position element containing the planning element status position' do |
|
||||||
render |
|
||||||
response.should have_selector('planning_element_status position', :text => '100') |
|
||||||
end |
|
||||||
end |
|
||||||
end |
|
||||||
end |
|
@ -1,104 +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. |
|
||||||
#++ |
|
||||||
|
|
||||||
require File.expand_path('../../../../../spec_helper', __FILE__) |
|
||||||
|
|
||||||
describe 'api/v2/planning_element_statuses/index.api.rsb' do |
|
||||||
before do |
|
||||||
view.extend TimelinesHelper |
|
||||||
end |
|
||||||
|
|
||||||
before do |
|
||||||
params[:format] = 'xml' |
|
||||||
end |
|
||||||
|
|
||||||
describe 'with no planning element statuses available' do |
|
||||||
it 'renders an empty planning_element_statuses document' do |
|
||||||
assign(:planning_element_statuses, []) |
|
||||||
|
|
||||||
render |
|
||||||
|
|
||||||
response.should have_selector('planning_element_statuses', :count => 1) |
|
||||||
response.should have_selector('planning_element_statuses[type=array][size="0"]') do |
|
||||||
without_tag 'planning_element_status' |
|
||||||
end |
|
||||||
end |
|
||||||
end |
|
||||||
|
|
||||||
describe 'with 3 planning element statuses available' do |
|
||||||
let(:planning_element_statuses) do |
|
||||||
[ |
|
||||||
FactoryGirl.build(:planning_element_status), |
|
||||||
FactoryGirl.build(:planning_element_status), |
|
||||||
FactoryGirl.build(:planning_element_status) |
|
||||||
] |
|
||||||
end |
|
||||||
|
|
||||||
it 'renders a planning_element_statuses document with the size 3 of type array' do |
|
||||||
assign(:planning_element_statuses, planning_element_statuses) |
|
||||||
|
|
||||||
render |
|
||||||
|
|
||||||
response.should have_selector('planning_element_statuses', :count => 1) |
|
||||||
response.should have_selector('planning_element_statuses[type=array][size="3"]') |
|
||||||
end |
|
||||||
|
|
||||||
it 'renders a planning_element_status for each assigned planning element' do |
|
||||||
assign(:planning_element_statuses, planning_element_statuses) |
|
||||||
|
|
||||||
|
|
||||||
render |
|
||||||
|
|
||||||
response.should have_selector('planning_element_statuses planning_element_status', :count => 3) |
|
||||||
end |
|
||||||
|
|
||||||
it 'renders the _planning_element_status template for each assigned planning element status' do |
|
||||||
assign(:planning_element_statuses, planning_element_statuses) |
|
||||||
|
|
||||||
view.should_receive(:render).exactly(3).times.with(hash_including(:partial => '/api/v2/planning_element_statuses/planning_element_status.api')).and_return('') |
|
||||||
|
|
||||||
# just to be able to call render despite the should_receive expectations above |
|
||||||
view.should_receive(:render).once.with({:template=>"api/v2/planning_element_statuses/index", :handlers=>["rsb"], :formats=>["api"]}, {}).and_call_original |
|
||||||
|
|
||||||
render |
|
||||||
end |
|
||||||
|
|
||||||
it 'passes the planning element statuses as local var to the partial' do |
|
||||||
assign(:planning_element_statuses, planning_element_statuses) |
|
||||||
|
|
||||||
view.should_receive(:render).once.with(hash_including(:object => planning_element_statuses.first)).and_return('') |
|
||||||
view.should_receive(:render).once.with(hash_including(:object => planning_element_statuses.second)).and_return('') |
|
||||||
view.should_receive(:render).once.with(hash_including(:object => planning_element_statuses.third)).and_return('') |
|
||||||
|
|
||||||
# just to be able to call render despite the should_receive expectations above |
|
||||||
view.should_receive(:render).once.with({:template=>"api/v2/planning_element_statuses/index", :handlers=>["rsb"], :formats=>["api"]}, {}).and_call_original |
|
||||||
|
|
||||||
render |
|
||||||
end |
|
||||||
end |
|
||||||
end |
|
@ -1,74 +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. |
|
||||||
#++ |
|
||||||
|
|
||||||
require File.expand_path('../../../../../spec_helper', __FILE__) |
|
||||||
|
|
||||||
describe 'api/v2/planning_element_statuses/show.api.rsb' do |
|
||||||
before do |
|
||||||
view.extend TimelinesHelper |
|
||||||
end |
|
||||||
|
|
||||||
before do |
|
||||||
params[:format] = 'xml' |
|
||||||
end |
|
||||||
|
|
||||||
describe 'with an assigned planning element status' do |
|
||||||
let(:planning_element_status) { FactoryGirl.build(:planning_element_status) } |
|
||||||
|
|
||||||
before do |
|
||||||
assign(:planning_element_status, planning_element_status) |
|
||||||
end |
|
||||||
|
|
||||||
it 'renders a planning_element_status document' do |
|
||||||
|
|
||||||
render |
|
||||||
|
|
||||||
response.should have_selector('planning_element_status', :count => 1) |
|
||||||
end |
|
||||||
|
|
||||||
it 'renders the _planning_element_status template once' do |
|
||||||
|
|
||||||
view.should_receive(:render).once.with(hash_including(:partial => '/api/v2/planning_element_statuses/planning_element_status.api')).and_return('') |
|
||||||
|
|
||||||
# just to render the speced template despite the should receive expectations above |
|
||||||
view.should_receive(:render).once.with({:template=>"api/v2/planning_element_statuses/show", :handlers=>["rsb"], :formats=>["api"]}, {}).and_call_original |
|
||||||
|
|
||||||
render |
|
||||||
end |
|
||||||
|
|
||||||
it 'passes the planning element status as local var to the partial' do |
|
||||||
|
|
||||||
view.should_receive(:render).once.with(hash_including(:object => planning_element_status)).and_return('') |
|
||||||
|
|
||||||
# just to render the speced template despite the should receive expectations above |
|
||||||
view.should_receive(:render).once.with({:template=>"api/v2/planning_element_statuses/show", :handlers=>["rsb"], :formats=>["api"]}, {}).and_call_original |
|
||||||
|
|
||||||
render |
|
||||||
end |
|
||||||
end |
|
||||||
end |
|
Loading…
Reference in new issue