From b08c215b726d5558cfb22ada7fb005739b901f45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20GAULIN?= Date: Sat, 12 Dec 2015 00:38:49 +0400 Subject: [PATCH 1/3] Filter lists by dates with two new scope types (date and range) --- modules/backend/lang/en/lang.php | 6 +- modules/backend/lang/fr/lang.php | 6 +- modules/backend/widgets/Filter.php | 113 +++++- .../widgets/filter/partials/_scope_date.htm | 14 + .../widgets/filter/partials/_scope_range.htm | 14 + modules/system/assets/ui/js/filter.dates.js | 344 ++++++++++++++++++ modules/system/assets/ui/less/filter.less | 42 +++ modules/system/assets/ui/storm.js | 1 + modules/system/lang/en/client.php | 14 + modules/system/lang/fr/client.php | 15 + 10 files changed, 566 insertions(+), 3 deletions(-) create mode 100644 modules/backend/widgets/filter/partials/_scope_date.htm create mode 100644 modules/backend/widgets/filter/partials/_scope_range.htm create mode 100644 modules/system/assets/ui/js/filter.dates.js diff --git a/modules/backend/lang/en/lang.php b/modules/backend/lang/en/lang.php index c1215f83f..6ca4effa3 100644 --- a/modules/backend/lang/en/lang.php +++ b/modules/backend/lang/en/lang.php @@ -349,7 +349,11 @@ return [ ], 'filter' => [ 'all' => 'all', - 'options_method_not_exists' => "The model class :model must define a method :method() returning options for the ':filter' filter." + 'options_method_not_exists' => "The model class :model must define a method :method() returning options for the ':filter' filter.", + 'date' => [ + 'all' => 'all period', + 'format' =>'Y-m-d' + ] ], 'import_export' => [ 'upload_csv_file' => '1. Upload a CSV file', diff --git a/modules/backend/lang/fr/lang.php b/modules/backend/lang/fr/lang.php index 4fdaeb8a2..dba5d29ec 100644 --- a/modules/backend/lang/fr/lang.php +++ b/modules/backend/lang/fr/lang.php @@ -350,7 +350,11 @@ return [ ], 'filter' => [ 'all' => 'tous', - 'options_method_not_exists' => "La classe du modèle :model doit définir une méthode :method() qui retourne les options pour le filtre ':filter'." + 'options_method_not_exists' => "La classe du modèle :model doit définir une méthode :method() qui retourne les options pour le filtre ':filter'.", + 'date' => [ + 'all' => 'toute la période', + 'format' =>'d/m/Y' + ] ], 'import_export' => [ 'upload_csv_file' => '1. Envoyer un fichier CSV', diff --git a/modules/backend/widgets/Filter.php b/modules/backend/widgets/Filter.php index 30d5dd53a..dc585c684 100644 --- a/modules/backend/widgets/Filter.php +++ b/modules/backend/widgets/Filter.php @@ -1,5 +1,8 @@ type) { + case 'date': + case 'range': + // Load datepicker assets + new DatePicker($this->controller, new FormField('dummy','dummy')); + break; + } + return $this->makePartial('scope_'.$scope->type, ['scope' => $scope]); } @@ -133,6 +144,32 @@ class Filter extends WidgetBase $value = post('value'); $this->setScopeValue($scope, $value); break; + + case 'date': + $dates = $this->datesFromAjax(post('options.dates')); + + if ( ! empty( $dates )) { + list( $date ) = $dates; + } else { + $date = null; + } + + $this->setScopeValue($scope, $date); + break; + + case 'range': + $dates = $this->datesFromAjax(post('options.dates')); + + if ( ! empty( $dates )) { + list( $after, $before ) = $dates; + + $dates = [$after, $before]; + } else { + $dates = null; + } + + $this->setScopeValue($scope, $dates); + break; } /* @@ -392,6 +429,14 @@ class Filter extends WidgetBase $this->scopeModels[$name] = $model; } + /* + * Ensure dates options are set + */ + if ( ! isset( $config['minDate'] )) { + $scopeObj->minDate = '2000-01-01'; + $scopeObj->maxDate = '2099-12-31'; + } + $this->allScopes[$name] = $scopeObj; } } @@ -451,7 +496,13 @@ class Filter extends WidgetBase return; } - $value = is_array($scope->value) ? array_keys($scope->value) : $scope->value; + switch ($scope->type) { + case'date': + case'range': + $this->applyDateScopeToQuery($scope, $query); + break; + default: + $value = is_array($scope->value) ? array_keys($scope->value) : $scope->value; /* * Condition @@ -488,6 +539,25 @@ class Filter extends WidgetBase return $query; } + + protected function applyDateScopeToQuery($scope, $query) + { + if ('range' === $scope->type) { + if (is_array($scope->value) && count($scope->value) > 1 && ( $scopeConditions = $scope->conditions )) { + list( $after, $before ) = array_values($scope->value); + + $query->whereRaw(strtr($scopeConditions, [ + ':after' => $after->format('Y-m-d'), + ':before' => $before->format('Y-m-d') + ])); + } + } else { + if ($scopeConditions = $scope->conditions) { + $query->whereRaw(strtr($scopeConditions, [':filtered' => $scope->value->format('Y-m-d')])); + } + } + } + // // Access layer // @@ -604,4 +674,45 @@ class Filter extends WidgetBase } return $processed; } + + + /** + * Convert an array from the posted dates + * + * @param mixed $scope + * @param array $dates + * + * @return array + */ + protected function datesFromAjax($ajaxDates) + { + $dates = []; + + if (null !== $ajaxDates) { + if ( ! is_array($ajaxDates)) { + $dates = [$ajaxDates]; + } + + foreach ($ajaxDates as $date) { + $dates[] = Carbon::createFromFormat('Y-m-d', $date); + } + } + + return $dates; + } + + + /** + * @param mixed $scope + * + * @return string + */ + protected function getFilterDateFormat($scope) + { + if (isset( $scope->date_format )) { + return $scope->date_format; + } + + return trans('backend::lang.filter.date.format'); + } } diff --git a/modules/backend/widgets/filter/partials/_scope_date.htm b/modules/backend/widgets/filter/partials/_scope_date.htm new file mode 100644 index 000000000..73bb6770d --- /dev/null +++ b/modules/backend/widgets/filter/partials/_scope_date.htm @@ -0,0 +1,14 @@ + + + label)) ?>: + value ? $scope->value->format(trans('backend::lang.filter.date.format')) : e(trans('backend::lang.filter.date.all')) ?> + diff --git a/modules/backend/widgets/filter/partials/_scope_range.htm b/modules/backend/widgets/filter/partials/_scope_range.htm new file mode 100644 index 000000000..191c5948e --- /dev/null +++ b/modules/backend/widgets/filter/partials/_scope_range.htm @@ -0,0 +1,14 @@ + + + label)) ?>: + value && is_array($scope->value) ? join(' → ', array_map(function($value) { return $value->format(trans('backend::lang.filter.date.format')); }, $scope->value)) : e(trans('backend::lang.filter.date.all')) ?> + diff --git a/modules/system/assets/ui/js/filter.dates.js b/modules/system/assets/ui/js/filter.dates.js new file mode 100644 index 000000000..a9cbb1daa --- /dev/null +++ b/modules/system/assets/ui/js/filter.dates.js @@ -0,0 +1,344 @@ +/* + * Filter Widget + * + * Data attributes: + * - data-behavior="filter" - enables the filter plugin + * + * Dependences: + * - October Popover (october.popover.js) + * + * Notes: + * Ideally this control would not depend on loader or the AJAX framework, + * then the Filter widget can use events to handle this business logic. + * + * Require: + * - mustache/mustache + * - modernizr/modernizr + * - storm/popover + */ ++function ($) { + "use strict"; + + var FilterWidget = $.fn.filterWidget.Constructor; + + /* ------------------------------------------------------------------------ + * Overloaded module functions + */ + + var overloaded_init = FilterWidget.prototype.init; + + FilterWidget.prototype.init = function () { + overloaded_init.apply(this); + + this.initFilterDate(); + }; + + + /*------------------------------------------------------------------------ + * New module functions + */ + + FilterWidget.prototype.initFilterDate = function () { + var self = this; + + this.$el.on('show.oc.popover', 'a.filter-scope-date', function () { + self.initDatePickers($(this).hasClass('range')); + }); + + this.$el.on('hiding.oc.popover', 'a.filter-scope-date', function () { + self.clearDatePickers(); + }); + + this.$el.on('hide.oc.popover', 'a.filter-scope-date', function () { + var $scope = $(this); + self.pushOptions(self.activeScopeName); + self.activeScopeName = null; + self.$activeScope = null; + + // Second click closes the filter scope + setTimeout(function () { + $scope.removeClass('filter-scope-open') + }, 200) + }); + + this.$el.on('click', 'a.filter-scope-date', function () { + var $scope = $(this), + scopeName = $scope.data('scope-name'); + + // Ignore if already opened + if ($scope.hasClass('filter-scope-open')) return; + + // Ignore if another popover is opened + if (null !== self.activeScopeName) return; + + self.$activeScope = $scope; + self.activeScopeName = scopeName; + self.isActiveScopeDirty = false; + + if ($scope.hasClass('range')) { + self.displayPopoverRange($scope) + } else { + self.displayPopoverDate($scope) + } + + $scope.addClass('filter-scope-open') + }); + + $(document).on('click', '#controlFilterPopover [data-trigger="filter"]', function (e) { + e.preventDefault(); + e.stopPropagation(); + + self.filterByDate() + }); + + $(document).on('click', '#controlFilterPopover [data-trigger="clear"]', function (e) { + e.preventDefault(); + e.stopPropagation(); + + self.filterByDate(true) + }) + }; + + /* + * Get popover date template + */ + FilterWidget.prototype.getPopoverDateTemplate = function () { + return ' \ +
\ + \ +
\ + \ +
\ +
\ + ' + }; + + /* + * Get popover range template + */ + FilterWidget.prototype.getPopoverRangeTemplate = function () { + return ' \ +
\ + \ +
\ + \ +
\ +
\ + ' + }; + + FilterWidget.prototype.displayPopoverDate = function ($scope) { + var self = this, + scopeName = $scope.data('scope-name'), + data = this.scopeValues[scopeName]; + + data = $.extend({}, data, { + filter_button_text: $.oc.lang.get('filter.dates.filter_button_text'), + reset_button_text: $.oc.lang.get('filter.dates.reset_button_text'), + date_placeholder: $.oc.lang.get('filter.dates.date_placeholder') + }); + + data.scopeName = scopeName; + + // Destroy any popovers already bound + $scope.data('oc.popover', null); + + $scope.ocPopover({ + content: Mustache.render(self.getPopoverDateTemplate(), data), + modal: false, + highlightModalTarget: true, + closeOnPageClick: true, + placement: 'bottom', + onCheckDocumentClickTarget: function (target) { + return self.onCheckDocumentClickTargetDatePicker(target); + } + }) + }; + + FilterWidget.prototype.displayPopoverRange = function ($scope) { + var self = this, + scopeName = $scope.data('scope-name'), + data = this.scopeValues[scopeName]; + + data = $.extend({}, data, { + filter_button_text: $.oc.lang.get('filter.dates.filter_button_text'), + reset_button_text: $.oc.lang.get('filter.dates.reset_button_text'), + after_placeholder: $.oc.lang.get('filter.dates.after_placeholder'), + before_placeholder: $.oc.lang.get('filter.dates.before_placeholder') + }); + + data.scopeName = scopeName; + + // Destroy any popovers already bound + $scope.data('oc.popover', null); + + $scope.ocPopover({ + content: Mustache.render(self.getPopoverRangeTemplate(), data), + modal: false, + highlightModalTarget: true, + closeOnPageClick: true, + placement: 'bottom', + onCheckDocumentClickTarget: function (target) { + return self.onCheckDocumentClickTargetDatePicker(target); + } + }) + }; + + FilterWidget.prototype.initDatePickers = function (isRange) { + var self = this, + scopeData = self.$activeScope.data('scope-data'), + $inputs = $('.field-datepicker input', '#controlFilterPopover'), + data = self.scopeValues[self.activeScopeName]; + + if (!data) { + data = { + dates: isRange ? (scopeData.dates ? scopeData.dates : []) : (scopeData.date ? [scopeData.date] : []) + } + } + + $inputs.each(function (index, datepicker) { + var defaultValue = '', + $datepicker = $(datepicker), + defaults = { + minDate: new Date(scopeData.minDate), + maxDate: new Date(scopeData.maxDate), + yearRange: 10, + setDefaultDate: '' !== defaultValue ? defaultValue.toDate() : '', + format: self.getDateFormat(), + i18n: $.oc.lang.get('pikaday') + }; + + if (0 <= index && index < data.dates.length) { + defaultValue = moment(data.dates[index], 'YYYY-MM-DD') + } + + if (!isRange) { + defaults.onSelect = function () { + self.filterByDate() + } + } + + datepicker.value = '' !== defaultValue ? defaultValue.format(self.getDateFormat()) : ''; + + $datepicker.pikaday(defaults) + }) + }; + + FilterWidget.prototype.clearDatePickers = function () { + var $inputs = $('.field-datepicker input', '#controlFilterPopover'); + + $inputs.each(function (index, datepicker) { + var $datepicker = $(datepicker); + + $datepicker.data('pikaday').destroy(); + }) + }; + + FilterWidget.prototype.updateScopeDateSetting = function ($scope, dates) { + var self = this, + $setting = $scope.find('.filter-setting'), + dateFormat = self.getDateFormat(); + + if (dates && dates.length) { + if (dates.length > 1) { + var after = moment(dates[0], 'YYYY-MM-DD').format(dateFormat), + before = moment(dates[1], 'YYYY-MM-DD').format(dateFormat); + + $setting.text(after + ' → ' + before) + } else { + $setting.text(moment(dates[0], 'YYYY-MM-DD').format(dateFormat)) + } + + $scope.addClass('active') + } + else { + $setting.text($.oc.lang.get('filter.dates.all')); + $scope.removeClass('active') + } + }; + + FilterWidget.prototype.filterByDate = function (isReset) { + var self = this, + dates = []; + + if (!isReset) { + $('.field-datepicker input', '#controlFilterPopover').each(function (index, datepicker) { + dates.push($(datepicker).data('pikaday').toString('YYYY-MM-DD')) + }) + } + + self.updateScopeDateSetting(self.$activeScope, dates); + self.scopeValues[self.activeScopeName] = { + dates: dates + }; + self.isActiveScopeDirty = true; + self.$activeScope.data('oc.popover').hide() + }; + + FilterWidget.prototype.getDateFormat = function () { + return $.oc.lang.get('filter.dates.format') + }; + + FilterWidget.prototype.onCheckDocumentClickTargetDatePicker = function (target) { + var $target = $(target); + + // If the click happens on a pikaday element, do not close the popover + return $target.hasClass('pika-next') || + $target.hasClass('pika-prev') || + $target.hasClass('pika-select') || + $target.hasClass('pika-button') || + $target.parents('.pika-table').length || + $target.parents('.pika-title').length; + }; +}(window.jQuery); \ No newline at end of file diff --git a/modules/system/assets/ui/less/filter.less b/modules/system/assets/ui/less/filter.less index 4f337c3bc..bb47d24bf 100644 --- a/modules/system/assets/ui/less/filter.less +++ b/modules/system/assets/ui/less/filter.less @@ -100,6 +100,38 @@ } } } + + > .filter-scope-date { + display: inline-block; + padding: 15px; + .filter-label {} + .filter-setting { + display: inline-block; + .transition(color 0.6s); + } + + &:after { + font-size: 14px; + .icon(@angle-down); + } + + &.active { + .filter-setting { + padding-left: 5px; + padding-right: 5px; + color: #FFF; + background-color: @color-filter-bg-active; + .border-radius(4px); + .transition(~'color 1s, background-color 1s'); + } + } + + &:hover { + color: #000; + .filter-label { color: @color-filter-text; } + &.active .filter-setting { background-color: darken(@color-filter-bg-active, 5%); } + } + } } .control-filter-popover { @@ -183,6 +215,16 @@ a:before { .icon(@times); } li.animate-enter { .animation(fadeInDown .5s); } } + + &.control-filter-date-popover { + min-width: 190px; + + .filter-buttons .btn { + border-radius: 0; + text-align: center; + margin: 0; + } + } } @media (max-width: @screen-xs) { diff --git a/modules/system/assets/ui/storm.js b/modules/system/assets/ui/storm.js index ad1dc8b12..31ae224c6 100644 --- a/modules/system/assets/ui/storm.js +++ b/modules/system/assets/ui/storm.js @@ -31,6 +31,7 @@ =require js/tooltip.js =require js/toolbar.js =require js/filter.js +=require js/filter.dates.js =require js/select.js =require js/loader.base.js =require js/loader.cursor.js diff --git a/modules/system/lang/en/client.php b/modules/system/lang/en/client.php index 506f05c70..631c5b697 100644 --- a/modules/system/lang/en/client.php +++ b/modules/system/lang/en/client.php @@ -59,6 +59,20 @@ return [ 'weekdaysShort' => ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] ], + 'filter' => [ + 'group' => [ + 'all' => 'all' + ], + 'dates' => [ + 'format' => 'YYYY-MM-DD', // Moment.js date format + 'all' => 'all period', + 'filter_button_text' => 'Filter', + 'reset_button_text' => 'Reset', + 'date_placeholder' => 'Date', + 'after_placeholder' => 'After', + 'before_placeholder' => 'Before' + ] + ], ]; diff --git a/modules/system/lang/fr/client.php b/modules/system/lang/fr/client.php index 8f096b371..dee648a45 100644 --- a/modules/system/lang/fr/client.php +++ b/modules/system/lang/fr/client.php @@ -61,6 +61,21 @@ return [ 'weekdays' => ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi'], 'weekdaysShort' => ['Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam'] ], + + 'filter' => [ + 'group' => [ + 'all' => 'all' + ], + 'dates' => [ + 'format' => 'DD/MM/YYYY', // Moment.js date format + 'all' => 'toute la période', + 'filter_button_text' => 'Filtrer', + 'reset_button_text' => 'Effacer', + 'date_placeholder' => 'Date', + 'after_placeholder' => 'Après le', + 'before_placeholder' => 'Avant le', + ] + ], ]; From 99dba21c9739119f329cb72fba0f85a78c7ea0b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Gaulin?= Date: Mon, 1 Feb 2016 11:18:35 +0100 Subject: [PATCH 2/3] Translate filter group dropdown 'all' reset text --- modules/system/assets/ui/js/filter.js | 2 +- modules/system/lang/fr/client.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/system/assets/ui/js/filter.js b/modules/system/assets/ui/js/filter.js index 3b765435e..6f14209e1 100644 --- a/modules/system/assets/ui/js/filter.js +++ b/modules/system/assets/ui/js/filter.js @@ -158,7 +158,7 @@ $scope.addClass('active') } else { - $setting.text('all') + $setting.text($.oc.lang.get('filter.group.all')) $scope.removeClass('active') } } diff --git a/modules/system/lang/fr/client.php b/modules/system/lang/fr/client.php index dee648a45..d1d2841b2 100644 --- a/modules/system/lang/fr/client.php +++ b/modules/system/lang/fr/client.php @@ -64,7 +64,7 @@ return [ 'filter' => [ 'group' => [ - 'all' => 'all' + 'all' => 'tous' ], 'dates' => [ 'format' => 'DD/MM/YYYY', // Moment.js date format From 51ac38dff7b73a515c2a95443382b0494a33ac7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Gaulin?= Date: Wed, 11 May 2016 16:22:48 +0200 Subject: [PATCH 3/3] Minor refactoring to match latest develop version --- modules/backend/widgets/Filter.php | 117 +++++++++--------- ...{_scope_date.htm => _scope_datepicker.htm} | 4 +- ...e_range.htm => _scope_daterangepicker.htm} | 4 +- modules/system/assets/ui/js/filter.dates.js | 2 +- 4 files changed, 62 insertions(+), 65 deletions(-) rename modules/backend/widgets/filter/partials/{_scope_date.htm => _scope_datepicker.htm} (57%) rename modules/backend/widgets/filter/partials/{_scope_range.htm => _scope_daterangepicker.htm} (67%) diff --git a/modules/backend/widgets/Filter.php b/modules/backend/widgets/Filter.php index dc585c684..2d3de1947 100644 --- a/modules/backend/widgets/Filter.php +++ b/modules/backend/widgets/Filter.php @@ -101,10 +101,10 @@ class Filter extends WidgetBase public function renderScopeElement($scope) { switch ($scope->type) { - case 'date': - case 'range': + case 'datepicker': + case 'daterangepicker': // Load datepicker assets - new DatePicker($this->controller, new FormField('dummy','dummy')); + new DatePicker($this->controller, new FormField('dummy', 'dummy')); break; } @@ -145,11 +145,11 @@ class Filter extends WidgetBase $this->setScopeValue($scope, $value); break; - case 'date': + case 'datepicker': $dates = $this->datesFromAjax(post('options.dates')); - if ( ! empty( $dates )) { - list( $date ) = $dates; + if (!empty($dates)) { + list($date) = $dates; } else { $date = null; } @@ -157,11 +157,11 @@ class Filter extends WidgetBase $this->setScopeValue($scope, $date); break; - case 'range': + case 'daterangepicker': $dates = $this->datesFromAjax(post('options.dates')); - if ( ! empty( $dates )) { - list( $after, $before ) = $dates; + if (!empty($dates)) { + list($after, $before) = $dates; $dates = [$after, $before]; } else { @@ -432,7 +432,7 @@ class Filter extends WidgetBase /* * Ensure dates options are set */ - if ( ! isset( $config['minDate'] )) { + if (!isset($config['minDate'])) { $scopeObj->minDate = '2000-01-01'; $scopeObj->maxDate = '2099-12-31'; } @@ -497,67 +497,64 @@ class Filter extends WidgetBase } switch ($scope->type) { - case'date': - case'range': - $this->applyDateScopeToQuery($scope, $query); + case 'datepicker': + if ($scope->value instanceof Carbon && $scopeConditions = $scope->conditions) { + $query->whereRaw(strtr($scopeConditions, [':filtered' => $scope->value->format('Y-m-d')])); + } + + break; + case 'daterangepicker': + if (is_array($scope->value) && count($scope->value) > 1 && ($scopeConditions = $scope->conditions)) { + list($after, $before) = array_values($scope->value); + + if($after instanceof Carbon && $before instanceof Carbon) { + $query->whereRaw(strtr($scopeConditions, [ + ':after' => $after->format('Y-m-d'), + ':before' => $before->format('Y-m-d') + ])); + } + } + break; default: $value = is_array($scope->value) ? array_keys($scope->value) : $scope->value; - /* - * Condition - */ - if ($scopeConditions = $scope->conditions) { + /* + * Condition + */ + if ($scopeConditions = $scope->conditions) { - /* - * Switch scope: multiple conditions, value either 1 or 2 - */ - if (is_array($scopeConditions)) { - $conditionNum = is_array($value) ? 0 : $value - 1; - list($scopeConditions) = array_slice($scopeConditions, $conditionNum); - } + /* + * Switch scope: multiple conditions, value either 1 or 2 + */ + if (is_array($scopeConditions)) { + $conditionNum = is_array($value) ? 0 : $value - 1; + list($scopeConditions) = array_slice($scopeConditions, $conditionNum); + } - if (is_array($value)) { - $filtered = implode(',', array_build($value, function ($key, $_value) { - return [$key, Db::getPdo()->quote($_value)]; - })); - } - else { - $filtered = Db::getPdo()->quote($value); - } + if (is_array($value)) { + $filtered = implode(',', array_build($value, function ($key, $_value) { + return [$key, Db::getPdo()->quote($_value)]; + })); + } + else { + $filtered = Db::getPdo()->quote($value); + } - $query->whereRaw(DbDongle::parse(strtr($scopeConditions, [':filtered' => $filtered]))); - } + $query->whereRaw(DbDongle::parse(strtr($scopeConditions, [':filtered' => $filtered]))); + } - /* - * Scope - */ - if ($scopeMethod = $scope->scope) { - $query->$scopeMethod($value); + /* + * Scope + */ + if ($scopeMethod = $scope->scope) { + $query->$scopeMethod($value); + } } return $query; } - - protected function applyDateScopeToQuery($scope, $query) - { - if ('range' === $scope->type) { - if (is_array($scope->value) && count($scope->value) > 1 && ( $scopeConditions = $scope->conditions )) { - list( $after, $before ) = array_values($scope->value); - - $query->whereRaw(strtr($scopeConditions, [ - ':after' => $after->format('Y-m-d'), - ':before' => $before->format('Y-m-d') - ])); - } - } else { - if ($scopeConditions = $scope->conditions) { - $query->whereRaw(strtr($scopeConditions, [':filtered' => $scope->value->format('Y-m-d')])); - } - } - } - // // Access layer // @@ -689,7 +686,7 @@ class Filter extends WidgetBase $dates = []; if (null !== $ajaxDates) { - if ( ! is_array($ajaxDates)) { + if (!is_array($ajaxDates)) { $dates = [$ajaxDates]; } @@ -709,7 +706,7 @@ class Filter extends WidgetBase */ protected function getFilterDateFormat($scope) { - if (isset( $scope->date_format )) { + if (isset($scope->date_format)) { return $scope->date_format; } diff --git a/modules/backend/widgets/filter/partials/_scope_date.htm b/modules/backend/widgets/filter/partials/_scope_datepicker.htm similarity index 57% rename from modules/backend/widgets/filter/partials/_scope_date.htm rename to modules/backend/widgets/filter/partials/_scope_datepicker.htm index 73bb6770d..f19a7e8b8 100644 --- a/modules/backend/widgets/filter/partials/_scope_date.htm +++ b/modules/backend/widgets/filter/partials/_scope_datepicker.htm @@ -4,11 +4,11 @@ href="javascript:;" data-scope-name="scopeName ?>" data-scope-data=" $scope->value ? $scope->value->format('Y-m-d') : null, + 'date' => $scope->value && $scope->value instanceof \Carbon\Carbon ? $scope->value->format('Y-m-d') : null, 'minDate' => $scope->minDate ? $scope->minDate : '2000-01-01' , 'maxDate' => $scope->maxDate ? $scope->maxDate : '2099-12-31', ])) ?>"> label)) ?>: - value ? $scope->value->format(trans('backend::lang.filter.date.format')) : e(trans('backend::lang.filter.date.all')) ?> + value && $scope->value instanceof \Carbon\Carbon ? $scope->value->format(trans('backend::lang.filter.date.format')) : e(trans('backend::lang.filter.date.all')) ?> diff --git a/modules/backend/widgets/filter/partials/_scope_range.htm b/modules/backend/widgets/filter/partials/_scope_daterangepicker.htm similarity index 67% rename from modules/backend/widgets/filter/partials/_scope_range.htm rename to modules/backend/widgets/filter/partials/_scope_daterangepicker.htm index 191c5948e..9aafbd31e 100644 --- a/modules/backend/widgets/filter/partials/_scope_range.htm +++ b/modules/backend/widgets/filter/partials/_scope_daterangepicker.htm @@ -4,11 +4,11 @@ href="javascript:;" data-scope-name="scopeName ?>" data-scope-data=" $scope->value && is_array($scope->value) ? array_map(function($value) { return $value->format('Y-m-d'); }, $scope->value) : null, + 'dates' => $scope->value && is_array($scope->value) ? array_map(function($value) { return $value instanceof \Carbon\Carbon ? $value->format('Y-m-d') : null; }, $scope->value) : null, 'minDate' => $scope->minDate ? $scope->minDate : '2000-01-01' , 'maxDate' => $scope->maxDate ? $scope->maxDate : '2099-12-31', ])) ?>"> label)) ?>: - value && is_array($scope->value) ? join(' → ', array_map(function($value) { return $value->format(trans('backend::lang.filter.date.format')); }, $scope->value)) : e(trans('backend::lang.filter.date.all')) ?> + value && is_array($scope->value) ? join(' → ', array_map(function($value) { return $value instanceof \Carbon\Carbon ? $value->format(trans('backend::lang.filter.date.format')) : null; }, $scope->value)) : e(trans('backend::lang.filter.date.all')) ?> diff --git a/modules/system/assets/ui/js/filter.dates.js b/modules/system/assets/ui/js/filter.dates.js index a9cbb1daa..00b3fcd2e 100644 --- a/modules/system/assets/ui/js/filter.dates.js +++ b/modules/system/assets/ui/js/filter.dates.js @@ -256,7 +256,7 @@ yearRange: 10, setDefaultDate: '' !== defaultValue ? defaultValue.toDate() : '', format: self.getDateFormat(), - i18n: $.oc.lang.get('pikaday') + i18n: $.oc.lang.get('datepicker') }; if (0 <= index && index < data.dates.length) {