Remove non-csp conformant js.erb with JSON remote field updater

Also fixes https://community.openproject.com/projects/openproject/work_packages/27844
pull/6827/head
Oliver Günther 6 years ago
parent f792df2235
commit 7ed1392518
No known key found for this signature in database
GPG Key ID: 88872239EB414F99
  1. 63
      app/controllers/cost_objects_controller.rb
  2. 5
      app/views/cost_objects/update_labor_budget_item.js.erb
  3. 7
      app/views/cost_objects/update_material_budget_item.js.erb
  4. 3
      app/views/costlog/edit.html.erb
  5. 6
      frontend/legacy-app/components/budget/cost-budget-subform.directive.ts
  6. 5
      frontend/legacy-app/components/budget/cost-unit-subform.directive.ts
  7. 4
      frontend/module/wp-display/wp-display-costs-by-type-field.module.ts
  8. 98
      spec/features/add_cost_entry_spec.rb

@ -21,16 +21,16 @@ class CostObjectsController < ApplicationController
before_action :find_cost_object, only: [:show, :edit, :update, :copy]
before_action :find_cost_objects, only: :destroy
before_action :find_project, only: [
:new, :create,
:update_material_budget_item, :update_labor_budget_item
:new, :create,
:update_material_budget_item, :update_labor_budget_item
]
before_action :find_optional_project, only: :index
before_action :authorize_global, only: :index
before_action :authorize, except: [
# unrestricted actions
:index,
:update_material_budget_item, :update_labor_budget_item
# unrestricted actions
:index,
:update_material_budget_item, :update_labor_budget_item
]
helper :sort
@ -47,8 +47,9 @@ class CostObjectsController < ApplicationController
def index
respond_to do |format|
format.html do end
format.csv { limit = Setting.work_packages_export_limit.to_i }
format.html do
end
format.csv { limit = Setting.work_packages_export_limit.to_i }
end
sort_columns = { 'id' => "#{CostObject.table_name}.id",
@ -60,23 +61,25 @@ class CostObjectsController < ApplicationController
sort_update sort_columns
@cost_objects = CostObject
.visible(current_user)
.order(sort_clause)
.includes(:author)
.where(project_id: @project.id)
.page(page_param)
.per_page(per_page_param)
.visible(current_user)
.order(sort_clause)
.includes(:author)
.where(project_id: @project.id)
.page(page_param)
.per_page(per_page_param)
respond_to do |format|
format.html do render action: 'index', layout: !request.xhr? end
format.csv { send_data(cost_objects_to_csv(@cost_objects), type: 'text/csv; header=present', filename: 'export.csv') }
format.html do
render action: 'index', layout: !request.xhr?
end
format.csv { send_data(cost_objects_to_csv(@cost_objects), type: 'text/csv; header=present', filename: 'export.csv') }
end
end
def show
@edit_allowed = User.current.allowed_to?(:edit_cost_objects, @project)
respond_to do |format|
format.html { render action: 'show', layout: !request.xhr? }
format.html { render action: 'show', layout: !request.xhr? }
end
end
@ -128,7 +131,7 @@ class CostObjectsController < ApplicationController
flash[:notice] = t(:notice_successful_create)
redirect_to(params[:continue] ? { action: 'new' } :
{ action: 'show', id: @cost_object })
{ action: 'show', id: @cost_object })
return
else
render action: 'new', layout: !request.xhr?
@ -151,10 +154,10 @@ class CostObjectsController < ApplicationController
params[:cost_object].delete(:kind)
@cost_object.attributes = permitted_params.cost_object if params[:cost_object]
if params[:cost_object][:existing_material_budget_item_attributes].nil?
@cost_object.existing_material_budget_item_attributes=({})
@cost_object.existing_material_budget_item_attributes = ({})
end
if params[:cost_object][:existing_labor_budget_item_attributes].nil?
@cost_object.existing_labor_budget_item_attributes=({})
@cost_object.existing_labor_budget_item_attributes = ({})
end
@cost_object.attach_files(permitted_params.attachments.to_h)
@ -184,16 +187,23 @@ class CostObjectsController < ApplicationController
cost_type = CostType.where(id: params[:cost_type_id]).first
if cost_type && params[:units].present?
volume = BigDecimal.new(Rate.clean_currency(params[:units]))
volume = BigDecimal.new(Rate.clean_currency(params[:units])) rescue 0.0
@costs = (volume * cost_type.rate_at(params[:fixed_date]).rate rescue 0.0)
@unit = volume == 1.0 ? cost_type.unit : cost_type.unit_plural
else
@costs = 0.0
@unit = ''
@unit = cost_type.try(:unit_plural) || ''
end
response = { "#{@element_id}_unit_name" => h(@unit) }
if current_user.allowed_to?(:view_cost_rates, @project)
response["#{@element_id}_costs"] = number_to_currency(@costs)
end
respond_to do |format|
format.js { render :update_material_budget_item }
format.json do
render json: response
end
end
end
@ -208,8 +218,15 @@ class CostObjectsController < ApplicationController
@costs = 0.0
end
response = { "#{@element_id}_unit_name" => h(@unit) }
if current_user.allowed_to?(:view_hourly_rates, @project)
response["#{@element_id}_costs"] = number_to_currency(@costs)
end
respond_to do |format|
format.js { render :update_labor_budget_item }
format.json do
render json: response
end
end
end

@ -1,5 +0,0 @@
(function($) {
<% if current_user.allowed_to? :view_hourly_rates, @project %>
$('#<%= "#{@element_id}_costs" %>').html("<%= number_to_currency(@costs) %>");
<% end %>
})(jQuery);

@ -1,7 +0,0 @@
(function($) {
<% if current_user.allowed_to? :view_cost_rates, @project %>
$('#<%= "#{@element_id}_costs" %>').html("<%= number_to_currency(@costs) %>");
<% end %>
$('#<%= "#{@element_id}_unit_name" %>').html("<%= h(@unit) %>");
})(jQuery);

@ -32,6 +32,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
<%= activate_angular_js do %>
<remote-field-updater url="<%= url_for(controller: :cost_objects, action: :update_material_budget_item, project_id: @cost_entry.project) %>"
mode="json"
method="POST">
<%= labelled_tabular_form_for @cost_entry, url: url, html: { method: method } do |f| %>
<%= error_messages_for 'cost_entry' %>
@ -108,7 +109,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
<cost-unit-subform obj-id="cost_entry_costs" obj-name="cost_entry[overridden_costs]">
<% if User.current.allowed_to? :view_cost_rates, @cost_entry.project %>
<a href="#" id="cost_entry_costs" class="icon-context icon-edit" title="<%= t(:help_click_to_edit) %>">
<%= number_to_currency(@cost_entry.calculated_costs) %>
<%= number_to_currency(@cost_entry.real_costs) %>
</a>
<% else %>
<span id="cost_entry_costs_editor" class="form--text-field-container">

@ -87,9 +87,11 @@ export class CostBudgetSubformController {
url: this.updateUrl,
method: 'POST',
data: request,
headers: { 'Accept': 'application/javascript' }
headers: { 'Accept': 'application/json' }
}).then((response:any) => {
eval(response.data);
_.each(response.data, (val:string, selector:string) => {
jQuery('#' + selector).html(val);
});
}).catch(response => {
this.pluginContext.context!.services.wpNotifications.handleErrorResponse(response);
});

@ -32,6 +32,9 @@ export class CostUnitSubformController {
public objName: string;
constructor(public $element:ng.IAugmentedJQuery) {
this.objId = this.$element.attr('obj-id');
this.objName = this.$element.attr('obj-name');
// Add new row handler
$element.find('#'+this.objId).click(() => {
this.makeEditable('#'+this.objId, this.objName);
@ -96,8 +99,6 @@ function costUnitSubform():any {
return {
restrict: 'E',
scope: {
objId: '@',
objName: '@'
},
bindToController: true,
controller: CostUnitSubformController,

@ -66,6 +66,10 @@ export class CostsByTypeDisplayField extends DisplayField {
}
}
public get title() {
return '';
}
public render(element:HTMLElement, displayText:string):void {
const showCosts = this.resource.showCosts;
if (this.isEmpty() || !showCosts) {

@ -0,0 +1,98 @@
#-- copyright
# OpenProject Costs Plugin
#
# Copyright (C) 2009 - 2014 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.
#
# 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.
#++
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
describe 'Work Package cost fields', type: :feature, js: true do
let(:type_task) { FactoryBot.create(:type_task) }
let!(:status) { FactoryBot.create(:status, is_default: true) }
let!(:priority) { FactoryBot.create(:priority, is_default: true) }
let!(:project) {
FactoryBot.create(:project, types: [type_task])
}
let(:user) { FactoryBot.create :user,
member_in_project: project,
member_through_role: role }
let(:role) { FactoryBot.create :role, permissions: [:view_work_packages,
:delete_work_packages,
:log_costs,
:view_cost_rates,
:edit_cost_entries,
:view_cost_entries] }
let!(:cost_type1) {
type = FactoryBot.create :cost_type, name: 'A', unit: 'A single', unit_plural: 'A plural'
FactoryBot.create :cost_rate, cost_type: type, rate: 1.00
type
}
let!(:cost_type2) {
type = FactoryBot.create :cost_type, name: 'B', unit: 'B single', unit_plural: 'B plural'
FactoryBot.create :cost_rate, cost_type: type, rate: 2.00
type
}
let!(:work_package) { FactoryBot.create :work_package, project: project, status: status, type: type_task }
let(:full_view) { ::Pages::FullWorkPackage.new(work_package, project) }
before do
login_as(user)
full_view.visit!
end
it 'does not show read-only fields' do
# Go to add cost entry page
find('#action-show-more-dropdown-menu .button').click
find('.menu-item', text: 'Log unit costs').click
# Set single value, should update suffix
select 'A', from: 'cost_entry_cost_type_id'
fill_in 'cost_entry_units', with: '1'
sleep 1
expect(page).to have_selector('#cost_entry_unit_name', text: 'A single')
expect(page).to have_selector('#cost_entry_costs', text: '1.00 EUR')
fill_in 'cost_entry_units', with: '2'
sleep 1
expect(page).to have_selector('#cost_entry_unit_name', text: 'A plural')
expect(page).to have_selector('#cost_entry_costs', text: '2.00 EUR')
# Switch cost type
select 'B', from: 'cost_entry_cost_type_id'
expect(page).to have_selector('#cost_entry_unit_name', text: 'B plural')
expect(page).to have_selector('#cost_entry_costs', text: '4.00 EUR')
# Override costs
find('#cost_entry_costs').click
fill_in 'cost_entry_costs_edit', with: '15'
click_on 'Save'
# Expect correct costs
expect(page).to have_selector('.flash.notice', text: I18n.t(:notice_cost_logged_successfully))
entry = CostEntry.last
expect(entry.cost_type_id).to eq(cost_type2.id)
expect(entry.units).to eq(2.0)
expect(entry.costs).to eq(4.0)
expect(entry.real_costs).to eq(15.0)
visit edit_cost_entry_path(entry)
expect(page).to have_selector('#cost_entry_costs', text: '15.00 EUR')
end
end
Loading…
Cancel
Save