Merge pull request #6760 from opf/feature/current_date_custom_action

allow current date for custom action
pull/6769/head
Henriette Dinger 6 years ago committed by GitHub
commit 7e1870bc3e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      app/assets/stylesheets/content/_custom_actions.sass
  2. 1
      app/contracts/work_packages/update_contract.rb
  3. 4
      app/models/custom_actions/actions/date.rb
  4. 23
      app/models/custom_actions/actions/strategies/date.rb
  5. 4
      app/models/custom_actions/actions/strategies/date_property.rb
  6. 8
      app/views/custom_actions/_form.html.erb
  7. 5
      config/locales/js-en.yml
  8. 19
      frontend/legacy/app/components/wp-custom-actions/date-action.component.html
  9. 99
      frontend/legacy/app/components/wp-custom-actions/date-action.component.ts
  10. 10
      frontend/src/app/angular4-modules.ts
  11. 4
      frontend/src/app/components/wp-by-version-graph/wp-by-version-graph.template.html
  12. 6
      spec/features/work_packages/custom_actions_spec.rb
  13. 23
      spec/models/custom_actions/actions/custom_field_spec.rb
  14. 13
      spec/models/custom_actions/actions/date_spec.rb
  15. 17
      spec/models/custom_actions/actions/due_date_spec.rb
  16. 17
      spec/models/custom_actions/actions/start_date_spec.rb
  17. 28
      spec/models/custom_actions/shared_expectations.rb

@ -46,3 +46,6 @@
width: 100%
// The margin is necessary for all buttons so that the alignment is correct on small screens
margin-right: 10px
wp-custom-actions-admin-date-action
display: flex

@ -37,7 +37,6 @@ module WorkPackages
end
end
validate :user_allowed_to_access
validate :user_allowed_to_edit

@ -36,7 +36,7 @@ class CustomActions::Actions::Date < CustomActions::Actions::Base
end
def apply(work_package)
work_package.start_date = values.first
work_package.due_date = values.first
work_package.start_date = date_to_apply
work_package.due_date = date_to_apply
end
end

@ -37,10 +37,27 @@ module CustomActions::Actions::Strategies::Date
:date_property
end
def to_date_or_nil(value)
return nil if value.nil?
def apply(work_package)
work_package.send("#{self.class.key}=", date_to_apply)
end
private
value.to_date
def date_to_apply
if values.first == '%CURRENT_DATE%'
Date.today
else
values.first
end
end
def to_date_or_nil(value)
case value
when nil, '%CURRENT_DATE%'
value
else
value.to_date
end
rescue TypeError, ArgumentError
nil
end

@ -30,8 +30,4 @@
module CustomActions::Actions::Strategies::DateProperty
include CustomActions::Actions::Strategies::Date
def apply(work_package)
work_package.send("#{self.class.key}=", values.first)
end
end

@ -59,11 +59,9 @@
</autocomplete-select-decoration>
</div>
<% elsif %i(date_property).include?(action.type) %>
<%= styled_text_field_tag input_name,
action.values,
container_class: '-slim',
class: '-augmented-datepicker',
size: '10' %>
<wp-custom-actions-admin-date-action field-value="<%= action.values.first %>"
field-name="<%= input_name %>">
</wp-custom-actions-admin-date-action>
<% elsif %i(string_property text_property).include?(action.type) %>
<%= styled_text_field_tag input_name,
action.values,

@ -132,6 +132,11 @@ en:
button: 'Embed work package table'
text: '[Placeholder] Embedded work package table'
custom_actions:
date:
specific: 'on'
current_date: 'Current date'
error:
internal: "An internal error has occurred."
cannot_save_changes_with_message: "Cannot save your changes due to the following error: %{error}"

@ -0,0 +1,19 @@
<span class="form--select-container">
<select class="form--select"
id="{{$ctrl.fieldId}}"
ng-model="$ctrl.selectedOperator"
ng-change="$ctrl.toggleValueVisibility()"
ng-options="n.label for n in $ctrl.operators track by n.key">
</select>
</span>
<span class="form--text-field-container -slim"
ng-if="$ctrl.valueVisible" >
<input type="text"
id="{{$ctrl.fieldId + '_visible'}}"
ng-model="$ctrl.visibleValue"
ng-change="$ctrl.updateDbValue()"
class="-augmented-datepicker form--text-field">
</span>
<input type="hidden"
name="{{$ctrl.fieldName}}"
value="{{$ctrl.fieldValue}}">

@ -0,0 +1,99 @@
// -- 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.
// ++
import {openprojectLegacyModule} from "core-app/openproject-legacy-app";
export class WpCustomActionsAdminDateActionComponent {
public valueVisible = false;
public fieldName:string;
public fieldValue:string;
public visibleValue:string;
public selectedOperator:any;
private i18n:any;
private onKey = 'on';
private currentKey = 'current';
private currentFieldValue = '%CURRENT_DATE%';
public operators:{key:string, label:string}[];
constructor() {
window.OpenProject.getPluginContext().then((context) => {
this.i18n = context.services.i18n;
this.initialize();
});
}
// cannot use $onInit as it would be called before the operators gets filled
public initialize() {
this.operators = [{key: this.onKey, label: this.i18n.t('js.custom_actions.date.specific')},
{key: this.currentKey, label: this.i18n.t('js.custom_actions.date.current_date')}];
if (this.fieldValue === this.currentFieldValue) {
this.selectedOperator = this.operators[1];
} else {
this.selectedOperator = this.operators[0];
this.visibleValue = this.fieldValue;
}
this.toggleValueVisibility();
}
public toggleValueVisibility() {
this.valueVisible = this.selectedOperator.key === this.onKey;
this.updateDbValue();
}
private updateDbValue() {
if (this.selectedOperator.key === this.currentKey) {
this.fieldValue = this.currentFieldValue;
} else {
this.fieldValue = this.visibleValue;
}
}
public get fieldId() {
// replace all square brackets by underscore
// to match the label's for value
return this.fieldName
.replace(/\[|\]/g, '_')
.replace('__', '_')
.replace(/_$/, '');
}
}
openprojectLegacyModule.component('wpCustomActionsAdminDateAction', {
template: require('!!raw-loader!./date-action.component.html'),
controller: WpCustomActionsAdminDateActionComponent,
bindings: {
fieldName: "@",
fieldValue: "@",
}
});

@ -348,8 +348,6 @@ import {WorkPackageByVersionGraphComponent} from "core-components/wp-by-version-
ZenModeButtonComponent,
WpResizerDirective,
MainMenuResizerComponent,
WpCustomActionComponent,
WpCustomActionsComponent,
WorkPackageTableSumsRowController,
SortHeaderDirective,
@ -486,6 +484,10 @@ import {WorkPackageByVersionGraphComponent} from "core-components/wp-by-version-
EmbeddedTablesMacroComponent,
CkeditorAugmentedTextareaComponent,
// CustomActions
WpCustomActionComponent,
WpCustomActionsComponent,
// Attachments
AttachmentsComponent,
AttachmentListComponent,
@ -501,7 +503,6 @@ import {WorkPackageByVersionGraphComponent} from "core-components/wp-by-version-
WorkPackageTablePaginationComponent,
WorkPackagesTableController,
TablePaginationComponent,
WpCustomActionsComponent,
// Split view
WorkPackageSplitViewComponent,
@ -574,6 +575,9 @@ import {WorkPackageByVersionGraphComponent} from "core-components/wp-by-version-
CkeditorAugmentedTextareaComponent,
EmbeddedTablesMacroComponent,
// CustomActions
WpCustomActionsComponent,
// Attachments
AttachmentsComponent,

@ -1,6 +1,6 @@
<select [(ngModel)]="groupBy"
(ngModelChange)="setQueryProps()">
<option [ngValue]="option.key" *ngFor="let option of availableGroupBy">{{option.label}}</option>
(ngModelChange)="setQueryProps()">
<option [ngValue]="option.key" *ngFor="let option of availableGroupBy">{{option.label}}</option>
</select>
<wp-embedded-graph #wpEmbeddedGraphMulti

@ -271,9 +271,11 @@ describe 'Custom actions', type: :feature, js: true do
retry_block do
new_ca_page.visit!
new_ca_page.set_name('Move project')
# Add date custom action which has a different admin layout
select date_custom_field.name, from: 'Add action'
select 'on', from: date_custom_field.name
date = (Date.today + 5.days).to_s
new_ca_page.add_action(date_custom_field.name, date)
page.find_field("custom_action_actions_custom_field_#{date_custom_field.id}", with: date)
fill_in "custom_action_actions_custom_field_#{date_custom_field.id}_visible", with: date
# Close autocompleter
if page.has_selector? '.ui-datepicker-close'

@ -508,9 +508,17 @@ describe CustomActions::Actions::CustomField, type: :model do
it_behaves_like 'string custom action validations'
end
context 'for a date custom field' do
let(:custom_field) { date_custom_field }
it_behaves_like 'date custom action validations'
end
end
describe '#apply' do
let(:work_package) { double('work_package') }
%i[list
version
bool
@ -523,7 +531,6 @@ describe CustomActions::Actions::CustomField, type: :model do
list_multi].each do |type|
let(:custom_field) { send(:"#{type}_custom_field") }
let(:work_package) { double('work_package') }
it "sets the value for #{type} custom fields" do
expect(work_package)
@ -535,5 +542,19 @@ describe CustomActions::Actions::CustomField, type: :model do
instance.apply(work_package)
end
end
context 'for a date custom field' do
let(:custom_field) { date_custom_field }
it "sets the value to today for a dynamic value" do
expect(work_package)
.to receive(:"custom_field_#{custom_field.id}=")
.with(Date.today)
instance.values = '%CURRENT_DATE%'
instance.apply(work_package)
end
end
end
end

@ -39,7 +39,18 @@ describe CustomActions::Actions::Date, type: :model do
let(:work_package) { FactoryBot.build_stubbed(:stubbed_work_package) }
it 'sets both start and finish date to the action\'s value' do
instance.values = [Date.today]
instance.values = [Date.today + 5]
instance.apply(work_package)
expect(work_package.start_date)
.to eql Date.today + 5
expect(work_package.due_date)
.to eql Date.today + 5
end
it 'sets both start and finish date to the current date if so specified' do
instance.values = ['%CURRENT_DATE%']
instance.apply(work_package)

@ -35,24 +35,15 @@ describe CustomActions::Actions::DueDate, type: :model do
let(:value) { Date.today }
it_behaves_like 'base custom action' do
describe '#apply' do
let(:work_package) { FactoryBot.build_stubbed(:stubbed_work_package) }
it 'sets the due_date to the action\'s value' do
instance.values = [Date.today]
instance.apply(work_package)
expect(work_package.due_date)
.to eql Date.today
end
end
describe '#multi_value?' do
it 'is false' do
expect(instance)
.not_to be_multi_value
end
end
it_behaves_like 'date custom action validations'
it_behaves_like 'date values transformation'
it_behaves_like 'date custom action apply'
end
end

@ -35,24 +35,15 @@ describe CustomActions::Actions::StartDate, type: :model do
let(:value) { Date.today }
it_behaves_like 'base custom action' do
describe '#apply' do
let(:work_package) { FactoryBot.build_stubbed(:stubbed_work_package) }
it 'sets the start_date to the action\'s value' do
instance.values = [Date.today]
instance.apply(work_package)
expect(work_package.start_date)
.to eql Date.today
end
end
describe '#multi_value?' do
it 'is false' do
expect(instance)
.not_to be_multi_value
end
end
it_behaves_like 'date custom action validations'
it_behaves_like 'date values transformation'
it_behaves_like 'date custom action apply'
end
end

@ -433,10 +433,10 @@ end
shared_examples_for 'date values transformation' do
describe '#values' do
it 'transforms the values to integers' do
instance.values = ["2015-03-29", Date.today, nil, (Date.today - 1.day).to_datetime, 'bogus']
instance.values = ["2015-03-29", Date.today, nil, (Date.today - 1.day).to_datetime, 'bogus', '%CURRENT_DATE%']
expect(instance.values)
.to match_array [Date.parse("2015-03-29"), Date.today, nil, Date.today - 1.day]
.to match_array [Date.parse("2015-03-29"), Date.today, nil, Date.today - 1.day, '%CURRENT_DATE%']
end
end
end
@ -507,3 +507,27 @@ shared_examples_for 'associated custom condition' do
end
end
end
shared_examples_for 'date custom action apply' do
describe '#apply' do
let(:work_package) { FactoryBot.build_stubbed(:stubbed_work_package) }
it 'sets the daate to the action\'s value' do
instance.values = [Date.today + 5.days]
instance.apply(work_package)
expect(work_package.send(key))
.to eql Date.today + 5.days
end
it 'sets the date to the current date if so specified' do
instance.values = ['%CURRENT_DATE%']
instance.apply(work_package)
expect(work_package.send(key))
.to eql Date.today
end
end
end

Loading…
Cancel
Save