<% end %>
+
diff --git a/app/views/shared/_costs_header.html.erb b/app/views/shared/_costs_header.html.erb
index 383261e091..8028ebf618 100644
--- a/app/views/shared/_costs_header.html.erb
+++ b/app/views/shared/_costs_header.html.erb
@@ -20,5 +20,4 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
<% content_for :header_tags do %>
<%= stylesheet_link_tag 'costs/costs.css' %>
- <%= javascript_include_tag 'costs/costs.js' %>
<% end %>
diff --git a/frontend/app/components/budget/cost-budget-subform.directive.ts b/frontend/app/components/budget/cost-budget-subform.directive.ts
index 2dda208744..d12f5789ff 100644
--- a/frontend/app/components/budget/cost-budget-subform.directive.ts
+++ b/frontend/app/components/budget/cost-budget-subform.directive.ts
@@ -43,7 +43,7 @@ export class CostBudgetSubformController {
// Updater URL for the rows contained here
public updateUrl: string;
- constructor(public $element, public $http, public wpNotificationsService) {
+ constructor(public $element, public wpNotificationsService) {
this.container = $element.find('.budget-item-container');
this.rowIndex = parseInt(this.itemCount);
@@ -121,7 +121,7 @@ function costsBudgetSubform() {
restrict: 'E',
scope: {
updateUrl: '@',
- rowIndex: '@'
+ itemCount: '@'
},
link: (scope, element, attr, ctrl) => {
const template = element.find('.budget-row-template');
diff --git a/frontend/app/components/subform/cost-subform.directive.ts b/frontend/app/components/subform/cost-subform.directive.ts
new file mode 100644
index 0000000000..1c3dc42642
--- /dev/null
+++ b/frontend/app/components/subform/cost-subform.directive.ts
@@ -0,0 +1,92 @@
+// -- copyright
+// OpenProject is a project management system.
+// Copyright (C) 2012-2015 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.
+// ++
+
+export class CostSubformController {
+
+ // Container for rows
+ private container: ng.IAugmentedJQuery;
+
+ // Template for new rows to insert, is rendered with INDEX placeholder
+ private rowTemplate: string;
+
+ // Current row index
+ public rowIndex: number;
+
+ // subform item count as output by rails
+ public itemCount: string;
+
+ constructor(public $element) {
+ this.container = $element.find('.subform-container');
+ this.rowIndex = parseInt(this.itemCount);
+
+ $element.on('click', '.delete-row-button', (evt) => {
+ var row = angular.element(evt.target).closest('.subform-row');
+ row.remove();
+ });
+
+ // Add new row handler
+ $element.find('.add-row-button').click(() => {
+ this.addRow();
+ });
+ }
+
+ /**
+ * Adds a new empty budget item row with the correct index set
+ */
+ public addRow() {
+ this.container.append(this.indexedTemplate);
+ this.rowIndex += 1;
+
+ this.container.find('.subform-row:last-child input:first').focus();
+ }
+
+ /**
+ * Return the next possible new row from rowTemplate,
+ * with the index set to the current last value.
+ */
+ private get indexedTemplate() {
+ return this.rowTemplate.replace(/INDEX/g, this.rowIndex.toString());
+ }
+}
+
+function costsSubform() {
+ return {
+ restrict: 'E',
+ scope: { itemCount: '@' },
+ link: (scope, element, attr, ctrl) => {
+ const template = element.find('.subform-row-template');
+ ctrl.rowTemplate = template[0].outerHTML;
+ template.remove();
+ },
+ bindToController: true,
+ controller: CostSubformController,
+ controllerAs: '$ctrl'
+ };
+}
+
+angular.module('openproject').directive('costsSubform', costsSubform);
diff --git a/spec/features/members_hourly_rates_spec.rb b/spec/features/members_hourly_rates_spec.rb
index f7556426b2..896a744192 100644
--- a/spec/features/members_hourly_rates_spec.rb
+++ b/spec/features/members_hourly_rates_spec.rb
@@ -48,6 +48,9 @@ describe 'hourly rates on a member', type: :feature, js: true do
fill_in 'Valid from', with: date.strftime('%Y-%m-%d') if date
fill_in 'Rate', with: rate
end
+
+ # Close the date picker if still open
+ find('.ui-datepicker-close').click rescue nil
end
def change_rate_date(from:, to:)
diff --git a/spec/features/update_budget_spec.rb b/spec/features/update_budget_spec.rb
index 72976ea04f..3120edf557 100644
--- a/spec/features/update_budget_spec.rb
+++ b/spec/features/update_budget_spec.rb
@@ -25,7 +25,7 @@ describe 'updating a budget', type: :feature, js: true do
let(:budget) { FactoryGirl.create :cost_object, author: user, project: project }
before do
- allow(User).to receive(:current).and_return user
+ login_as(user)
end
describe 'with new cost items' do
@@ -33,7 +33,7 @@ describe 'updating a budget', type: :feature, js: true do
FactoryGirl.create :cost_type, name: 'Post-war', unit: 'cap', unit_plural: 'caps'
end
- let(:page) { Pages::EditBudget.new budget.id }
+ let(:budget_page) { Pages::EditBudget.new budget.id }
before do
project.add_member! user, FactoryGirl.create(:role)
@@ -43,22 +43,22 @@ describe 'updating a budget', type: :feature, js: true do
end
it 'creates the cost items' do
- page.visit!
+ budget_page.visit!
click_on 'Update'
- page.add_unit_costs! 3, comment: 'Stimpak'
- page.add_labor_costs! 5, user_name: user.name, comment: 'treatment'
+ budget_page.add_unit_costs! 3, comment: 'Stimpak'
+ budget_page.add_labor_costs! 5, user_name: user.name, comment: 'treatment'
click_on 'Submit'
- expect(page).to have_content('Successful update')
+ expect(budget_page).to have_content('Successful update')
- page.toggle_unit_costs!
- expect(page.unit_costs_at(1)).to have_content '150.00 EUR'
- expect(page.overall_unit_costs).to have_content '150.00 EUR'
+ budget_page.toggle_unit_costs!
+ expect(budget_page.unit_costs_at(1)).to have_content '150.00 EUR'
+ expect(budget_page.overall_unit_costs).to have_content '150.00 EUR'
- page.toggle_labor_costs!
- expect(page.labor_costs_at(1)).to have_content '125.00 EUR'
- expect(page.overall_labor_costs).to have_content '125.00 EUR'
+ budget_page.toggle_labor_costs!
+ expect(budget_page.labor_costs_at(1)).to have_content '125.00 EUR'
+ expect(budget_page.overall_labor_costs).to have_content '125.00 EUR'
end
end
@@ -79,7 +79,7 @@ describe 'updating a budget', type: :feature, js: true do
cost_object: budget
end
- let(:page) { Pages::EditBudget.new budget.id }
+ let(:budget_page) { Pages::EditBudget.new budget.id }
before do
project.add_member! user, FactoryGirl.create(:role)
@@ -93,25 +93,25 @@ describe 'updating a budget', type: :feature, js: true do
end
it 'updates the cost items' do
- page.visit!
+ budget_page.visit!
click_on 'Update'
- page.edit_unit_costs! material_budget_item.id, units: 5,
+ budget_page.edit_unit_costs! material_budget_item.id, units: 5,
comment: 'updated num stimpaks'
- page.edit_labor_costs! labor_budget_item.id, hours: 3,
+ budget_page.edit_labor_costs! labor_budget_item.id, hours: 3,
user_name: user.name,
comment: 'updated treatment duration'
click_on 'Submit'
- expect(page).to have_content('Successful update')
+ expect(budget_page).to have_content('Successful update')
- page.toggle_unit_costs!
- expect(page.unit_costs_at(1)).to have_content '250.00 EUR'
- expect(page.overall_unit_costs).to have_content '250.00 EUR'
+ budget_page.toggle_unit_costs!
+ expect(budget_page.unit_costs_at(1)).to have_content '250.00 EUR'
+ expect(budget_page.overall_unit_costs).to have_content '250.00 EUR'
- page.toggle_labor_costs!
- expect(page.labor_costs_at(1)).to have_content '75.00 EUR'
- expect(page.overall_labor_costs).to have_content '75.00 EUR'
+ budget_page.toggle_labor_costs!
+ expect(budget_page.labor_costs_at(1)).to have_content '75.00 EUR'
+ expect(budget_page.overall_labor_costs).to have_content '75.00 EUR'
end
end
end