diff --git a/Gemfile.lock b/Gemfile.lock index c5f2bd7e6..98a7378ba 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -628,7 +628,7 @@ DEPENDENCIES yomu RUBY VERSION - ruby 2.4.3p205 + ruby 2.4.4p296 BUNDLED WITH 1.16.3 diff --git a/app/controllers/activities_controller.rb b/app/controllers/activities_controller.rb index 792b5e2cf..54b693aae 100644 --- a/app/controllers/activities_controller.rb +++ b/app/controllers/activities_controller.rb @@ -34,12 +34,12 @@ class ActivitiesController < ApplicationController end # send last activity date of the previus batch previous_activity = Activity.find_by_id(params[:last_activity]) - previus_date = previous_activity.created_at.to_date if previous_activity + previus_date = previous_activity.created_at if previous_activity { activities: activities, more_activities_url: more_url, page: page, - previous_activity_created_at: previus_date + previous_activity_created_at: I18n.l(previus_date, format: :full_date) } end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 13faeba34..607e5185c 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -6,6 +6,7 @@ class ApplicationController < ActionController::Base before_action :authenticate_user! helper_method :current_team before_action :update_current_team, if: :user_signed_in? + before_action :set_date_format, if: :user_signed_in? around_action :set_time_zone, if: :current_user layout 'main' @@ -81,4 +82,9 @@ class ApplicationController < ActionController::Base def set_time_zone(&block) Time.use_zone(current_user.settings[:time_zone], &block) end + + def set_date_format + I18n.backend.date_format = + current_user.settings[:date_format] || Constants::DEFAULT_DATE_FORMAT + end end diff --git a/app/controllers/my_module_comments_controller.rb b/app/controllers/my_module_comments_controller.rb index 2a0251384..226023cd9 100644 --- a/app/controllers/my_module_comments_controller.rb +++ b/app/controllers/my_module_comments_controller.rb @@ -75,7 +75,7 @@ class MyModuleCommentsController < ApplicationController comment: @comment } ), - date: @comment.created_at.strftime('%d.%m.%Y'), + date: I18n.l(@comment.created_at, format: :full_date), linked_id: @my_module.id, # Used for counter badge counter: @my_module.task_comments.count # Used for counter badge }, diff --git a/app/controllers/my_modules_controller.rb b/app/controllers/my_modules_controller.rb index 48bdff2e6..96ba21779 100644 --- a/app/controllers/my_modules_controller.rb +++ b/app/controllers/my_modules_controller.rb @@ -144,7 +144,13 @@ class MyModulesController < ApplicationController end def update - @my_module.assign_attributes(my_module_params) + update_params = my_module_params + if update_params[:due_date].present? + update_params[:due_date] = Time.strptime( + update_params[:due_date], I18n.backend.date_format.dup.delete('-') + ) + end + @my_module.assign_attributes(update_params) @my_module.last_modified_by = current_user description_changed = @my_module.description_changed? diff --git a/app/controllers/project_comments_controller.rb b/app/controllers/project_comments_controller.rb index 9cf099cdc..e0870b4e3 100644 --- a/app/controllers/project_comments_controller.rb +++ b/app/controllers/project_comments_controller.rb @@ -71,7 +71,7 @@ class ProjectCommentsController < ApplicationController comment: @comment } ), - date: @comment.created_at.strftime('%d.%m.%Y'), + date: I18n.l(@comment.created_at, format: :full_date), linked_id: @project.id, counter: @project.project_comments.count }, status: :created diff --git a/app/controllers/result_comments_controller.rb b/app/controllers/result_comments_controller.rb index 6d4c48544..44cc271ee 100644 --- a/app/controllers/result_comments_controller.rb +++ b/app/controllers/result_comments_controller.rb @@ -71,7 +71,7 @@ class ResultCommentsController < ApplicationController comment: @comment } ), - date: @comment.created_at.strftime('%d.%m.%Y') + date: I18n.l(@comment.created_at, format: :full_date) }, status: :created } diff --git a/app/controllers/step_comments_controller.rb b/app/controllers/step_comments_controller.rb index 713592122..44fcb92e7 100644 --- a/app/controllers/step_comments_controller.rb +++ b/app/controllers/step_comments_controller.rb @@ -73,7 +73,7 @@ class StepCommentsController < ApplicationController comment: @comment } ), - date: @comment.created_at.strftime('%d.%m.%Y') + date: I18n.l(@comment.created_at, format: :full_date) }, status: :created } diff --git a/app/controllers/users/settings/account/preferences_controller.rb b/app/controllers/users/settings/account/preferences_controller.rb index 54e7ad2aa..456e62486 100644 --- a/app/controllers/users/settings/account/preferences_controller.rb +++ b/app/controllers/users/settings/account/preferences_controller.rb @@ -68,9 +68,7 @@ module Users end def update_params - params.require(:user).permit( - :time_zone - ) + params.require(:user).permit(:time_zone, :date_format) end end end diff --git a/app/datatables/custom_datatable.rb b/app/datatables/custom_datatable.rb index c958000a0..0b60d9e12 100644 --- a/app/datatables/custom_datatable.rb +++ b/app/datatables/custom_datatable.rb @@ -37,4 +37,17 @@ class CustomDatatable < AjaxDatatablesRails::Base end @sortable_displayed_columns end + + def formated_date + f_date = I18n.backend.date_format.dup + f_date.gsub!(/%-d/, 'FMDD') + f_date.gsub!(/%d/, 'DD') + f_date.gsub!(/%-m/, 'FMMM') + f_date.gsub!(/%m/, 'MM') + f_date.gsub!(/%b/, 'Mon') + f_date.gsub!(/%B/, 'Month') + f_date.gsub!('%Y', 'YYYY') + f_date += ' HH24:MI' + f_date + end end diff --git a/app/datatables/load_from_repository_protocols_datatable.rb b/app/datatables/load_from_repository_protocols_datatable.rb index 99ee07c12..d43ecf0ea 100644 --- a/app/datatables/load_from_repository_protocols_datatable.rb +++ b/app/datatables/load_from_repository_protocols_datatable.rb @@ -36,7 +36,6 @@ class LoadFromRepositoryProtocolsDatatable < CustomDatatable def new_search_condition(column, value) model, column = column.split('.') model = model.constantize - formated_date = (I18n.t 'time.formats.datatables_date').gsub!(/^\"|\"?$/, '') case column when 'published_on' casted_column = ::Arel::Nodes::NamedFunction.new('CAST', diff --git a/app/datatables/protocols_datatable.rb b/app/datatables/protocols_datatable.rb index 89818b11a..38ee52632 100644 --- a/app/datatables/protocols_datatable.rb +++ b/app/datatables/protocols_datatable.rb @@ -58,7 +58,6 @@ class ProtocolsDatatable < CustomDatatable def new_search_condition(column, value) model, column = column.split('.') model = model.constantize - formated_date = (I18n.t 'time.formats.datatables_date').gsub!(/^\"|\"?$/, '') case column when 'published_on' casted_column = ::Arel::Nodes::NamedFunction.new('CAST', diff --git a/app/datatables/team_users_datatable.rb b/app/datatables/team_users_datatable.rb index 2772f9062..4ba722d91 100644 --- a/app/datatables/team_users_datatable.rb +++ b/app/datatables/team_users_datatable.rb @@ -36,8 +36,6 @@ class TeamUsersDatatable < CustomDatatable def new_search_condition(column, value) model, column = column.split('.') model = model.constantize - formated_date = (I18n.t 'time.formats.datatables_date') - .gsub!(/^\"|\"?$/, '') if column == 'created_at' casted_column = ::Arel::Nodes::NamedFunction.new( 'CAST', diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index e97f92b36..4cacd89ca 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -158,7 +158,7 @@ module ApplicationHelper #{I18n.t('atwho.users.popover_html', role: user_t.role.capitalize, team: user_t.team.name, - time: user_t.created_at.strftime('%B %Y'))} + time: I18n.l(user_t.created_at, format: :full_date))}

) else user_description += %(

) diff --git a/app/helpers/bootstrap_form_helper.rb b/app/helpers/bootstrap_form_helper.rb index b711edb93..62903ecf5 100644 --- a/app/helpers/bootstrap_form_helper.rb +++ b/app/helpers/bootstrap_form_helper.rb @@ -24,7 +24,14 @@ module BootstrapFormHelper input_name = "#{@object_name}[#{name.to_s}]" timestamp = @object[name] ? "#{@object[name].to_i}000" : "" js_locale = I18n.locale.to_s - js_format = I18n.t("time.formats.full_js") + js_format = I18n.backend.date_format.dup + js_format.gsub!(/%-d/, 'D') + js_format.gsub!(/%d/, 'DD') + js_format.gsub!(/%-m/, 'M') + js_format.gsub!(/%m/, 'MM') + js_format.gsub!(/%b/, 'MMM') + js_format.gsub!(/%B/, 'MMMM') + js_format.gsub!('%Y', 'YYYY') label = name.to_s.humanize if options[:label] then diff --git a/app/models/user.rb b/app/models/user.rb index 3ac31a6b2..111b35f97 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -41,6 +41,7 @@ class User < ApplicationRecord default_settings( time_zone: 'UTC', + date_format: Constants::DEFAULT_DATE_FORMAT, notifications_settings: { assignments: true, assignments_email: false, @@ -233,6 +234,18 @@ class User < ApplicationRecord @avatar_remote_url = url_value end + def date_format + settings[:date_format] || Constants::DEFAULT_DATE_FORMAT + end + + def date_format=(date_format) + return if settings[:date_format] == date_format + if Constants::SUPPORTED_DATE_FORMATS.include?(date_format) + settings[:date_format] = date_format + clear_view_cache + end + end + def current_team Team.find_by_id(self.current_team_id) end @@ -524,4 +537,8 @@ class User < ApplicationRecord # Now, simply destroy all user notification relations left user_notifications.destroy_all end + + def clear_view_cache + Rails.cache.delete_matched(%r{^views\/users\/#{id}-}) + end end diff --git a/app/models/zip_export.rb b/app/models/zip_export.rb index eddba2617..877a90826 100644 --- a/app/models/zip_export.rb +++ b/app/models/zip_export.rb @@ -47,6 +47,8 @@ class ZipExport < ApplicationRecord end def generate_exportable_zip(user, data, type, options = {}) + I18n.backend.date_format = + user.settings[:date_format] || Constants::DEFAULT_DATE_FORMAT FileUtils.mkdir_p(File.join(Rails.root, 'tmp/zip-ready')) dir_to_zip = FileUtils.mkdir_p( File.join(Rails.root, "tmp/temp-zip-#{Time.now.to_i}") diff --git a/app/services/custom_i18n_backend.rb b/app/services/custom_i18n_backend.rb new file mode 100644 index 000000000..cb635f46a --- /dev/null +++ b/app/services/custom_i18n_backend.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +class CustomI18nBackend < I18n::Backend::Simple + attr_accessor :date_format + + def localize(locale, object, format = :default, options = {}) + options[:date_format] ||= @date_format || Constants::DEFAULT_DATE_FORMAT + super(locale, object, format, options) + end +end diff --git a/app/views/my_module_comments/_list.html.erb b/app/views/my_module_comments/_list.html.erb index 627d9d6cd..a054871ca 100644 --- a/app/views/my_module_comments/_list.html.erb +++ b/app/views/my_module_comments/_list.html.erb @@ -6,7 +6,7 @@ <% if comment_day <= current_day && comment_day > day %> <% day = days_since_1970(comment.created_at) %>
  • -

    <%= comment.created_at.strftime('%d.%m.%Y') %>

    +

    <%= l(comment.created_at, format: :full_date) %>

  • <% end %>
  • diff --git a/app/views/project_comments/_list.html.erb b/app/views/project_comments/_list.html.erb index fd3a8f646..169b52cd7 100644 --- a/app/views/project_comments/_list.html.erb +++ b/app/views/project_comments/_list.html.erb @@ -5,7 +5,7 @@ <% if comment_day <= current_day && comment_day > day %> <% day = days_since_1970(comment.created_at) %>
  • -

    <%= comment.created_at.strftime('%d.%m.%Y') %>

    +

    <%= l(comment.created_at, format: :full_date) %>

  • <% end %>
  • diff --git a/app/views/result_comments/_list.html.erb b/app/views/result_comments/_list.html.erb index 37529b929..c77a9237d 100644 --- a/app/views/result_comments/_list.html.erb +++ b/app/views/result_comments/_list.html.erb @@ -6,7 +6,7 @@ <% if comment_day <= current_day && comment_day > day %> <% day = days_since_1970(comment.created_at) %>
  • -

    <%= comment.created_at.strftime('%d.%m.%Y') %>

    +

    <%= l(comment.created_at, format: :full_date) %>

  • <% end %>
  • diff --git a/app/views/step_comments/_list.html.erb b/app/views/step_comments/_list.html.erb index 2865f3fb8..a0d65fbd8 100644 --- a/app/views/step_comments/_list.html.erb +++ b/app/views/step_comments/_list.html.erb @@ -6,7 +6,7 @@ <% if comment_day <= current_day && comment_day > day %> <% day = days_since_1970(comment.created_at) %>
  • -

    <%= comment.created_at.strftime('%d.%m.%Y') %>

    +

    <%= l(comment.created_at, format: :full_date) %>

  • <% end %>
  • diff --git a/app/views/users/settings/account/preferences/index.html.erb b/app/views/users/settings/account/preferences/index.html.erb index 89ab57ffe..dd4a7a5ed 100644 --- a/app/views/users/settings/account/preferences/index.html.erb +++ b/app/views/users/settings/account/preferences/index.html.erb @@ -49,6 +49,48 @@ <% end %> + <%= form_for(@user, + url: update_preferences_path(format: :json), + remote: true, + html: { + method: :put, + 'data-for' => 'date_format', + 'data-turbolinks' => false + }) do |f| %> +
    +
    + <%= f.label t("users.settings.account.preferences.edit.date_format_label") %> + + <%= t("users.settings.account.preferences.edit.date_format_sublabel") %> +
    +
    +
    +
    +

    <%=t "users.settings.account.preferences.edit.date_format_title" %>

    +
    + <%= f.select :date_format, Constants::SUPPORTED_DATE_FORMATS.collect { |df| + ["#{l(Time.now, format: :full_date, date_format: df)}", df] + }, {}, { class: 'form-control selectpicker', 'data-role': 'clear' } %> + <%= t("users.settings.account.preferences.edit.date_format_sublabel") %> +
    +
    + <%=t "general.cancel" %> + <%= f.submit t("general.save"), class: "btn btn-success" %> +
    +
    +
    + <% end %>

    <%= t('notifications.title') %>

    diff --git a/config/initializers/constants.rb b/config/initializers/constants.rb index 7eae71806..5b8f0f5e0 100644 --- a/config/initializers/constants.rb +++ b/config/initializers/constants.rb @@ -115,7 +115,18 @@ class Constants # URL); it expires in exactly one day URL_LONG_EXPIRE_TIME = 86_400 - DATE_FORMAT = '%d.%m.%Y %H:%M'.freeze + DEFAULT_DATE_FORMAT = '%m/%d/%Y'.freeze + + SUPPORTED_DATE_FORMATS = [ + # US formats + '%m/%d/%Y', '%m.%d.%Y', '%m. %d. %Y', '%m-%d-%Y', '%-m/%-d/%Y', + '%-m.%-d.%Y', '%-m. %-d. %Y', '%-m-%-d-%Y', + # European formats + '%d/%m/%Y', '%d.%m.%Y', '%d. %m. %Y', '%d-%b-%Y', '%Y-%m-%d', + '%d.%b.%Y', '%Y/%b/%d', '%d, %B, %Y', '%B, %d, %Y', '%-d/%-m/%Y', + '%-d.%-m.%Y', '%-d. %-m. %Y', '%d-%m-%Y', '%Y-%-m-%-d', '%-d-%b-%Y', + '%Y-%b-%-d', '%-d, %B, %Y', '%B, %d, %Y' + ].freeze #============================================================================= # Application colors diff --git a/config/initializers/i18n.rb b/config/initializers/i18n.rb new file mode 100644 index 000000000..a5e3a45f8 --- /dev/null +++ b/config/initializers/i18n.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +I18n.backend = CustomI18nBackend.new diff --git a/config/locales/en.yml b/config/locales/en.yml index fbc45fc63..792ac6c4f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1437,6 +1437,9 @@ en: time_zone_label: "Time zone" time_zone_sublabel: "Time zone setting affects all time & date fields throughout application." time_zone_title: "Time zone" + date_format_label: "Date format" + date_format_sublabel: "Date format setting affects all date display throughout application." + date_format_title: "Date format" update_flash: "Preferences successfully updated." addons: head_title: "Settings | Add-ons" @@ -1810,16 +1813,10 @@ en: time: formats: - full: "%d.%m.%Y %H:%M" - # This format is used for JS datetimepicker, - # only in different notation; - # it should be the same as the above full format full_js: "D.M.YYYY HH:mm" - # This format is used only in datatables - # to format the timestamp in SQL so it can - # be easily searched by input param - datatables_date: 'DD.MM.YYYY HH24:MI' - full_date: "%d.%m.%Y" + full: "%{date_format} %H:%M" + full_with_tz: "%{date_format} %H:%M %z" + full_date: "%{date_format}" time: "%H:%M" short: "%H"