From 43d5a600f1ca508e425da41e63b65c3b6e553892 Mon Sep 17 00:00:00 2001 From: mhirtie Date: Wed, 4 Mar 2015 16:43:53 +0200 Subject: [PATCH 01/30] Added date range picker on details pane. --- frontend/app/services/timezone-service.js | 4 + .../date/date-range-directive.js | 77 +++++++++++++++++++ frontend/app/ui_components/index.js | 1 + .../inplace_editor/display/daterange.html | 1 + .../inplace_editor/editable/daterange.html | 1 + 5 files changed, 84 insertions(+) create mode 100644 frontend/app/ui_components/date/date-range-directive.js create mode 100644 frontend/public/templates/components/inplace_editor/display/daterange.html create mode 100644 frontend/public/templates/components/inplace_editor/editable/daterange.html diff --git a/frontend/app/services/timezone-service.js b/frontend/app/services/timezone-service.js index 04a0d86d2e..1b157a3b6a 100644 --- a/frontend/app/services/timezone-service.js +++ b/frontend/app/services/timezone-service.js @@ -52,6 +52,10 @@ 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).toISOString().split('T')[0]; } }; diff --git a/frontend/app/ui_components/date/date-range-directive.js b/frontend/app/ui_components/date/date-range-directive.js new file mode 100644 index 0000000000..82dca95ac6 --- /dev/null +++ b/frontend/app/ui_components/date/date-range-directive.js @@ -0,0 +1,77 @@ +//-- 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, $timeout) { + return { + restrict: 'EA', + replace: true, + scope: { + startDate: '=', + endDate: '=' + }, + template: '
', + link: function(scope, element, attrs) { + var previous = -1, + current = -1, + div = element.find('div'), + input = element.find('input'); + + div.datepicker({ + onSelect: function(dateText, inst) { + previous = +current; + current = inst.selectedDay; + if(previous == -1 || previous == current) { + previous = current; + input.val(dateText); + } else { + $timeout(function(){ + scope.startDate = TimezoneService.formattedDate(new Date(inst.selectedYear, inst.selectedMonth, Math.min(previous,current))); + scope.endDate = TimezoneService.formattedDate(new Date(inst.selectedYear, inst.selectedMonth, Math.max(previous,current))); + + input.val(scope.startDate + ' - ' + scope.endDate); + }); + } + }, + beforeShowDay: function(selectedDay) { + return [true, ((selectedDay.getDate() >= Math.min(previous, current) && selectedDay.getDate() <= Math.max(previous, current)) ? 'date-range-selected' : '')] + } + }) + .position({ + my: 'left top', + at: 'left bottom', + of: '.daterange input' + }); + + div.datepicker('setDate', TimezoneService.parseDate(scope.startDate).toDate()); + angular.element('.ui-datepicker-current-day').click(); + + div.datepicker('setDate', TimezoneService.parseDate(scope.endDate).toDate()); + angular.element('.ui-datepicker-current-day').click(); + } + }; +}; diff --git a/frontend/app/ui_components/index.js b/frontend/app/ui_components/index.js index 8bc4b34c97..b3c1601225 100644 --- a/frontend/app/ui_components/index.js +++ b/frontend/app/ui_components/index.js @@ -46,6 +46,7 @@ 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('opDateRange', ['TimezoneService', '$timeout', require('./date/date-range-directive')]) .constant('ENTER_KEY', 13) .directive('executeOnEnter', ['ENTER_KEY', require( './execute-on-enter-directive')]) diff --git a/frontend/public/templates/components/inplace_editor/display/daterange.html b/frontend/public/templates/components/inplace_editor/display/daterange.html new file mode 100644 index 0000000000..8b800382e9 --- /dev/null +++ b/frontend/public/templates/components/inplace_editor/display/daterange.html @@ -0,0 +1 @@ + - \ No newline at end of file diff --git a/frontend/public/templates/components/inplace_editor/editable/daterange.html b/frontend/public/templates/components/inplace_editor/editable/daterange.html new file mode 100644 index 0000000000..d9226081df --- /dev/null +++ b/frontend/public/templates/components/inplace_editor/editable/daterange.html @@ -0,0 +1 @@ + From 89aa61b258a233d7b31da50d486266333c2f4259 Mon Sep 17 00:00:00 2001 From: mhirtie Date: Thu, 5 Mar 2015 12:18:19 +0200 Subject: [PATCH 02/30] Fix updating of date range in initial spans. --- frontend/app/services/timezone-service.js | 2 +- frontend/app/ui_components/date/date-directive.js | 3 +++ .../app/ui_components/date/date-range-directive.js | 13 +++++++++---- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/frontend/app/services/timezone-service.js b/frontend/app/services/timezone-service.js index 1b157a3b6a..c2d8503709 100644 --- a/frontend/app/services/timezone-service.js +++ b/frontend/app/services/timezone-service.js @@ -55,7 +55,7 @@ module.exports = function(ConfigurationService, I18n) { }, formattedISODate: function(date) { - return TimezoneService.parseDate(date).toISOString().split('T')[0]; + return TimezoneService.parseDate(date).format('YYYY-MM-DD'); } }; diff --git a/frontend/app/ui_components/date/date-directive.js b/frontend/app/ui_components/date/date-directive.js index 62230fec81..815df14e7e 100644 --- a/frontend/app/ui_components/date/date-directive.js +++ b/frontend/app/ui_components/date/date-directive.js @@ -34,6 +34,9 @@ module.exports = function(TimezoneService) { template: '{{date}}', link: function(scope, element, attrs) { scope.date = TimezoneService.formattedDate(scope.dateValue); + scope.$watch('dateValue', function(newVal){ + scope.date = TimezoneService.formattedDate(newVal); + }); if (!scope.hideTitle) { scope.dateTitle = scope.date; } diff --git a/frontend/app/ui_components/date/date-range-directive.js b/frontend/app/ui_components/date/date-range-directive.js index 82dca95ac6..6be7d7abd8 100644 --- a/frontend/app/ui_components/date/date-range-directive.js +++ b/frontend/app/ui_components/date/date-range-directive.js @@ -39,7 +39,9 @@ module.exports = function(TimezoneService, $timeout) { var previous = -1, current = -1, div = element.find('div'), - input = element.find('input'); + input = element.find('input'), + startDate = '', + endDate = ''; div.datepicker({ onSelect: function(dateText, inst) { @@ -49,11 +51,14 @@ module.exports = function(TimezoneService, $timeout) { previous = current; input.val(dateText); } else { + var start = new Date(inst.selectedYear, inst.selectedMonth, Math.min(previous,current)), + end = new Date(inst.selectedYear, inst.selectedMonth, Math.max(previous,current)); $timeout(function(){ - scope.startDate = TimezoneService.formattedDate(new Date(inst.selectedYear, inst.selectedMonth, Math.min(previous,current))); - scope.endDate = TimezoneService.formattedDate(new Date(inst.selectedYear, inst.selectedMonth, Math.max(previous,current))); + scope.startDate = TimezoneService.formattedISODate(start); + scope.endDate = TimezoneService.formattedISODate(end); + console.log(scope.startDate, scope.endDate); - input.val(scope.startDate + ' - ' + scope.endDate); + input.val(TimezoneService.formattedDate(start) + ' - ' + TimezoneService.formattedDate(end)); }); } }, From 9f83ee5cd7c67d33abec051942453d58cb0503ba Mon Sep 17 00:00:00 2001 From: mhirtie Date: Thu, 5 Mar 2015 12:32:17 +0200 Subject: [PATCH 03/30] Fix missed semicolon and line length. --- .../ui_components/date/date-range-directive.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/frontend/app/ui_components/date/date-range-directive.js b/frontend/app/ui_components/date/date-range-directive.js index 6be7d7abd8..2c7730f69d 100644 --- a/frontend/app/ui_components/date/date-range-directive.js +++ b/frontend/app/ui_components/date/date-range-directive.js @@ -35,13 +35,11 @@ module.exports = function(TimezoneService, $timeout) { endDate: '=' }, template: '
', - link: function(scope, element, attrs) { + link: function(scope, element) { var previous = -1, current = -1, div = element.find('div'), - input = element.find('input'), - startDate = '', - endDate = ''; + input = element.find('input'); div.datepicker({ onSelect: function(dateText, inst) { @@ -56,14 +54,16 @@ module.exports = function(TimezoneService, $timeout) { $timeout(function(){ scope.startDate = TimezoneService.formattedISODate(start); scope.endDate = TimezoneService.formattedISODate(end); - console.log(scope.startDate, scope.endDate); - input.val(TimezoneService.formattedDate(start) + ' - ' + TimezoneService.formattedDate(end)); + input.val(TimezoneService.formattedDate(start) + ' - ' + + TimezoneService.formattedDate(end)); }); } }, beforeShowDay: function(selectedDay) { - return [true, ((selectedDay.getDate() >= Math.min(previous, current) && selectedDay.getDate() <= Math.max(previous, current)) ? 'date-range-selected' : '')] + var isSelected = selectedDay.getDate() >= Math.min(previous, current) && + selectedDay.getDate() <= Math.max(previous, current); + return [true, (isSelected ? 'date-range-selected' : '')]; } }) .position({ @@ -73,10 +73,10 @@ module.exports = function(TimezoneService, $timeout) { }); div.datepicker('setDate', TimezoneService.parseDate(scope.startDate).toDate()); - angular.element('.ui-datepicker-current-day').click(); + div.find('.ui-datepicker-current-day').click(); div.datepicker('setDate', TimezoneService.parseDate(scope.endDate).toDate()); - angular.element('.ui-datepicker-current-day').click(); + div.find('.ui-datepicker-current-day').click(); } }; }; From 704bbc6cb80bac371af9d91c31ae22dde844b875 Mon Sep 17 00:00:00 2001 From: mhirtie Date: Thu, 5 Mar 2015 17:40:33 +0200 Subject: [PATCH 04/30] Add of manual editing of date in input. --- .../date/date-range-directive.js | 78 ++++++++++++++----- 1 file changed, 57 insertions(+), 21 deletions(-) diff --git a/frontend/app/ui_components/date/date-range-directive.js b/frontend/app/ui_components/date/date-range-directive.js index 2c7730f69d..acb7ea778d 100644 --- a/frontend/app/ui_components/date/date-range-directive.js +++ b/frontend/app/ui_components/date/date-range-directive.js @@ -27,6 +27,11 @@ //++ module.exports = function(TimezoneService, $timeout) { + var datePattern = /^(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[012])\/\d{4}$/i, + parseDate = TimezoneService.parseDate, + formattedDate = TimezoneService.formattedDate, + formattedISODate = TimezoneService.formattedISODate; + return { restrict: 'EA', replace: true, @@ -34,36 +39,54 @@ module.exports = function(TimezoneService, $timeout) { startDate: '=', endDate: '=' }, - template: '
', + template: '
', link: function(scope, element) { - var previous = -1, - current = -1, + var previous, + current, div = element.find('div'), - input = element.find('input'); + input = element.find('input'), + setDate = function(date) { + div.datepicker('setDate', parseDate(date).toDate()); + div.find('.ui-datepicker-current-day').click(); + }; + + scope.change = function(scope) { + var range = scope.daterange.split(/\s+?-\s+?/i), + isMatching = range.every(function(date) { + return datePattern.test(date) + }); + + if(isMatching) { + range.forEach(function(date) { + setDate(date); + }); + } + }; div.datepicker({ onSelect: function(dateText, inst) { - previous = +current; - current = inst.selectedDay; + previous = current; + current = parseDate(new Date(inst.selectedYear, inst.selectedMonth, inst.selectedDay)); if(previous == -1 || previous == current) { previous = current; - input.val(dateText); + input.val(formattedDate(current)); } else { - var start = new Date(inst.selectedYear, inst.selectedMonth, Math.min(previous,current)), - end = new Date(inst.selectedYear, inst.selectedMonth, Math.max(previous,current)); + var start = minDate(current, previous), + end = maxDate(current, previous); + $timeout(function(){ - scope.startDate = TimezoneService.formattedISODate(start); - scope.endDate = TimezoneService.formattedISODate(end); + scope.startDate = formattedISODate(start); + scope.endDate = formattedISODate(end); - input.val(TimezoneService.formattedDate(start) + ' - ' + - TimezoneService.formattedDate(end)); + input.val(formattedDate(start) + ' - ' + + formattedDate(end)); }); } }, beforeShowDay: function(selectedDay) { - var isSelected = selectedDay.getDate() >= Math.min(previous, current) && - selectedDay.getDate() <= Math.max(previous, current); - return [true, (isSelected ? 'date-range-selected' : '')]; + var isSelected = parseDate(selectedDay) >= minDate(current, previous) && + parseDate(selectedDay) <= maxDate(current, previous); + return [true, isSelected ? 'date-range-selected' : '']; } }) .position({ @@ -72,11 +95,24 @@ module.exports = function(TimezoneService, $timeout) { of: '.daterange input' }); - div.datepicker('setDate', TimezoneService.parseDate(scope.startDate).toDate()); - div.find('.ui-datepicker-current-day').click(); - - div.datepicker('setDate', TimezoneService.parseDate(scope.endDate).toDate()); - div.find('.ui-datepicker-current-day').click(); + setDate(scope.startDate); + setDate(scope.endDate); } }; + + function minDate(firstDate, secondDate) { + if(secondDate && firstDate && firstDate.isAfter(secondDate)) { + return secondDate; + } + + return firstDate; + } + + function maxDate(firstDate, secondDate) { + if(secondDate && firstDate && !firstDate.isAfter(secondDate)) { + return secondDate; + } + + return firstDate; + } }; From 4ebe6b44924a87aeeaa76b34c5f03607955e8224 Mon Sep 17 00:00:00 2001 From: mhirtie Date: Thu, 5 Mar 2015 17:45:39 +0200 Subject: [PATCH 05/30] Add semicolon to the end of line. --- frontend/app/ui_components/date/date-range-directive.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/app/ui_components/date/date-range-directive.js b/frontend/app/ui_components/date/date-range-directive.js index acb7ea778d..3bf0c7c6fc 100644 --- a/frontend/app/ui_components/date/date-range-directive.js +++ b/frontend/app/ui_components/date/date-range-directive.js @@ -53,7 +53,7 @@ module.exports = function(TimezoneService, $timeout) { scope.change = function(scope) { var range = scope.daterange.split(/\s+?-\s+?/i), isMatching = range.every(function(date) { - return datePattern.test(date) + return datePattern.test(date); }); if(isMatching) { From 838d1960c99b66ae1e9155b3ce940804dc61e7c7 Mon Sep 17 00:00:00 2001 From: mhirtie Date: Mon, 9 Mar 2015 13:45:54 +0200 Subject: [PATCH 06/30] Add tests for date range picker. --- .../details-pane/date-range-picker-spec.js | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 frontend/tests/integration/specs/work-packages/details-pane/date-range-picker-spec.js diff --git a/frontend/tests/integration/specs/work-packages/details-pane/date-range-picker-spec.js b/frontend/tests/integration/specs/work-packages/details-pane/date-range-picker-spec.js new file mode 100644 index 0000000000..ab7d7c8418 --- /dev/null +++ b/frontend/tests/integration/specs/work-packages/details-pane/date-range-picker-spec.js @@ -0,0 +1,105 @@ +//-- 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. +//++ + +var expect = require('../../../spec_helper.js').expect, + detailsPaneHelper = require('./details-pane-helper.js'); + + +describe('details pane', function() { + var dateRangePicker; + + beforeEach(function() { + detailsPaneHelper.loadPane(819, 'overview'); + dateRangePicker = $('.inplace-editor.type-daterange'); + }); + + describe('date range picker', function() { + context('read value', function() { + it('should be present on page', function(){ + expect(dateRangePicker.isPresent()).to.eventually.be.true; + }); + + it('shows date range', function() { + expect(dateRangePicker.getText()).to.eventually.equal("10/23/2014 - 12/27/2014"); + }); + }); + + context('write value', function() { + beforeEach(function() { + dateRangePicker.$('.ined-read-value').click(); + }); + + it('opens calendar on click', function() { + expect(dateRangePicker.$('.ui-datepicker').isDisplayed()).to.eventually.be.true; + }); + + it('shows date range in input', function() { + dateRangePicker.$("[ng-model='daterange']").getText(function(text) { + expect(text).to.equal("10/23/2014 - 12/27/2014"); + }); + }); + + describe('range selection', function() { + it('changes start date by clicking on calendar', function() { + element.all(by.css("a.ui-state-default")).filter(function(elem, index){ + return elem.getText().then(function(text) { + return text.indexOf('9') !== -1; + }); + }).then(function(filteredElements) { + filteredElements[0].click(); + dateRangePicker.$("[ng-model='daterange']").getText(function(text) { + expect(text).to.equal("12/09/2014 - 12/27/2014"); + }); + }); + }); + + it('changes end date by clicking on calendar', function() { + element.all(by.css("a.ui-state-default")).filter(function(elem, index){ + return elem.getText().then(function(text) { + return text.indexOf('17') !== -1; + }); + }).then(function(filteredElements) { + filteredElements[0].click(); + dateRangePicker.$("[ng-model='daterange']").getText(function(text) { + expect(text).to.equal("09/23/2014 - 12/17/2014"); + }); + }); + }); + + it('doesn\'t change start date month by clicking on calendar', function() { + element.all(by.css('.ui-datepicker-next')).then(function(elem) { + elem[0].click(); + dateRangePicker.$("[ng-model='daterange']").getText(function(text) { + expect(text).to.equal("09/23/2014 - 12/17/2015"); + }); + }); + }); + }); + }); + }); +}); From d41d44baa84164532b08555aa1b652b5cb46b570 Mon Sep 17 00:00:00 2001 From: mhirtie Date: Tue, 10 Mar 2015 09:47:40 +0200 Subject: [PATCH 07/30] Fix date range picker spec. --- .../work-packages/details-pane/date-range-picker-spec.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/frontend/tests/integration/specs/work-packages/details-pane/date-range-picker-spec.js b/frontend/tests/integration/specs/work-packages/details-pane/date-range-picker-spec.js index ab7d7c8418..41bd7f4a78 100644 --- a/frontend/tests/integration/specs/work-packages/details-pane/date-range-picker-spec.js +++ b/frontend/tests/integration/specs/work-packages/details-pane/date-range-picker-spec.js @@ -93,9 +93,10 @@ describe('details pane', function() { it('doesn\'t change start date month by clicking on calendar', function() { element.all(by.css('.ui-datepicker-next')).then(function(elem) { - elem[0].click(); - dateRangePicker.$("[ng-model='daterange']").getText(function(text) { - expect(text).to.equal("09/23/2014 - 12/17/2015"); + elem[0].click().then(function() { + dateRangePicker.$("[ng-model='daterange']").getText(function(text) { + expect(text).to.equal("09/23/2014 - 12/17/2015"); + }); }); }); }); From 038f436e35e351b08dc84d97ee30817f37ebcd02 Mon Sep 17 00:00:00 2001 From: mhirtie Date: Tue, 10 Mar 2015 14:46:37 +0200 Subject: [PATCH 08/30] Fix tests. --- .../specs/work-packages/details-pane/date-range-picker-spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/tests/integration/specs/work-packages/details-pane/date-range-picker-spec.js b/frontend/tests/integration/specs/work-packages/details-pane/date-range-picker-spec.js index 41bd7f4a78..235ed837a6 100644 --- a/frontend/tests/integration/specs/work-packages/details-pane/date-range-picker-spec.js +++ b/frontend/tests/integration/specs/work-packages/details-pane/date-range-picker-spec.js @@ -91,7 +91,7 @@ describe('details pane', function() { }); }); - it('doesn\'t change start date month by clicking on calendar', function() { + xit('doesn\'t change start date month by clicking on calendar', function() { element.all(by.css('.ui-datepicker-next')).then(function(elem) { elem[0].click().then(function() { dateRangePicker.$("[ng-model='daterange']").getText(function(text) { From d0cc1790ae04f1dede446c420d03125a90d7ef87 Mon Sep 17 00:00:00 2001 From: mhirtie Date: Tue, 10 Mar 2015 15:08:54 +0200 Subject: [PATCH 09/30] Fix positioning in Firefox --- frontend/app/ui_components/date/date-range-directive.js | 5 ----- .../work-packages/details-pane/date-range-picker-spec.js | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/frontend/app/ui_components/date/date-range-directive.js b/frontend/app/ui_components/date/date-range-directive.js index 3bf0c7c6fc..fd14ec94c5 100644 --- a/frontend/app/ui_components/date/date-range-directive.js +++ b/frontend/app/ui_components/date/date-range-directive.js @@ -88,11 +88,6 @@ module.exports = function(TimezoneService, $timeout) { parseDate(selectedDay) <= maxDate(current, previous); return [true, isSelected ? 'date-range-selected' : '']; } - }) - .position({ - my: 'left top', - at: 'left bottom', - of: '.daterange input' }); setDate(scope.startDate); diff --git a/frontend/tests/integration/specs/work-packages/details-pane/date-range-picker-spec.js b/frontend/tests/integration/specs/work-packages/details-pane/date-range-picker-spec.js index 235ed837a6..41bd7f4a78 100644 --- a/frontend/tests/integration/specs/work-packages/details-pane/date-range-picker-spec.js +++ b/frontend/tests/integration/specs/work-packages/details-pane/date-range-picker-spec.js @@ -91,7 +91,7 @@ describe('details pane', function() { }); }); - xit('doesn\'t change start date month by clicking on calendar', function() { + it('doesn\'t change start date month by clicking on calendar', function() { element.all(by.css('.ui-datepicker-next')).then(function(elem) { elem[0].click().then(function() { dateRangePicker.$("[ng-model='daterange']").getText(function(text) { From 1f592b8b9a1669e7cc79bd67614dc416bd396f4a Mon Sep 17 00:00:00 2001 From: mhirtie Date: Mon, 16 Mar 2015 17:13:39 +0200 Subject: [PATCH 10/30] Fix date range picker. Add button for clearing dates. Now is possible to set one date. Add week days in calendar and the starting of week is possible to set from settings. --- frontend/app/config/configuration-service.js | 8 +- frontend/app/services/timezone-service.js | 33 +---- .../app/ui_components/date/date-directive.js | 4 +- .../date/date-range-directive.js | 119 ++++++++++++++---- frontend/app/ui_components/index.js | 2 +- .../inplace_editor/display/daterange.html | 2 +- .../inplace_editor/editable/daterange.html | 2 +- .../client_preference_extractor.rb | 3 +- 8 files changed, 112 insertions(+), 61 deletions(-) diff --git a/frontend/app/config/configuration-service.js b/frontend/app/config/configuration-service.js index bcb013b529..aa85cf54a4 100644 --- a/frontend/app/config/configuration-service.js +++ b/frontend/app/config/configuration-service.js @@ -90,5 +90,11 @@ 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; + } }; -}; +}; \ No newline at end of file diff --git a/frontend/app/services/timezone-service.js b/frontend/app/services/timezone-service.js index c2d8503709..9c91275ddf 100644 --- a/frontend/app/services/timezone-service.js +++ b/frontend/app/services/timezone-service.js @@ -1,30 +1,3 @@ -//-- 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(ConfigurationService, I18n) { var TimezoneService = { @@ -56,8 +29,12 @@ module.exports = function(ConfigurationService, I18n) { formattedISODate: function(date) { return TimezoneService.parseDate(date).format('YYYY-MM-DD'); + }, + + isValid: function(date) { + return moment(date, [ConfigurationService.dateFormatPresent() ? ConfigurationService.dateFormat() : 'L']).isValid() } }; return TimezoneService; -}; +}; \ No newline at end of file diff --git a/frontend/app/ui_components/date/date-directive.js b/frontend/app/ui_components/date/date-directive.js index 815df14e7e..8a396e6fac 100644 --- a/frontend/app/ui_components/date/date-directive.js +++ b/frontend/app/ui_components/date/date-directive.js @@ -34,8 +34,8 @@ module.exports = function(TimezoneService) { template: '{{date}}', link: function(scope, element, attrs) { scope.date = TimezoneService.formattedDate(scope.dateValue); - scope.$watch('dateValue', function(newVal){ - scope.date = TimezoneService.formattedDate(newVal); + scope.$watch('dateValue', function(newVal) { + scope.date = newVal ? TimezoneService.formattedDate(newVal) : ''; }); if (!scope.hideTitle) { scope.dateTitle = scope.date; diff --git a/frontend/app/ui_components/date/date-range-directive.js b/frontend/app/ui_components/date/date-range-directive.js index fd14ec94c5..3ef53e77f2 100644 --- a/frontend/app/ui_components/date/date-range-directive.js +++ b/frontend/app/ui_components/date/date-range-directive.js @@ -26,10 +26,12 @@ // See doc/COPYRIGHT.rdoc for more details. //++ -module.exports = function(TimezoneService, $timeout) { +module.exports = function(TimezoneService, ConfigurationService, $timeout) { var datePattern = /^(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[012])\/\d{4}$/i, parseDate = TimezoneService.parseDate, - formattedDate = TimezoneService.formattedDate, + formattedDate = function(date) { + return TimezoneService.parseDate(date).format('L'); + }, formattedISODate = TimezoneService.formattedISODate; return { @@ -43,44 +45,87 @@ module.exports = function(TimezoneService, $timeout) { link: function(scope, element) { var previous, current, + timerId, div = element.find('div'), input = element.find('input'), setDate = function(date) { - div.datepicker('setDate', parseDate(date).toDate()); - div.find('.ui-datepicker-current-day').click(); + if(date) { + div.datepicker('setDate', parseDate(date).toDate()); + div.find('.ui-datepicker-current-day').click(); + } + }, + clearDate = function(inst) { + previous = current = null; + var onSelect = jQuery.datepicker._get(inst, "onSelect"); + if (onSelect) { + onSelect.apply(input, inst); // trigger custom callback + } + }, + addClearButton = function (inp, inst) { + setTimeout(function() { + var buttonPane = jQuery(inp) + .find(".ui-datepicker-buttonpane"); + + jQuery( "