Merge remote-tracking branch 'upstream/release/4.1' into dev

pull/2826/head
Jan Sandbrink 10 years ago
commit 3c3ae18c38
  1. 1
      app/assets/javascripts/application.js.erb
  2. 16
      app/assets/stylesheets/content/_in_place_editing.sass
  3. 2
      frontend/.jshintrc
  4. 13
      frontend/app/config/configuration-service.js
  5. 38
      frontend/app/misc/datepicker-defaults.js
  6. 14
      frontend/app/services/timezone-service.js
  7. 5
      frontend/app/services/work-package-service.js
  8. 3
      frontend/app/templates/components/inplace_editor/date/date_range_picker.html
  9. 1
      frontend/app/templates/components/inplace_editor/display/daterange.html
  10. 1
      frontend/app/templates/components/inplace_editor/editable/daterange.html
  11. 15
      frontend/app/ui_components/date/date-directive.js
  12. 226
      frontend/app/ui_components/date/date-range-picker-directive.js
  13. 2
      frontend/app/ui_components/index.js
  14. 11
      frontend/app/work_packages/directives/inplace_editor/inplace-editor-display-pane-directive.js
  15. 29
      frontend/app/work_packages/services/work-package-field-service.js
  16. 3
      frontend/public/templates/components/inplace_editor/date/date_range_picker.html
  17. 1
      frontend/public/templates/components/inplace_editor/display/daterange.html
  18. 1
      frontend/public/templates/components/inplace_editor/editable/daterange.html
  19. 2248
      frontend/tests/integration/mocks/work-packages/823.json
  20. 2248
      frontend/tests/integration/mocks/work-packages/824.json
  21. 325
      frontend/tests/integration/specs/work-packages/details-pane/date-range-picker-spec.js
  22. 6
      frontend/tests/integration/specs/work-packages/details-pane/details-pane-editable-spec.js
  23. 3
      frontend/tests/integration/specs/work-packages/work-packages-modal-focus-spec.js
  24. 3
      lib/open_project/client_preference_extractor.rb

@ -77,7 +77,6 @@ jQuery(document).ready(function ($) {
return false;
});
});
function checkAll (id, checked) {

@ -17,6 +17,22 @@ $inplace-edit--color--very-dark: #cacaca
opacity: 0.5
*
cursor: wait!important
inplace-edit--write
.inplace-edit--write-value
.date-range-picker
display: table
& > *
display: table-cell
margin-bottom: 0
& > span
padding-right: 5px
padding-left: 5px
.ui-datepicker-current,
.ui-datepicker-close
display: none
#ui-datepicker-div
z-index: 9999 !important
.inplace-edit--form
display: block

@ -5,6 +5,7 @@
"OpenProject",
"_",
"moment",
"angular",
"inject",
@ -18,6 +19,7 @@
"context",
"expect",
"element",
"describe",
"xdescribe",
"it",

@ -76,13 +76,15 @@ module.exports = function() {
return this.settings.user_preferences.time_zone;
},
dateFormatPresent: function() {
return this.displaySettingPresent('date_format') && this.settings.display.date_format != '';
return this.displaySettingPresent('date_format') &&
this.settings.display.date_format !== '';
},
dateFormat: function() {
return this.settings.display.date_format;
},
timeFormatPresent: function() {
return this.displaySettingPresent('time_format') && this.settings.display.time_format != '';
return this.displaySettingPresent('time_format') &&
this.settings.display.time_format !== '';
},
timeFormat: function() {
return this.settings.display.time_format;
@ -90,5 +92,12 @@ module.exports = function() {
isModuleEnabled: function(module) {
return this.settings.enabled_modules.indexOf(module) >= 0;
},
startOfWeekPresent: function() {
return this.displaySettingPresent('start_of_week') &&
this.setting.display.start_of_week !== '';
},
startOfWeek: function() {
return this.settings.display.start_of_week;
}
};
};

@ -25,12 +25,13 @@
//
// See doc/COPYRIGHT.rdoc for more details.
//++
/* global CS */
window.CS = window.CS || {};
jQuery(function($) {
var regions = $.datepicker.regional;
var regional = regions[CS.lang] || regions[""];
var regional = regions[CS.lang] || regions[''];
$.datepicker.setDefaults(regional);
var gotoToday = $.datepicker._gotoToday;
@ -49,7 +50,7 @@ jQuery(function($) {
showWeek: true,
changeMonth: true,
changeYear: true,
yearRange: "c-100:c+10",
yearRange: 'c-100:c+10',
dateFormat: 'yy-mm-dd',
showButtonPanel: true,
calculateWeek: function (day) {
@ -63,9 +64,40 @@ jQuery(function($) {
}
};
if (CS.firstWeekDay && CS.firstWeekDay !== "") {
if (CS.firstWeekDay && CS.firstWeekDay !== '') {
defaults.firstDay = parseInt(CS.firstWeekDay, 10);
}
$.datepicker.setDefaults(defaults);
$.extend($.datepicker, {
// Reference the orignal function so we can override it and call it later
_inlineDatepicker2: $.datepicker._inlineDatepicker,
// Override the _inlineDatepicker method
_inlineDatepicker: function (target, inst) {
// Call the original
this._inlineDatepicker2(target, inst);
var beforeShow = $.datepicker._get(inst, 'beforeShow');
if (beforeShow) {
beforeShow.apply(target, [target, inst]);
}
},
_checkOffsetOriginal: $.datepicker._checkOffset,
_checkOffset: function(inst, offset, isFixed) {
var _offset = $.datepicker._checkOffsetOriginal(inst, offset, isFixed);
var alterOffset = this._get(inst, 'alterOffset');
if (alterOffset) {
var inp = inst.input ? inst.input[0] : null;
// trigger custom callback
return alterOffset.apply(inp, [_offset]);
}
return _offset;
}
});
});

@ -33,8 +33,8 @@ module.exports = function(ConfigurationService, I18n) {
moment.lang(I18n.locale);
},
parseDate: function(date) {
var d = moment.utc(date);
parseDate: function(date, format) {
var d = moment.utc(date, format);
if (ConfigurationService.isTimezoneSet()) {
d.local();
@ -52,6 +52,16 @@ module.exports = function(ConfigurationService, I18n) {
formattedTime: function(date) {
var format = ConfigurationService.timeFormatPresent() ? ConfigurationService.timeFormat() : 'LT';
return TimezoneService.parseDate(date).format(format);
},
formattedISODate: function(date) {
return TimezoneService.parseDate(date).format('YYYY-MM-DD');
},
isValid: function(date) {
var format = ConfigurationService.dateFormatPresent() ?
ConfigurationService.dateFormat() : 'L';
return moment(date, [format]).isValid();
}
};

@ -178,6 +178,11 @@ module.exports = function($http,
_links: {}
};
_.forEach(workPackage.form.pendingChanges, function(value, field) {
if(field == 'date') {
data['startDate'] = value['startDate'];
data['dueDate'] = value['dueDate'];
return;
}
if (WorkPackageFieldService.isSavedAsLink(workPackage, field)) {
data._links[field] = value ? value.links.self.props : { href: null };
} else {

@ -0,0 +1,3 @@
<div class="date-range-picker">
<input type="text" class="start" /><span>-</span><input type="text" class="end" />
</div>

@ -0,0 +1 @@
<op-date date-value="displayPaneController.getReadValue().startDate" no-date-text="displayPaneController.getReadValue().noStartDate"></op-date>&nbsp;&nbsp;-&nbsp;&nbsp;<op-date date-value="displayPaneController.getReadValue().dueDate" no-date-text="displayPaneController.getReadValue().noEndDate"></op-date>

@ -0,0 +1 @@
<op-date-range-picker start-date="fieldController.writeValue.startDate" end-date="fieldController.writeValue.dueDate"></op-date-range-picker>

@ -30,10 +30,21 @@ module.exports = function(TimezoneService) {
return {
restrict: 'EA',
replace: true,
scope: { dateValue: '=', hideTitle: '@' },
scope: { dateValue: '=', hideTitle: '@', noDateText: '=' },
template: '<span title="{{ dateTitle }}">{{date}}</span>',
link: function(scope, element, attrs) {
scope.date = TimezoneService.formattedDate(scope.dateValue);
function setDate(date) {
if(date){
scope.date = TimezoneService.formattedDate(date);
} else {
scope.date = scope.noDateText;
}
}
setDate(scope.dateValue);
scope.$watch('dateValue', function(newVal) {
setDate(newVal);
});
if (!scope.hideTitle) {
scope.dateTitle = scope.date;
}

@ -0,0 +1,226 @@
//-- 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.
//++
module.exports = function(TimezoneService, ConfigurationService,
I18n, $timeout) {
var parseDate = TimezoneService.parseDate,
formattedDate = function(date) {
return TimezoneService.parseDate(date).format('L');
},
formattedISODate = TimezoneService.formattedISODate,
noStartDate = I18n.t('js.label_no_start_date'),
noEndDate = I18n.t('js.label_no_due_date');
return {
restrict: 'EA',
replace: true,
scope: {
'startDate': '=',
'endDate': '='
},
templateUrl: '/templates/components/inplace_editor/date/date_range_picker.html',
link: function(scope, element) {
var startTimerId = 0,
endTimerId = 0,
inputStart = element.find('input.start'),
inputEnd = element.find('input.end'),
prevStartDate = '',
prevEndDate = '',
addClearButton = function (inp) {
setTimeout(function() {
var buttonPane = jQuery('.ui-datepicker-buttonpane');
if(buttonPane.find('.ui-datepicker-clear').length === 0) {
buttonPane.find('.ui-datepicker-clear').remove();
}
jQuery( '<button>', {
text: 'Clear',
click: function() {
inp.val('');
inp.change();
}
})
.addClass('ui-datepicker-clear ui-state-default ui-priority-primary ui-corner-all')
.appendTo(buttonPane);
}, 1);
},
setDate = function(input, date) {
if(date) {
input.datepicker('option', 'defaultDate', formattedDate(date));
input.datepicker('option', 'setDate', formattedDate(date));
input.val(formattedDate(date));
} else {
input.datepicker('option', 'defaultDate', null);
input.datepicker('option', 'setDate', null);
input.val('');
date = null;
}
};
inputStart.attr('placeholder', noStartDate);
inputEnd.attr('placeholder', noEndDate);
inputStart.on('change', function() {
if(inputStart.val().replace(/^\s+|\s+$/g, '') === '') {
$timeout(function() {
scope.startDate = null;
});
inputStart.val('');
$timeout.cancel(startTimerId);
return;
}
$timeout.cancel(startTimerId);
startTimerId = $timeout(function() {
var date = inputStart.val(),
isValid = TimezoneService.isValid(date, 'DD/MM/YYYY');
if(isValid){
scope.startDate = formattedISODate(date);
}
}, 1000);
});
inputEnd.on('change', function() {
if(inputEnd.val().replace(/^\s+|\s+$/g, '') === '') {
$timeout(function() {
scope.endDate = null;
});
inputEnd.val('');
$timeout.cancel(endTimerId);
return;
}
$timeout.cancel(startTimerId);
startTimerId = $timeout(function() {
var date = inputEnd.val(),
isValid = TimezoneService.isValid(date, 'DD/MM/YYYY');
if(isValid){
scope.endDate = formattedISODate(date);
}
}, 1000);
});
inputStart.datepicker({
firstDay: ConfigurationService.startOfWeek(),
showWeeks: true,
changeMonth: true,
numberOfMonths: 2,
showButtonPanel: true,
dateFormat: 'dd/mm/yy',
inline: true,
alterOffset: function(offset) {
var wHeight = jQuery(window).height(),
dpHeight = jQuery('#ui-datepicker-div').height(),
inputTop = inputStart.offset().top,
inputHeight = inputStart.innerHeight();
if((inputTop + inputHeight + dpHeight) > wHeight) {
offset.top -= inputHeight - 4;
}
return offset;
},
beforeShow: function() {
addClearButton(inputStart);
},
onChangeMonthYear: function() {
addClearButton(inputStart);
},
onClose: function(selectedDate) {
if(!selectedDate || selectedDate === '' || selectedDate === prevStartDate) {
return;
}
var parsedDate = parseDate(selectedDate, 'DD/MM/YYYY');
prevStartDate = parsedDate;
$timeout(function() {
scope.startDate = formattedISODate(parsedDate);
});
inputEnd.datepicker('option', 'minDate', selectedDate ? selectedDate : null);
}
});
inputEnd.datepicker({
firstDay: ConfigurationService.startOfWeek(),
showWeeks: true,
changeMonth: true,
numberOfMonths: 2,
dateFormat: 'dd/mm/yy',
inline: true,
alterOffset: function(offset) {
var wHeight = jQuery(window).height(),
dpHeight = jQuery('#ui-datepicker-div').height(),
inputTop = inputEnd.offset().top,
inputHeight = inputEnd.innerHeight();
if((inputTop + inputHeight + dpHeight) > wHeight) {
offset.top -= inputHeight - 4;
}
return offset;
},
beforeShow: function() {
addClearButton(inputEnd);
},
onChangeMonthYear: function() {
addClearButton(inputEnd);
},
onClose: function(selectedDate) {
if(!selectedDate || selectedDate === '' || selectedDate === prevEndDate) {
return;
}
var parsedDate = parseDate(selectedDate, 'DD/MM/YYYY');
prevEndDate = parsedDate;
$timeout(function() {
scope.endDate = formattedISODate(parsedDate);
});
inputStart.datepicker('option', 'maxDate', selectedDate ? selectedDate : null);
}
});
if(scope.endDate) {
prevEndDate = formattedDate(scope.endDate);
inputStart.datepicker('option', 'maxDate', formattedDate(scope.endDate));
}
if(scope.startDate) {
prevStartDate = formattedDate(scope.startDate);
inputEnd.datepicker('option', 'minDate', formattedDate(scope.startDate));
}
setDate(inputStart, scope.startDate);
setDate(inputEnd, scope.endDate);
angular.element('.work-packages--details-content').scroll(function() {
inputStart.datepicker('hide');
inputEnd.datepicker('hide');
angular.element('#ui-datepicker-div').blur();
});
angular.element(window).resize(function() {
inputStart.datepicker('hide');
inputEnd.datepicker('hide');
angular.element('#ui-datepicker-div').blur();
});
}
};
};

@ -46,6 +46,8 @@ angular.module('openproject.uiComponents')
.directive('opTime', ['TimezoneService', require('./date/time-directive')])
.directive('opDateTime', ['$compile', 'TimezoneService', require('./date/date-time-directive')])
.directive('emptyElement', [require('./empty-element-directive')])
.directive('opDateRangePicker', ['TimezoneService', 'ConfigurationService',
'I18n', '$timeout', require('./date/date-range-picker-directive')])
.constant('ENTER_KEY', 13)
.directive('executeOnEnter', ['ENTER_KEY', require(
'./execute-on-enter-directive')])

@ -80,12 +80,11 @@ module.exports = function(
link: function(scope, element, attrs, fieldController) {
scope.fieldController = fieldController;
scope.displayPaneController.field = scope.fieldController.field;
scope.templateUrl = '/templates/components/inplace_editor/display/' +
WorkPackageFieldService.getInplaceDisplayStrategy(
EditableFieldsState.workPackage,
fieldController.field
) +
'.html';
var type = WorkPackageFieldService.getInplaceDisplayStrategy(
EditableFieldsState.workPackage,
fieldController.field
);
scope.templateUrl = '/templates/components/inplace_editor/display/' + type +'.html';
// TODO: extract this when more placeholders come
if (fieldController.field === 'description') {

@ -42,7 +42,7 @@ module.exports = function(
// TODO: extract to strategy if new cases arise
if (field === 'date') {
// nope
return false;
return true;
//return workPackage.schema.props.startDate.writable
// && workPackage.schema.props.dueDate.writable;
}
@ -71,6 +71,12 @@ module.exports = function(
}
function getValue(workPackage, field) {
if (field === 'date') {
return {
startDate: workPackage.props['startDate'],
dueDate: workPackage.props['dueDate']
};
}
if (!_.isUndefined(workPackage.props[field])) {
return workPackage.props[field];
}
@ -178,12 +184,16 @@ module.exports = function(
function getInplaceEditStrategy(workPackage, field) {
var fieldType = null,
inplaceType = 'text';
if (field === 'date') {
fieldType = 'DateRange';
} else {
fieldType = workPackage.form.embedded.schema.props[field].type;
}
switch(fieldType) {
case 'DateRange':
inplaceType = 'daterange';
break;
case 'Float':
inplaceType = 'float';
break;
@ -238,7 +248,6 @@ module.exports = function(
case 'Integer':
case 'Float':
case 'Duration':
case 'DateRange':
case 'Date':
case 'Boolean':
displayStrategy = 'text';
@ -255,6 +264,9 @@ module.exports = function(
case 'User':
displayStrategy = 'user';
break;
case 'DateRange':
displayStrategy = 'daterange';
break;
}
//workPackageOverviewAttributes
@ -272,13 +284,12 @@ module.exports = function(
function format(workPackage, field) {
if (field === 'date') {
var displayedStartDate =
WorkPackagesHelper.formatValue(workPackage.props.startDate, 'startDate') ||
I18n.t('js.label_no_start_date'),
displayedEndDate =
WorkPackagesHelper.formatValue(workPackage.props.dueDate, 'dueDate') ||
I18n.t('js.label_no_due_date');
return displayedStartDate + ' - ' + displayedEndDate;
return {
startDate: workPackage.props.startDate,
dueDate: workPackage.props.dueDate,
noStartDate: I18n.t('js.label_no_start_date'),
noEndDate: I18n.t('js.label_no_due_date')
};
}
var value = workPackage.props[field];

@ -0,0 +1,3 @@
<div class="date-range-picker">
<input ng-model="editableStartDate" type="text" class="start" /><span>-</span><input ng-model="editableEndDate" type="text" class="end" />
</div>

@ -0,0 +1 @@
<op-date date-value="readValue.startDate" no-date-text="readValue.noStartDate"></op-date> - <op-date date-value="readValue.dueDate" no-date-text="readValue.noEndDate"></op-date>

@ -0,0 +1 @@
<op-date-range-picker start-date="dataObject.startDate" end-date="dataObject.dueDate"></op-date-range-picker>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,325 @@
//-- 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.
//++
/* jshint ignore:start */
var expect = require('../../../spec_helper.js').expect,
detailsPaneHelper = require('./details-pane-helper.js');
describe('details pane', function() {
var dateRangePicker;
describe('date range picker', function() {
beforeEach(function() {
detailsPaneHelper.loadPane(819, 'overview');
dateRangePicker = element(by.css('.inplace-edit.attribute-date'));
});
context('read value', function() {
it('should be present on page', function(){
expect(dateRangePicker.isDisplayed()).to.eventually.be.true;
});
it('shows date range', function() {
expect(dateRangePicker.getText()).to.eventually.equal('02/17/2015\n - \n04/29/2015');
});
});
context('write value', function() {
var startDate, endDate;
beforeEach(function() {
startDate = dateRangePicker.$('input.start');
endDate = dateRangePicker.$('input.end');
});
beforeEach(function() {
dateRangePicker.$('.inplace-edit--read-value').click();
});
it('opens calendar on click', function() {
startDate.click();
expect($('.ui-datepicker').isDisplayed()).to.eventually.be.true;
});
it('shows date range in input', function() {
startDate.getText(function(text) {
expect(text).to.equal('10/23/2014');
});
endDate.getText(function(text) {
expect(text).to.equal('12/27/2014');
});
});
describe('validation', function() {
it('validates valid start date', function() {
startDate.clear();
startDate.sendKeys('10/24/2014');
startDate.getText(function(text) {
expect(text).to.equal('10/24/2014');
});
});
it('validates valid end date', function() {
endDate.clear();
endDate.sendKeys('11/27/2014');
endDate.getText(function(text) {
expect(text).to.equal('11/27/2014');
});
});
it('doesn\'t validate invalid start date', function() {
startDate.clear();
startDate.sendKeys('13/24/2014');
startDate.getText(function(text) {
expect(text).to.equal('10/23/2014');
});
});
it('doesn\'t validate invalid end date', function() {
endDate.clear();
endDate.sendKeys('11/40/2014');
endDate.getText(function(text) {
expect(text).to.equal('12/27/2014');
});
});
it('validates empty start date', function() {
startDate.clear();
startDate.getText(function(text) {
expect(text).to.equal('no start date');
});
});
it('validates empty end date', function() {
endDate.clear();
endDate.getText(function(text) {
expect(text).to.equal('no end date');
});
});
});
describe('range selection', function() {
it('changes start date by clicking on calendar', function() {
startDate.click();
element.all(by.css('a.ui-state-default')).filter(function(elem) {
return elem.getText().then(function(text) {
return text.indexOf('9') !== -1;
});
}).then(function(filteredElements) {
filteredElements[0].click();
startDate.getText(function(text) {
expect(text).to.equal('12/09/2014');
});
endDate.getText(function(text) {
expect(text).to.equal('12/17/2014');
});
});
});
it('changes end date by clicking on calendar', function() {
endDate.click();
element.all(by.css('a.ui-state-default')).filter(function(elem){
return elem.getText().then(function(text) {
return text.indexOf('17') !== -1;
});
}).then(function(filteredElements) {
filteredElements[0].click();
startDate.getText(function(text) {
expect(text).to.equal('09/23/2014');
});
endDate.getText(function(text) {
expect(text).to.equal('12/17/2014');
});
});
});
});
});
});
describe('date range picker with start null date', function() {
beforeEach(function() {
detailsPaneHelper.loadPane(823, 'overview');
dateRangePicker = element(by.css('.inplace-edit.attribute-date'));
});
context('read value', function() {
it('should be present on page', function(){
expect(dateRangePicker.isDisplayed()).to.eventually.be.true;
});
it('shows date range', function() {
expect(dateRangePicker.getText()).to.eventually.equal('no start date\n - \n12/27/2014');
});
});
context('write value', function() {
var startDate, endDate;
beforeEach(function() {
startDate = dateRangePicker.$('input.start');
endDate = dateRangePicker.$('input.end');
});
beforeEach(function() {
dateRangePicker.$('.inplace-edit--read-value').click();
});
it('opens calendar on click', function() {
startDate.click();
expect($('.ui-datepicker').isDisplayed()).to.eventually.be.true;
});
it('shows date range in input', function() {
startDate.getText(function(text) {
expect(text).to.equal('no start date');
});
endDate.getText(function(text) {
expect(text).to.equal('12/27/2014');
});
});
describe('range selection', function() {
it('changes start date by clicking on calendar', function() {
startDate.click();
element.all(by.css('a.ui-state-default')).filter(function(elem){
return elem.getText().then(function(text) {
return text.indexOf('9') !== -1;
});
}).then(function(filteredElements) {
filteredElements[0].click();
startDate.getText(function(text) {
expect(text).to.equal('12/09/2014');
});
endDate.getText(function(text) {
expect(text).to.equal('12/17/2014');
});
});
});
it('changes end date by clicking on calendar', function() {
endDate.click();
element.all(by.css('a.ui-state-default')).filter(function(elem){
return elem.getText().then(function(text) {
return text.indexOf('17') !== -1;
});
}).then(function(filteredElements) {
filteredElements[0].click();
startDate.getText(function(text) {
expect(text).to.equal('09/23/2014');
});
endDate.getText(function(text) {
expect(text).to.equal('12/17/2014');
});
});
});
});
});
});
describe('date range picker with due null date', function() {
beforeEach(function() {
detailsPaneHelper.loadPane(824, 'overview');
dateRangePicker = element(by.css('.inplace-edit.attribute-date'));
});
context('read value', function() {
it('should be present on page', function(){
expect(dateRangePicker.isDisplayed()).to.eventually.be.true;
});
it('shows date range', function() {
expect(dateRangePicker.getText()).to.eventually.equal('10/23/2014\n - \nno end date');
});
});
context('write value', function() {
var startDate, endDate;
beforeEach(function() {
startDate = dateRangePicker.$('input.start');
endDate = dateRangePicker.$('input.end');
});
beforeEach(function() {
dateRangePicker.$('.inplace-edit--read-value').click();
});
it('opens calendar on click', function() {
startDate.click();
expect($('.ui-datepicker').isDisplayed()).to.eventually.be.true;
});
it('shows date range in input', function() {
startDate.getText(function(text) {
expect(text).to.equal('10/23/2014');
});
endDate.getText(function(text) {
expect(text).to.equal('no end date');
});
});
describe('range selection', function() {
it('changes start date by clicking on calendar', function() {
startDate.click();
element.all(by.css('a.ui-state-default')).filter(function(elem){
return elem.getText().then(function(text) {
return text.indexOf('9') !== -1;
});
}).then(function(filteredElements) {
filteredElements[0].click();
startDate.getText(function(text) {
expect(text).to.equal('12/09/2014');
});
endDate.getText(function(text) {
expect(text).to.equal('12/17/2014');
});
});
});
it('changes end date by clicking on calendar', function() {
endDate.click();
element.all(by.css('a.ui-state-default')).filter(function(elem){
return elem.getText().then(function(text) {
return text.indexOf('17') !== -1;
});
}).then(function(filteredElements) {
filteredElements[0].click();
endDate.getText(function(text) {
expect(text).to.equal('09/23/2014');
});
endDate.getText(function(text) {
expect(text).to.equal('12/17/2014');
});
});
});
});
});
});
});
/* jshint ignore:end */

@ -78,7 +78,11 @@ describe('OpenProject', function(){
}
describe('subject', function() {
var subjectEditor = $('.inplace-edit.attribute-subject');
var subjectEditor;
beforeEach(function() {
subjectEditor = element(by.css('.inplace-edit.attribute-subject'));
});
context('work package with update link', function() {
beforeEach(function() {

@ -48,7 +48,10 @@ describe('OpenProject', function() {
it('sorting modal should focus', function() {
element(by.css('#work-packages-settings-button')).click();
element(by.css('[ng-click="showSortingModal($event)"]')).click();
//don't why, but if to do the request twice the test is green
browser.driver.switchTo().activeElement().getAttribute('id');
browser.driver.switchTo().activeElement().getAttribute('id').then(function (elementId) {
browser.waitForAngular();
expect(element(by.css('.ng-modal-window .form--row:first-child input.ui-select-focusser')).getAttribute('id'))
.to.eventually.equal(elementId);
});

@ -34,7 +34,8 @@ module OpenProject
user_preferences: user_preferences,
display: {
date_format: momentjstify_date_format(Setting.date_format),
time_format: momentjstify_time_format(Setting.time_format)
time_format: momentjstify_time_format(Setting.time_format),
start_of_week: Setting.start_of_week
},
pagination: {
per_page_options: Setting.per_page_options_array

Loading…
Cancel
Save