Skip to content

Commit 01e8d5f

Browse files
committed
Fix datetime delocalization issues by using ISO8601 time format
Localization is now performed only in the browser, without affecting browser-server communication. Closes #3344
1 parent 4379451 commit 01e8d5f

28 files changed

Lines changed: 599 additions & 291 deletions

File tree

.rubocop_todo.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,6 @@ Style/RescueStandardError:
440440
Exclude:
441441
- 'lib/rails_admin/adapters/mongoid.rb'
442442
- 'lib/rails_admin/adapters/mongoid/bson.rb'
443-
- 'lib/rails_admin/support/i18n.rb'
444443

445444
# Offense count: 2
446445
# Cop supports --auto-correct.

app/assets/javascripts/rails_admin/ra.filter-box.js

Lines changed: 40 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -34,57 +34,46 @@
3434
}
3535
break;
3636
case 'date':
37-
additional_control =
38-
$('<input size="20" class="date additional-fieldset default input-sm form-control" type="text" />')
39-
.css('display', (!field_operator || field_operator == "default") ? 'inline-block' : 'none')
40-
.prop('name', value_name + '[]')
41-
.prop('value', field_value[0] || '')
42-
.add(
43-
$('<input size="20" placeholder="-∞" class="date additional-fieldset between input-sm form-control" type="text" />')
44-
.css('display', (field_operator == "between") ? 'inline-block' : 'none')
45-
.prop('name', value_name + '[]')
46-
.prop('value', field_value[1] || '')
47-
)
48-
.add(
49-
$('<input size="20" placeholder="∞" class="date additional-fieldset between input-sm form-control" type="text" />')
50-
.css('display', (field_operator == "between") ? 'inline-block' : 'none')
51-
.prop('name', value_name + '[]')
52-
.prop('value', field_value[2] || '')
53-
);
5437
case 'datetime':
5538
case 'timestamp':
39+
case 'time':
5640
control = control || $('<select class="switch-additional-fieldsets input-sm form-control"></select>')
5741
.prop('name', operator_name)
58-
.append($('<option data-additional-fieldset="default" value="default"></option>').prop('selected', field_operator == "default").text(RailsAdmin.I18n.t("date")))
42+
.append($('<option data-additional-fieldset="default" value="default"></option>').prop('selected', field_operator == "default").text(RailsAdmin.I18n.t(field_type == "time" ? "time" : "date")))
5943
.append($('<option data-additional-fieldset="between" value="between"></option>').prop('selected', field_operator == "between").text(RailsAdmin.I18n.t("between_and_")))
60-
.append($('<option value="today"></option>').prop('selected', field_operator == "today").text(RailsAdmin.I18n.t("today")))
61-
.append($('<option value="yesterday"></option>').prop('selected', field_operator == "yesterday").text(RailsAdmin.I18n.t("yesterday")))
62-
.append($('<option value="this_week"></option>').prop('selected', field_operator == "this_week").text(RailsAdmin.I18n.t("this_week")))
63-
.append($('<option value="last_week"></option>').prop('selected', field_operator == "last_week").text(RailsAdmin.I18n.t("last_week")))
44+
if (field_type != 'time') {
45+
control.append([
46+
$('<option value="today"></option>').prop('selected', field_operator == "today").text(RailsAdmin.I18n.t("today")),
47+
$('<option value="yesterday"></option>').prop('selected', field_operator == "yesterday").text(RailsAdmin.I18n.t("yesterday")),
48+
$('<option value="this_week"></option>').prop('selected', field_operator == "this_week").text(RailsAdmin.I18n.t("this_week")),
49+
$('<option value="last_week"></option>').prop('selected', field_operator == "last_week").text(RailsAdmin.I18n.t("last_week")),
50+
])
51+
}
6452
if (!required) {
6553
control.append([
6654
'<option disabled="disabled">---------</option>',
6755
$('<option value="_not_null"></option>').prop('selected', field_operator == "_not_null").text(RailsAdmin.I18n.t("is_present")),
6856
$('<option value="_null"></option>').prop('selected', field_operator == "_null").text(RailsAdmin.I18n.t("is_blank"))
6957
])
7058
}
71-
additional_control = additional_control ||
72-
$('<input size="25" class="datetime additional-fieldset default input-sm form-control" type="text" />')
73-
.css('display', (!field_operator || field_operator == "default") ? 'inline-block' : 'none')
74-
.prop('name', value_name + '[]')
75-
.prop('value', field_value[0] || '')
76-
.add(
77-
$('<input size="25" placeholder="-∞" class="datetime additional-fieldset between input-sm form-control" type="text" />')
78-
.css('display', (field_operator == "between") ? 'inline-block' : 'none')
79-
.prop('name', value_name + '[]')
80-
.prop('value', field_value[1] || '')
81-
)
82-
.add(
83-
$('<input size="25" placeholder="∞" class="datetime additional-fieldset between input-sm form-control" type="text" />')
84-
.css('display', (field_operator == "between") ? 'inline-block' : 'none')
85-
.prop('name', value_name + '[]')
86-
.prop('value', field_value[2] || '')
87-
);
59+
additional_control =
60+
$.map([undefined, '-∞', '∞'], function(placeholder, index){
61+
var visible = index == 0 ? (!field_operator || field_operator == "default") : (field_operator == "between");
62+
return $('<span class="additional-fieldset"></span>')
63+
.addClass(index == 0 ? 'default' : 'between')
64+
.css('display', visible ? 'inline-block' : 'none')
65+
.html(
66+
$('<input type="hidden" />')
67+
.prop('name', value_name + '[]')
68+
.prop('value', field_value[index] || '')
69+
.add(
70+
$('<input class="input-sm form-control" type="text" />')
71+
.addClass(field_type == 'date' ? 'date' : 'datetime')
72+
.prop('size', field_type == 'date' || field_type == 'time' ? 20 : 25)
73+
.prop('placeholder', placeholder)
74+
)
75+
);
76+
});
8877
break;
8978
case 'enum':
9079
var multiple_values = ((field_value instanceof Array) ? true : false)
@@ -193,10 +182,18 @@
193182

194183
$('#filters_box').append($content);
195184

196-
$content.find('.date, .datetime').datetimepicker({
197-
locale: RailsAdmin.I18n.locale,
198-
showTodayButton: true,
199-
format: options['datetimepicker_format']
185+
$content.find('.date, .datetime').each(function() {
186+
$(this).datetimepicker({
187+
date: moment($(this).siblings('[type=hidden]').val()),
188+
locale: RailsAdmin.I18n.locale,
189+
showTodayButton: true,
190+
format: options['datetimepicker_format']
191+
});
192+
$(this).on('dp.change', function(e) {
193+
if (e.date) {
194+
$(this).siblings('[type=hidden]').val(e.date.format('YYYY-MM-DD[T]HH:mm:ss'));
195+
}
196+
});
200197
});
201198

202199
$("hr.filters_box:hidden").show('slow');

app/assets/javascripts/rails_admin/ra.widgets.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,15 @@
3737
var options;
3838
options = $(this).data('options');
3939
$.extend(options, {
40+
date: moment($(this).siblings('[type=hidden]').val()),
4041
locale: RailsAdmin.I18n.locale
4142
});
4243
$(this).datetimepicker(options);
44+
$(this).on('dp.change', function(e) {
45+
if (e.date) {
46+
$(this).siblings('[type=hidden]').val(e.date.format('YYYY-MM-DD[T]HH:mm:ss'));
47+
}
48+
});
4349
});
4450
content.find('[data-enumeration]').each(function() {
4551
if ($(this).is('[multiple]')) {

app/helpers/rails_admin/application_helper.rb

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
1-
require 'rails_admin/support/i18n'
2-
31
module RailsAdmin
42
module ApplicationHelper
5-
include RailsAdmin::Support::I18n
6-
73
def capitalize_first_letter(wording)
84
return nil unless wording.present? && wording.is_a?(String)
95

app/helpers/rails_admin/main_helper.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def ordered_filter_options
6969
when :enum
7070
options[:select_options] = options_for_select(field.with(object: @abstract_model.model.new).enum, filter_hash['v'])
7171
when :date, :datetime, :time
72-
options[:datetimepicker_format] = field.parser.to_momentjs
72+
options[:datetimepicker_format] = field.momentjs_format
7373
end
7474
options[:label] = field.label
7575
options[:name] = field.name
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
.form-inline
22
.input-group
3-
= form.send field.view_helper, field.method_name, field.html_attributes.reverse_merge({value: field.form_value, class: 'form-control', data: {datetimepicker: true, options: field.datepicker_options.to_json}})
3+
= form.hidden_field(field.method_name, id: nil, value: field.form_value)
4+
= form.text_field field.method_name, field.html_attributes.reverse_merge({class: 'form-control', data: {datetimepicker: true, options: field.datepicker_options.to_json}, name: nil, value: nil})
45
= form.label(field.method_name, class: 'input-group-addon') do
56
%i.fa.fa-fw.fa-calendar

app/views/rails_admin/main/index.html.haml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
- else
3636
- ''
3737
%li
38-
%a{href: '#', :"data-field-label" => field.label, :"data-field-name" => field.name, :"data-field-operator" => field.default_filter_operator, :"data-field-options" => field_options.html_safe, :"data-field-required" => field.required.to_s, :"data-field-type" => field.type, :"data-field-value" => "", :"data-field-datetimepicker-format" => (field.try(:parser) && field.parser.to_momentjs)}= capitalize_first_letter(field.label)
38+
%a{href: '#', :"data-field-label" => field.label, :"data-field-name" => field.name, :"data-field-operator" => field.default_filter_operator, :"data-field-options" => field_options.html_safe, :"data-field-required" => field.required.to_s, :"data-field-type" => field.type, :"data-field-value" => "", :"data-field-datetimepicker-format" => field.try(:momentjs_format)}= capitalize_first_letter(field.label)
3939
4040
%style
4141
- properties.select{ |p| p.column_width.present? }.each do |property|

config/locales/rails_admin.en.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ en:
1111
yesterday: Yesterday
1212
this_week: This week
1313
last_week: Last week
14+
time: Time ...
1415
number: Number ...
1516
contains: Contains
1617
is_exactly: Is exactly

lib/rails_admin/abstract_model.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ def build_statement_for_type_generic
139139
case @type
140140
when :date
141141
build_statement_for_date
142-
when :datetime, :timestamp
142+
when :datetime, :timestamp, :time
143143
build_statement_for_datetime_or_timestamp
144144
end
145145
end
@@ -178,8 +178,8 @@ def build_statement_for_date
178178

179179
def build_statement_for_datetime_or_timestamp
180180
start_date, end_date = get_filtering_duration
181-
start_date = start_date.try(:beginning_of_day) if start_date
182-
end_date = end_date.try(:end_of_day) if end_date
181+
start_date = start_date.beginning_of_day if start_date.is_a?(Date)
182+
end_date = end_date.end_of_day if end_date.is_a?(Date)
183183
range_filter(start_date, end_date)
184184
end
185185

lib/rails_admin/adapters/active_record.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,9 @@ def boolean_unary_operators
205205
alias_method :numeric_unary_operators, :boolean_unary_operators
206206

207207
def range_filter(min, max)
208-
if min && max
208+
if min && max && min == max
209+
["(#{@column} = ?)", min]
210+
elsif min && max
209211
["(#{@column} BETWEEN ? AND ?)", min, max]
210212
elsif min
211213
["(#{@column} >= ?)", min]

0 commit comments

Comments
 (0)