Просмотр исходного кода

Fixes #3018: Times in ticket history are displayed in UTC

Bola Ahmed Buari 3 лет назад
Родитель
Сommit
0fb4c1234e

+ 28 - 3
app/assets/javascripts/app/controllers/_application_controller/generic_history.coffee

@@ -83,7 +83,7 @@ class App.GenericHistory extends App.ControllerModal
       else
         content = "#{ @T( item.type ) } #{ @T(item.object) } "
         if item.attribute
-          content += "#{ @T(item.attribute) }"
+          content += "#{ @translateItemAttribute(item) }"
 
           # convert time stamps
           if item.object is 'User' && item.attribute is 'last_login'
@@ -95,12 +95,12 @@ class App.GenericHistory extends App.ControllerModal
         if item.value_from
           if item.value_to
             content += " #{ @T( 'from' ) }"
-          content += " '#{ App.Utils.htmlEscape(item.value_from) }'"
+          content += " '#{ @translateItemValue(item, item.value_from) }'"
 
         if item.value_to
           if item.value_from
             content += ' →'
-          content += " '#{ App.Utils.htmlEscape(item.value_to) }'"
+          content += " '#{ @translateItemValue(item, item.value_to) }'"
         else if item.value_from
           content += " → '-'"
 
@@ -110,3 +110,28 @@ class App.GenericHistory extends App.ControllerModal
       newItems.push newItem
 
     newItems
+
+  translateItemValue: ({object, attribute}, value) ->
+    localAttribute = @objectAttribute(object, attribute)
+    if localAttribute && localAttribute.tag is 'datetime'
+      return App.i18n.translateTimestamp(value)
+
+    if /_(time|at)$/.test(attribute)
+      return App.i18n.translateTimestamp(value)
+
+    if localAttribute && localAttribute.translate is true
+      return @T(value)
+
+    App.Utils.htmlEscape(value)
+
+  translateItemAttribute: ({object, attribute}) ->
+    localAttribute = @objectAttribute(object, attribute)
+    if localAttribute && localAttribute.display
+      return @T(localAttribute.display)
+
+    @T(attribute)
+
+  objectAttribute: (object, attribute) ->
+    return if !App[object]
+    return if !App[object].attributesGet()
+    App[object].attributesGet()["#{attribute}_id"] ||  App[object].attributesGet()[attribute]

+ 12 - 0
app/assets/javascripts/app/lib/app_post/i18n.coffee

@@ -365,6 +365,11 @@ class _i18nSingleton extends Spine.Module
     return time if !time
     @convert(time, offset, @mapTime['timestamp'] || @timestampFormat)
 
+  convertUTC: (time) ->
+    timeArray = time.match(/\d+/g)
+    [y, m, d, H, M] = timeArray
+    new Date(Date.UTC(y, m - 1, d, H, M))
+
   formatNumber: (num, digits) ->
     while num.toString().length < digits
       num = '0' + num
@@ -374,6 +379,13 @@ class _i18nSingleton extends Spine.Module
 
     timeObject = new Date(time)
 
+    # On firefox the Date constructor does not recongise date format that
+    # ends with UTC, instead it returns a NaN (Invalid Date Format) this
+    # block serves as polyfill to support time format that ends UTC in firefox
+    if isNaN(timeObject)
+       # works for only time string with this format: 2021-02-08 09:13:20 UTC
+      timeObject = @convertUTC(time) if time.match(/ UTC/)
+
     # add timezone diff, needed for unit tests
     if offset
       timeObject = new Date(timeObject.getTime() + (timeObject.getTimezoneOffset() * 60000))

+ 3 - 0
public/assets/tests/i18n.js

@@ -114,6 +114,9 @@ test('i18n .detectBrowserLocale', function() {
     var timestamp = App.i18n.translateTimestamp('2012-11-06T21:07:24Z', offset);
     equal(timestamp, '06.11.2012 21:07', 'de-de - timestamp translated correctly')
 
+    var timestamp = App.i18n.translateTimestamp('2021-02-08 09:13:20 UTC', offset);
+    equal(timestamp, '08.02.2021 09:13', 'de-de - timestamp translated correctly with UTC format')
+
     timestamp = App.i18n.translateTimestamp('', offset);
     equal(timestamp, '', 'de-de - timestamp translated correctly')
 

+ 81 - 0
spec/system/ticket/history_spec.rb

@@ -0,0 +1,81 @@
+require 'rails_helper'
+
+RSpec.describe 'Ticket history', type: :system, authenticated_as: true, time_zone: 'Europe/London' do
+  let(:group) { Group.find_by(name: 'Users') }
+  let(:ticket) { create(:ticket, group: group) }
+  let!(:session_user) { User.find_by(login: 'master@example.com') }
+
+  before do
+    freeze_time
+
+    travel_to DateTime.parse('2021-01-22 13:40:00 UTC')
+    current_time = Time.current
+    ticket.update(title: 'New Ticket Title')
+    ticket_article = create(:ticket_article, ticket: ticket, internal: true)
+    ticket.update! state: Ticket::State.lookup(name: 'open')
+    ticket.update! last_owner_update_at: current_time
+    ticket.update! priority: Ticket::Priority.lookup(name: '1 low')
+    ticket.update! last_contact_at: current_time
+    ticket.update! last_contact_customer_at: current_time
+    ticket.update! last_contact_agent_at: current_time
+    ticket_article.update! internal: false
+
+    travel_to DateTime.parse('2021-04-06 23:30:00 UTC')
+    current_time = Time.current
+    ticket.update! state: Ticket::State.lookup(name: 'pending close')
+    ticket.update! priority: Ticket::Priority.lookup(name: '3 high')
+    ticket_article.update! internal: true
+    ticket.update! last_contact_at: current_time
+    ticket.update! last_contact_customer_at: current_time
+    ticket.update! last_contact_agent_at: current_time
+    ticket.update! pending_time: current_time
+    ticket.update! first_response_escalation_at: current_time
+
+    travel_back
+
+    session_user.preferences[:locale] = 'de-de'
+    session_user.save!
+
+    refresh
+
+    visit "#ticket/zoom/#{ticket.id}"
+    find('[data-tab="ticket"] .js-actions').click
+    click('[data-type="ticket-history"]')
+  end
+
+  it "translates timestamp when attribute's tag is datetime" do
+    expect(page).to have_css('li', text: /22.01.2021 13:40/)
+  end
+
+  it 'does not include time with UTC format' do
+    expect(page).to have_no_text(/ UTC/)
+  end
+
+  it 'translates value when attribute is state' do
+    expect(page).to have_css('li', text: /Ticket Status von 'neu'/)
+  end
+
+  it 'translates value when attribute is priority' do
+    expect(page).to have_css('li', text: /Ticket Priorität von '1 niedrig'/)
+  end
+
+  it 'translates value when attribute is internal' do
+    expect(page).to have_css('li', text: /Artikel intern von 'true'/)
+  end
+
+  it 'translates last_contact_at display attribute' do
+    expect(page).to have_css('li', text: /Ticket Letzter Kontakt von '22.01.2021 13:40' → '07.04.2021 00:30'/)
+  end
+
+  it 'translates last_contact_customer_at display attribute' do
+    expect(page).to have_css('li', text: /Ticket Letzter Kontakt \(Kunde\) von '22.01.2021 13:40' → '07.04.2021 00:30'/)
+  end
+
+  it 'translates last_contact_agent_at display attribute' do
+    expect(page).to have_css('li', text: /Ticket Letzter Kontakt \(Agent\) von '22.01.2021 13:40' → '07.04.2021 00:30'/)
+  end
+
+  it 'translates pending_time display attribute' do
+    expect(page).to have_css('li', text: /Ticket Warten bis '07.04.2021 00:30'/)
+  end
+end

+ 53 - 0
spec/system/user/history_spec.rb

@@ -0,0 +1,53 @@
+require 'rails_helper'
+
+RSpec.describe 'Ticket history', type: :system, authenticated_as: true, time_zone: 'Europe/London' do
+  let(:group) { Group.find_by(name: 'Users') }
+  let(:customer) { create(:customer) }
+  let!(:session_user) { User.find_by(login: 'master@example.com') }
+
+  before do
+    freeze_time
+
+    travel_to DateTime.parse('2021-01-22 13:40:00 UTC')
+    current_time = Time.current
+    customer.update! firstname: 'Customer'
+    customer.update! email: 'test@example.com'
+    customer.update! country: 'Germany'
+    customer.update! out_of_office_start_at: current_time
+    customer.update! last_login: current_time
+
+    travel_to DateTime.parse('2021-04-06 23:30:00 UTC')
+    current_time = Time.current
+    customer.update! lastname: 'Example'
+    customer.update! mobile: '5757473827'
+    customer.update! out_of_office_end_at: current_time
+    customer.update! last_login: current_time
+
+    travel_back
+
+    session_user.preferences[:locale] = 'de-de'
+    session_user.save!
+
+    refresh
+
+    visit "#user/profile/#{customer.id}"
+    find('#userAction').click
+    click('[data-type="history"]')
+  end
+
+  it "translates timestamp when attribute's tag is datetime" do
+    expect(page).to have_css('li', text: /'22.01.2021 00:00'/)
+  end
+
+  it 'does not include time with UTC format' do
+    expect(page).to have_no_text(/ UTC/)
+  end
+
+  it 'translates out_of_office_start_at value to time stamp' do
+    expect(page).to have_css('li', text: /Benutzer out_of_office_start_at '22.01.2021 00:00'/)
+  end
+
+  it 'translates out_of_office_end_at value to time stamp' do
+    expect(page).to have_css('li', text: /Benutzer out_of_office_end_at '06.04.2021 01:00'/)
+  end
+end