Improved pretty time.
This commit is contained in:
parent
fefb728954
commit
0a96e8b421
9 changed files with 221 additions and 87 deletions
|
@ -151,32 +151,6 @@ class App.Controller extends Spine.Controller
|
||||||
formValidate: (data) ->
|
formValidate: (data) ->
|
||||||
App.ControllerForm.validate(data)
|
App.ControllerForm.validate(data)
|
||||||
|
|
||||||
ticketTableAttributes: (attributes) =>
|
|
||||||
all_attributes = [
|
|
||||||
{ name: 'number', type: 'link', title: 'title', dataType: 'edit' },
|
|
||||||
{ name: 'title', type: 'link', title: 'title', dataType: 'edit' },
|
|
||||||
{ name: 'customer', class: 'user-popover', data: { id: true } },
|
|
||||||
{ name: 'state', translate: true, title: true },
|
|
||||||
{ name: 'priority', translate: true, title: true },
|
|
||||||
{ name: 'group', title: 'group' },
|
|
||||||
{ name: 'owner', class: 'user-popover', data: { id: true } },
|
|
||||||
{ name: 'created_at', callback: @frontendTime },
|
|
||||||
{ name: 'last_contact', callback: @frontendTime },
|
|
||||||
{ name: 'last_contact_agent', callback: @frontendTime },
|
|
||||||
{ name: 'last_contact_customer', callback: @frontendTime },
|
|
||||||
{ name: 'first_response', callback: @frontendTime },
|
|
||||||
{ name: 'close_time', callback: @frontendTime },
|
|
||||||
{ name: 'escalation_time', callback: @frontendTime, subclass: 'escalation' },
|
|
||||||
{ name: 'article_count', },
|
|
||||||
]
|
|
||||||
shown_all_attributes = []
|
|
||||||
for all_attribute in all_attributes
|
|
||||||
for attribute in attributes
|
|
||||||
if all_attribute['name'] is attribute
|
|
||||||
shown_all_attributes.push all_attribute
|
|
||||||
break
|
|
||||||
return shown_all_attributes
|
|
||||||
|
|
||||||
# redirectToLogin: (data) ->
|
# redirectToLogin: (data) ->
|
||||||
#
|
#
|
||||||
|
|
||||||
|
@ -188,66 +162,11 @@ class App.Controller extends Spine.Controller
|
||||||
size = Math.round( size / 1024 ) + ' KBytes'
|
size = Math.round( size / 1024 ) + ' KBytes'
|
||||||
else
|
else
|
||||||
size = size + ' Bytes'
|
size = size + ' Bytes'
|
||||||
return size
|
size
|
||||||
|
|
||||||
# human readable time
|
# human readable time
|
||||||
humanTime: ( time, escalation ) =>
|
humanTime: ( time, escalation, long = true ) =>
|
||||||
current = new Date()
|
App.PrettyDate.humanTime( time, escalation, long )
|
||||||
created = new Date(time)
|
|
||||||
string = ''
|
|
||||||
diff = ( current - created ) / 1000
|
|
||||||
escalated = ''
|
|
||||||
if escalation
|
|
||||||
if diff > 0
|
|
||||||
escalated = '-'
|
|
||||||
if diff >= 0
|
|
||||||
style = "class=\"label label-danger\""
|
|
||||||
else if diff > -60 * 60
|
|
||||||
style = "class=\"label label-warning\""
|
|
||||||
else
|
|
||||||
style = "class=\"label label-success\""
|
|
||||||
|
|
||||||
if diff.toString().match('-')
|
|
||||||
diff = diff.toString().replace('-', '')
|
|
||||||
diff = parseFloat(diff)
|
|
||||||
|
|
||||||
if diff >= 86400
|
|
||||||
unit = Math.floor( ( diff / 86400 ) )
|
|
||||||
# if unit > 1
|
|
||||||
# return unit + ' ' + App.i18n.translateContent('days')
|
|
||||||
# else
|
|
||||||
# return unit + ' ' + App.i18n.translateContent('day')
|
|
||||||
string = unit + ' ' + App.i18n.translateInline('d')
|
|
||||||
if diff >= 3600
|
|
||||||
unit = Math.floor( ( diff / 3600 ) % 24 )
|
|
||||||
# if unit > 1
|
|
||||||
# return unit + ' ' + App.i18n.translateContent('hours')
|
|
||||||
# else
|
|
||||||
# return unit + ' ' + App.i18n.translateContent('hour')
|
|
||||||
if string isnt ''
|
|
||||||
string = string + ' ' + unit + ' ' + App.i18n.translateInline('h')
|
|
||||||
if escalation
|
|
||||||
string = "<span #{style}>#{escalated}#{string}</b>"
|
|
||||||
return string
|
|
||||||
else
|
|
||||||
string = unit + ' ' + App.i18n.translateInline('h')
|
|
||||||
if diff <= 86400
|
|
||||||
unit = Math.floor( ( diff / 60 ) % 60 )
|
|
||||||
# if unit > 1
|
|
||||||
# return unit + ' ' + App.i18n.translateContent('minutes')
|
|
||||||
# else
|
|
||||||
# return unit + ' ' + App.i18n.translateContent('minute')
|
|
||||||
if string isnt ''
|
|
||||||
string = string + ' ' + unit + ' ' + App.i18n.translateInline('m')
|
|
||||||
if escalation
|
|
||||||
string = "<span #{style}>#{escalated}#{string}</b>"
|
|
||||||
return string
|
|
||||||
else
|
|
||||||
string = unit + ' ' + App.i18n.translateInline('m')
|
|
||||||
|
|
||||||
if escalation
|
|
||||||
string = "<span #{style}>#{escalated}#{string}</b>"
|
|
||||||
return string
|
|
||||||
|
|
||||||
userInfo: (data) =>
|
userInfo: (data) =>
|
||||||
el = data.el || $('[data-id="customer_info"]')
|
el = data.el || $('[data-id="customer_info"]')
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
class App.PrettyDate
|
||||||
|
|
||||||
|
# human readable time
|
||||||
|
@humanTime: ( time, escalation, long = true ) =>
|
||||||
|
return '' if !time
|
||||||
|
current = new Date()
|
||||||
|
created = new Date(time)
|
||||||
|
diff = ( current - created ) / 1000
|
||||||
|
|
||||||
|
escalated = ''
|
||||||
|
if escalation
|
||||||
|
if diff > 0
|
||||||
|
escalated = '-'
|
||||||
|
if diff >= 0
|
||||||
|
style = "class=\"label label-danger\""
|
||||||
|
else if diff > -60 * 60
|
||||||
|
style = "class=\"label label-warning\""
|
||||||
|
else
|
||||||
|
style = "class=\"label label-success\""
|
||||||
|
|
||||||
|
# remember past/future
|
||||||
|
direction = 'future'
|
||||||
|
if diff > -1
|
||||||
|
direction = 'past'
|
||||||
|
|
||||||
|
# strip not longer needed -
|
||||||
|
if diff.toString().match('-')
|
||||||
|
diff = diff.toString().replace('-', '')
|
||||||
|
diff = parseFloat(diff)
|
||||||
|
|
||||||
|
# days
|
||||||
|
string = ''
|
||||||
|
count = 0
|
||||||
|
if diff >= 86400
|
||||||
|
count++
|
||||||
|
unit = Math.floor( ( diff / 86400 ) )
|
||||||
|
day = App.i18n.translateInline('d')
|
||||||
|
if long
|
||||||
|
if unit > 1 || unit is 0
|
||||||
|
day = App.i18n.translateContent('days')
|
||||||
|
else
|
||||||
|
day = App.i18n.translateContent('day')
|
||||||
|
string = unit + ' ' + day
|
||||||
|
diff = diff - ( unit * 86400 )
|
||||||
|
if unit >= 9 || diff < 3600 || count is 2
|
||||||
|
if direction is 'past'
|
||||||
|
string = App.i18n.translateInline('%s ago', string)
|
||||||
|
else
|
||||||
|
string = App.i18n.translateInline('in %s', string)
|
||||||
|
if escalation
|
||||||
|
string = "<span #{style}>#{string}</b>"
|
||||||
|
return string
|
||||||
|
|
||||||
|
# hours
|
||||||
|
if diff >= 3600
|
||||||
|
count++
|
||||||
|
unit = Math.floor( ( diff / 3600 ) % 24 )
|
||||||
|
hour = App.i18n.translateInline('h')
|
||||||
|
if long
|
||||||
|
if unit > 1 || unit is 0
|
||||||
|
hour = App.i18n.translateInline('hours')
|
||||||
|
else
|
||||||
|
hour = App.i18n.translateInline('hour')
|
||||||
|
if string isnt ''
|
||||||
|
string = string + ' '
|
||||||
|
string = string + unit + ' ' + hour
|
||||||
|
diff = diff - ( unit * 3600 )
|
||||||
|
if unit >= 9 || diff < 60 || count is 2
|
||||||
|
if direction is 'past'
|
||||||
|
string = App.i18n.translateInline('%s ago', string)
|
||||||
|
else
|
||||||
|
string = App.i18n.translateInline('in %s', string)
|
||||||
|
if escalation
|
||||||
|
string = "<span #{style}>#{string}</b>"
|
||||||
|
return string
|
||||||
|
|
||||||
|
# minutes
|
||||||
|
unit = Math.floor( ( diff / 60 ) % 60 )
|
||||||
|
minute = App.i18n.translateInline('m')
|
||||||
|
if long
|
||||||
|
if unit > 1 || unit is 0
|
||||||
|
minute = App.i18n.translateContent('minutes')
|
||||||
|
else
|
||||||
|
minute = App.i18n.translateContent('minute')
|
||||||
|
if string isnt ''
|
||||||
|
string = string + ' '
|
||||||
|
string = string + unit + ' ' + minute
|
||||||
|
if direction is 'past'
|
||||||
|
string = App.i18n.translateInline('%s ago', string)
|
||||||
|
else
|
||||||
|
string = App.i18n.translateInline('in %s', string)
|
||||||
|
if escalation
|
||||||
|
string = "<span #{style}>#{string}</b>"
|
||||||
|
return string
|
|
@ -9,6 +9,13 @@ class TestsController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# GET /tests/ui
|
||||||
|
def ui
|
||||||
|
respond_to do |format|
|
||||||
|
format.html # index.html.erb
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# GET /tests/from
|
# GET /tests/from
|
||||||
def form
|
def form
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
|
|
|
@ -20,5 +20,3 @@ body {
|
||||||
<button type="submit" class="btn btn-primary submit">Submit</button>
|
<button type="submit" class="btn btn-primary submit">Submit</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
15
app/views/tests/ui.html.erb
Normal file
15
app/views/tests/ui.html.erb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="/assets/tests/qunit-1.10.0.css">
|
||||||
|
<script src="/assets/tests/qunit-1.10.0.js"></script>
|
||||||
|
<script src="/assets/tests/ui.js"></script>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
padding-top: 0px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div id="qunit"></div>
|
|
@ -1,6 +1,7 @@
|
||||||
Zammad::Application.routes.draw do
|
Zammad::Application.routes.draw do
|
||||||
|
|
||||||
match '/tests-core', :to => 'tests#core', :via => :get
|
match '/tests-core', :to => 'tests#core', :via => :get
|
||||||
|
match '/tests-ui', :to => 'tests#ui', :via => :get
|
||||||
match '/tests-form', :to => 'tests#form', :via => :get
|
match '/tests-form', :to => 'tests#form', :via => :get
|
||||||
match '/tests-table', :to => 'tests#table', :via => :get
|
match '/tests-table', :to => 'tests#table', :via => :get
|
||||||
match '/tests/wait/:sec', :to => 'tests#wait', :via => :get
|
match '/tests/wait/:sec', :to => 'tests#wait', :via => :get
|
||||||
|
|
|
@ -1700,7 +1700,7 @@ Translation.create_if_not_exists( :locale => 'de', :source => "Close time", :tar
|
||||||
Translation.create_if_not_exists( :locale => 'de', :source => "First response", :target => "Erste Reaktion" )
|
Translation.create_if_not_exists( :locale => 'de', :source => "First response", :target => "Erste Reaktion" )
|
||||||
Translation.create_if_not_exists( :locale => 'de', :source => "Ticket %s created!", :target => "Ticket %s erstellt!" )
|
Translation.create_if_not_exists( :locale => 'de', :source => "Ticket %s created!", :target => "Ticket %s erstellt!" )
|
||||||
Translation.create_if_not_exists( :locale => 'de', :source => "day", :target => "Tag" )
|
Translation.create_if_not_exists( :locale => 'de', :source => "day", :target => "Tag" )
|
||||||
Translation.create_if_not_exists( :locale => 'de', :source => "days", :target => "Tage" )
|
Translation.create_if_not_exists( :locale => 'de', :source => "days", :target => "Tagen" )
|
||||||
Translation.create_if_not_exists( :locale => 'de', :source => "hour", :target => "Stunde" )
|
Translation.create_if_not_exists( :locale => 'de', :source => "hour", :target => "Stunde" )
|
||||||
Translation.create_if_not_exists( :locale => 'de', :source => "hours", :target => "Stunden" )
|
Translation.create_if_not_exists( :locale => 'de', :source => "hours", :target => "Stunden" )
|
||||||
Translation.create_if_not_exists( :locale => 'de', :source => "minute", :target => "Minute" )
|
Translation.create_if_not_exists( :locale => 'de', :source => "minute", :target => "Minute" )
|
||||||
|
@ -1864,6 +1864,8 @@ Translation.create_if_not_exists( :locale => 'de', :source => "Here you can crea
|
||||||
Translation.create_if_not_exists( :locale => 'de', :source => "Fold in", :target => "Einklappen" )
|
Translation.create_if_not_exists( :locale => 'de', :source => "Fold in", :target => "Einklappen" )
|
||||||
Translation.create_if_not_exists( :locale => 'de', :source => "from", :target => "von" )
|
Translation.create_if_not_exists( :locale => 'de', :source => "from", :target => "von" )
|
||||||
Translation.create_if_not_exists( :locale => 'de', :source => "to", :target => "nach" )
|
Translation.create_if_not_exists( :locale => 'de', :source => "to", :target => "nach" )
|
||||||
|
Translation.create_if_not_exists( :locale => 'de', :source => "%s ago", :target => "vor %s" )
|
||||||
|
Translation.create_if_not_exists( :locale => 'de', :source => "in %s", :target => "in %s" )
|
||||||
#Translation.create_if_not_exists( :locale => 'de', :source => "", :target => "" )
|
#Translation.create_if_not_exists( :locale => 'de', :source => "", :target => "" )
|
||||||
|
|
||||||
# install all packages in auto_install
|
# install all packages in auto_install
|
||||||
|
|
76
public/assets/tests/ui.js
Normal file
76
public/assets/tests/ui.js
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
|
||||||
|
// pretty date
|
||||||
|
test( "check pretty date", function() {
|
||||||
|
var current = new Date()
|
||||||
|
|
||||||
|
// past
|
||||||
|
var result = App.PrettyDate.humanTime( current );
|
||||||
|
equal( result, '0 minutes ago', 'right now')
|
||||||
|
|
||||||
|
result = App.PrettyDate.humanTime( current - 60000 );
|
||||||
|
equal( result, '1 minute ago', '1 min ago')
|
||||||
|
|
||||||
|
result = App.PrettyDate.humanTime( current - ( 2 * 60000 ) );
|
||||||
|
equal( result, '2 minutes ago', '2 min ago')
|
||||||
|
|
||||||
|
result = App.PrettyDate.humanTime( current - ( 60000 * 60 ) ) ;
|
||||||
|
equal( result, '1 hour ago', '1 hour')
|
||||||
|
|
||||||
|
result = App.PrettyDate.humanTime( current - ( 60000 * 60 * 2 ) );
|
||||||
|
equal( result, '2 hours ago', '2 hours')
|
||||||
|
|
||||||
|
result = App.PrettyDate.humanTime( current - ( 60000 * 60 * 2.5 ) );
|
||||||
|
equal( result, '2 hours 30 minutes ago', '2.5 hours')
|
||||||
|
|
||||||
|
result = App.PrettyDate.humanTime( current - ( 60000 * 60 * 12.5 ) );
|
||||||
|
equal( result, '12 hours ago', '12.5 hours')
|
||||||
|
|
||||||
|
result = App.PrettyDate.humanTime( current - ( 60000 * 60 * 24 ) ) ;
|
||||||
|
equal( result, '1 day ago', '1 day')
|
||||||
|
|
||||||
|
result = App.PrettyDate.humanTime( current - ( 60000 * 60 * 24 * 2 ) );
|
||||||
|
equal( result, '2 days ago', '2 days')
|
||||||
|
|
||||||
|
result = App.PrettyDate.humanTime( current - ( 60000 * 60 * 24 * 2 ) - ( 60000 * 5 ) );
|
||||||
|
equal( result, '2 days ago', '2 days')
|
||||||
|
|
||||||
|
result = App.PrettyDate.humanTime( current - ( 60000 * 60 * 24 * 2.5 ) );
|
||||||
|
equal( result, '2 days 12 hours ago', '2.5 days')
|
||||||
|
|
||||||
|
result = App.PrettyDate.humanTime( current - ( 60000 * 60 * 24 * 2.5 ) - ( 60000 * 5 ) );
|
||||||
|
equal( result, '2 days 12 hours ago', '2.5 days')
|
||||||
|
|
||||||
|
result = App.PrettyDate.humanTime( current - ( 60000 * 60 * 24 * 10.5 ) );
|
||||||
|
equal( result, '10 days ago', '10.5 days')
|
||||||
|
|
||||||
|
// future
|
||||||
|
current = new Date()
|
||||||
|
result = App.PrettyDate.humanTime( current );
|
||||||
|
equal( result, '0 minutes ago', 'right now')
|
||||||
|
|
||||||
|
result = App.PrettyDate.humanTime( current.getTime() + 65000 );
|
||||||
|
equal( result, 'in 1 minute', 'in 1 min')
|
||||||
|
|
||||||
|
result = App.PrettyDate.humanTime( current.getTime() + ( 2 * 65000 ) );
|
||||||
|
equal( result, 'in 2 minutes', 'in 2 min')
|
||||||
|
|
||||||
|
result = App.PrettyDate.humanTime( current.getTime() + ( 60500 * 60 ) ) ;
|
||||||
|
equal( result, 'in 1 hour', 'in 1 hour')
|
||||||
|
|
||||||
|
result = App.PrettyDate.humanTime( current.getTime() + ( 60050 * 60 * 2 ) );
|
||||||
|
equal( result, 'in 2 hours', 'in 2 hours')
|
||||||
|
|
||||||
|
result = App.PrettyDate.humanTime( current.getTime() + ( 60050 * 60 * 2.5 ) );
|
||||||
|
equal( result, 'in 2 hours 30 minutes', 'in 2.5 hours')
|
||||||
|
|
||||||
|
result = App.PrettyDate.humanTime( current.getTime() + ( 60050 * 60 * 24 ) ) ;
|
||||||
|
equal( result, 'in 1 day', 'in 1 day')
|
||||||
|
|
||||||
|
result = App.PrettyDate.humanTime( current.getTime() + ( 60050 * 60 * 24 * 2 ) );
|
||||||
|
equal( result, 'in 2 days', 'in 2 days')
|
||||||
|
|
||||||
|
result = App.PrettyDate.humanTime( current.getTime() + ( 60050 * 60 * 24 * 2.5 ) );
|
||||||
|
equal( result, 'in 2 days 12 hours', 'in 2.5 days')
|
||||||
|
|
||||||
|
|
||||||
|
});
|
|
@ -24,6 +24,28 @@ class AAbUnitTest < TestCase
|
||||||
]
|
]
|
||||||
browser_single_test(tests)
|
browser_single_test(tests)
|
||||||
end
|
end
|
||||||
|
def test_ui
|
||||||
|
tests = [
|
||||||
|
{
|
||||||
|
:name => 'start',
|
||||||
|
:instance => browser_instance,
|
||||||
|
:url => browser_url + '/tests-ui',
|
||||||
|
:action => [
|
||||||
|
{
|
||||||
|
:execute => 'wait',
|
||||||
|
:value => 8,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:execute => 'match',
|
||||||
|
:css => '.result .failed',
|
||||||
|
:value => '0',
|
||||||
|
:match_result => true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
browser_single_test(tests)
|
||||||
|
end
|
||||||
def test_form
|
def test_form
|
||||||
tests = [
|
tests = [
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue