Merge branch 'develop' of github.com:martini/zammad into develop
This commit is contained in:
commit
20dbbfdf28
15 changed files with 280 additions and 452 deletions
|
@ -15,5 +15,6 @@ App.Config.set( 'Admin', { prio: 9000, parent: '', name: 'Admin', translate: tru
|
||||||
App.Config.set( 'New', { prio: 20000, parent: '', name: 'New', translate: true, target: '#new', class: 'add' }, 'NavBarRight' )
|
App.Config.set( 'New', { prio: 20000, parent: '', name: 'New', translate: true, target: '#new', class: 'add' }, 'NavBarRight' )
|
||||||
|
|
||||||
App.Config.set( 'Misc', { prio: 90000, parent: '', name: 'Tools', translate: true, target: '#tools', child: true, class: 'tools' }, 'NavBar' )
|
App.Config.set( 'Misc', { prio: 90000, parent: '', name: 'Tools', translate: true, target: '#tools', child: true, class: 'tools' }, 'NavBar' )
|
||||||
App.Config.set( 'Misc1', { prio: 1600, parent: '#tools', name: 'Test 1', target: '#test1', role: [ 'Admin' ] }, 'NavBar' )
|
# only for testing
|
||||||
App.Config.set( 'Misc2', { prio: 1700, parent: '#tools', name: 'Test 2', target: '#test2', role: [ 'Admin' ] }, 'NavBar' )
|
#App.Config.set( 'Misc1', { prio: 1600, parent: '#tools', name: 'Test 1', target: '#test1', role: [ 'Admin' ] }, 'NavBar' )
|
||||||
|
#App.Config.set( 'Misc2', { prio: 1700, parent: '#tools', name: 'Test 2', target: '#test2', role: [ 'Admin' ] }, 'NavBar' )
|
||||||
|
|
|
@ -6,52 +6,36 @@ class App.UiElement.date
|
||||||
attribute.nameRaw = attribute.name
|
attribute.nameRaw = attribute.name
|
||||||
attribute.name = "{date}#{attribute.name}"
|
attribute.name = "{date}#{attribute.name}"
|
||||||
|
|
||||||
# get time object
|
|
||||||
if attribute.value
|
|
||||||
if typeof attribute.value is 'string'
|
|
||||||
time = new Date( Date.parse( "#{attribute.value}T00:00:00Z" ) )
|
|
||||||
else
|
|
||||||
time = new Date( attribute.value )
|
|
||||||
|
|
||||||
# time items
|
|
||||||
year = time.getUTCFullYear()
|
|
||||||
month = time.getUTCMonth() + 1
|
|
||||||
day = time.getUTCDate()
|
|
||||||
|
|
||||||
# create element
|
|
||||||
item = $( App.view('generic/date')(
|
item = $( App.view('generic/date')(
|
||||||
attribute: attribute
|
attribute: attribute
|
||||||
year: year
|
|
||||||
month: month
|
|
||||||
day: day
|
|
||||||
) )
|
) )
|
||||||
|
|
||||||
# start bindings
|
# apply date widgets
|
||||||
item.find('.js-today').bind('click', (e) =>
|
$.fn.datepicker.dates['custom'] =
|
||||||
e.preventDefault()
|
days: [App.i18n.translateInline('Sunday'), App.i18n.translateInline('Monday'), App.i18n.translateInline('Tuesday'), App.i18n.translateInline('Wednesday'), App.i18n.translateInline('Thursday'), App.i18n.translateInline('Friday'), App.i18n.translateInline('Saturday'), App.i18n.translateInline('Sunday')],
|
||||||
@setNewTime(item, attribute, 0, true)
|
daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
|
||||||
@validation(item, attribute)
|
daysMin: [App.i18n.translateInline('Su'), App.i18n.translateInline('Mo'), App.i18n.translateInline('Tu'), App.i18n.translateInline('We'), App.i18n.translateInline('Th'), App.i18n.translateInline('Fr'), App.i18n.translateInline('Sa'), App.i18n.translateInline('Su')],
|
||||||
)
|
months: [App.i18n.translateInline('January'), App.i18n.translateInline('February'), App.i18n.translateInline('March'), App.i18n.translateInline('April'), App.i18n.translateInline('May'), App.i18n.translateInline('June'), App.i18n.translateInline('July'), App.i18n.translateInline('August'), App.i18n.translateInline('September'), App.i18n.translateInline('October'), App.i18n.translateInline('November'), App.i18n.translateInline('December')],
|
||||||
item.find('.js-plus-day').bind('click', (e) =>
|
monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
|
||||||
e.preventDefault()
|
today: App.i18n.translateInline('today'),
|
||||||
@setNewTime(item, attribute, 60 * 24, false, true)
|
clear: App.i18n.translateInline('clear')
|
||||||
@validation(item, attribute)
|
currentDate = undefined
|
||||||
)
|
if attribute.value
|
||||||
item.find('.js-minus-day').bind('click', (e) =>
|
startDate = new Date(attribute.value)
|
||||||
e.preventDefault()
|
item.find('.js-datepicker').datepicker(
|
||||||
@setNewTime(item, attribute, -60 * 24, false, true)
|
autoclose: true
|
||||||
@validation(item, attribute)
|
todayBtn: 'linked'
|
||||||
)
|
todayHighlight: true
|
||||||
item.find('.js-plus-week').bind('click', (e) =>
|
#startDate: startDate
|
||||||
e.preventDefault()
|
format: App.i18n.timeFormat().date
|
||||||
@setNewTime(item, attribute, 60 * 24 * 7, false, true)
|
container: item
|
||||||
@validation(item, attribute)
|
language: 'custom'
|
||||||
)
|
|
||||||
item.find('.js-minus-week').bind('click', (e) =>
|
|
||||||
e.preventDefault()
|
|
||||||
@setNewTime(item, attribute, -60 * 24 * 7, false, true)
|
|
||||||
@validation(item, attribute)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# set initial date time
|
||||||
|
@setNewTimeInitial(item, attribute)
|
||||||
|
|
||||||
|
# observer changes
|
||||||
item.find('input').bind('keyup blur focus change', (e) =>
|
item.find('input').bind('keyup blur focus change', (e) =>
|
||||||
@setNewTime(item, attribute, 0)
|
@setNewTime(item, attribute, 0)
|
||||||
@validation(item, attribute, true)
|
@validation(item, attribute, true)
|
||||||
|
@ -59,64 +43,42 @@ class App.UiElement.date
|
||||||
item.bind('validate', (e) =>
|
item.bind('validate', (e) =>
|
||||||
@validation(item, attribute)
|
@validation(item, attribute)
|
||||||
)
|
)
|
||||||
#setShadowTimestamp()
|
|
||||||
@setNewTime(item, attribute, 0)
|
|
||||||
|
|
||||||
item
|
item
|
||||||
|
|
||||||
@format: (number) ->
|
@setNewTime: (item, attribute, tolerant = false) ->
|
||||||
if number isnt '' && Number(number) < 10
|
|
||||||
number = "0#{Number(number)}"
|
|
||||||
number
|
|
||||||
|
|
||||||
@setNewTime: (item, attribute, diff, reset = false, tolerant = false) ->
|
datetime = item.find('.js-datepicker').datepicker('getDate')
|
||||||
|
if !datetime || datetime.toString() is 'Invalid Date'
|
||||||
resetTimeToToday = =>
|
App.Log.debug 'UiElement.date.setNewTime', datetime
|
||||||
time = new Date()
|
item.find("[name=\"#{attribute.name}\"]").val('')
|
||||||
time.setMinutes( time.getMinutes() + diff )
|
|
||||||
@setParams(item, attribute, time)
|
|
||||||
|
|
||||||
return resetTimeToToday() if reset
|
|
||||||
|
|
||||||
params = @getParams(item)
|
|
||||||
if params.year is '' && params.month is '' && params.day is ''
|
|
||||||
return if !tolerant
|
|
||||||
resetTimeToToday()
|
|
||||||
params = @getParams(item)
|
|
||||||
|
|
||||||
time = new Date( Date.parse( "#{params.year}-#{@format(params.month)}-#{@format(params.day)}T00:00:00Z" ) )
|
|
||||||
time.setMinutes( time.getMinutes() + diff )
|
|
||||||
return if !time
|
|
||||||
@setParams(item, attribute, time)
|
|
||||||
|
|
||||||
@setShadowTimestamp: (item, attribute, time) ->
|
|
||||||
timestamp = ''
|
|
||||||
if time
|
|
||||||
timestamp = time.toISOString().replace(/T\d\d:\d\d:\d\d\.\d\d\dZ$/, '')
|
|
||||||
item.find("[name=\"#{attribute.name}\"]").val(timestamp)
|
|
||||||
|
|
||||||
@setParams: (item, attribute, time) ->
|
|
||||||
App.Log.debug 'UiElement.date.setParams', time.toString()
|
|
||||||
|
|
||||||
if time.toString() is 'Invalid Date'
|
|
||||||
@setShadowTimestamp(item, attribute)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
day = time.getDate()
|
App.Log.debug 'UiElement.date.setNewTime', datetime
|
||||||
month = time.getMonth()+1
|
year = datetime.getFullYear()
|
||||||
year = time.getFullYear()
|
month = datetime.getMonth() + 1
|
||||||
item.find('[data-item=day]').val(day)
|
day = datetime.getDate()
|
||||||
item.find('[data-item=month]').val(month)
|
date = "#{App.Utils.formatTime(year)}-#{App.Utils.formatTime(month,2)}-#{App.Utils.formatTime(day,2)}"
|
||||||
item.find('[data-item=year]').val(year)
|
|
||||||
@setShadowTimestamp(item, attribute, time)
|
|
||||||
|
|
||||||
@getParams: (item) ->
|
if date is ''
|
||||||
params = {}
|
item.find("[name=\"#{attribute.name}\"]").val('')
|
||||||
params.day = item.find('[data-item=day]').val().trim()
|
return
|
||||||
params.month = item.find('[data-item=month]').val().trim()
|
|
||||||
params.year = item.find('[data-item=year]').val().trim()
|
App.Log.debug 'UiElement.date.setNewTime', date
|
||||||
App.Log.debug 'UiElement.date.getParams', params
|
item.find("[name=\"#{attribute.name}\"]").val(date)
|
||||||
params
|
|
||||||
|
@setNewTimeInitial: (item, attribute) ->
|
||||||
|
App.Log.debug 'UiElement.date.setNewTimeInitial', timestamp
|
||||||
|
timestamp = item.find("[name=\"#{attribute.name}\"]").val()
|
||||||
|
return if !timestamp
|
||||||
|
|
||||||
|
timeObject = new Date( Date.parse( timestamp ) )
|
||||||
|
|
||||||
|
hour = timeObject.getHours()
|
||||||
|
minute = timeObject.getMinutes()
|
||||||
|
|
||||||
|
App.Log.debug 'UiElement.date.setNewTimeInitial', timestamp, timeObject
|
||||||
|
item.find('.js-datepicker').datepicker('setUTCDate', timeObject)
|
||||||
|
|
||||||
@validation: (item, attribute, runtime) ->
|
@validation: (item, attribute, runtime) ->
|
||||||
|
|
||||||
|
@ -126,57 +88,21 @@ class App.UiElement.date
|
||||||
item.find('.help-inline').html('')
|
item.find('.help-inline').html('')
|
||||||
item.closest('.form-group').find('.help-inline').html('')
|
item.closest('.form-group').find('.help-inline').html('')
|
||||||
|
|
||||||
params = @getParams(item)
|
timestamp = item.find("[name=\"#{attribute.name}\"]").val()
|
||||||
|
|
||||||
# check required attributes
|
# check required attributes
|
||||||
errors = {}
|
errors = {}
|
||||||
if !runtime && !attribute.null
|
if !timestamp
|
||||||
if params.day is ''
|
if !attribute.null
|
||||||
errors.day = 'missing'
|
errors[attribute.name] = 'missing'
|
||||||
if params.month is ''
|
else
|
||||||
errors.month = 'missing'
|
timeObject = new Date( Date.parse( timestamp ) )
|
||||||
if params.year is ''
|
|
||||||
errors.year = 'missing'
|
|
||||||
|
|
||||||
# ranges
|
|
||||||
if params.day
|
|
||||||
daysInMonth = 31
|
|
||||||
if params.month && params.year
|
|
||||||
daysInMonth = new Date(params.year, params.month, 0).getDate()
|
|
||||||
|
|
||||||
if isNaN( Number(params.day) )
|
|
||||||
errors.day = 'invalid'
|
|
||||||
else if Number(params.day) > daysInMonth || Number(params.day) < 1
|
|
||||||
errors.day = 'invalid'
|
|
||||||
|
|
||||||
if params.month
|
|
||||||
if isNaN( Number(params.month) )
|
|
||||||
errors.month = 'invalid'
|
|
||||||
else if Number(params.month) > 12 || Number(params.month) < 1
|
|
||||||
errors.month = 'invalid'
|
|
||||||
|
|
||||||
if params.year
|
|
||||||
if isNaN( Number(params.year) )
|
|
||||||
errors.year = 'invalid'
|
|
||||||
else if Number(params.year) > 2200 || Number(params.year) < 2001
|
|
||||||
errors.year = 'invalid'
|
|
||||||
|
|
||||||
|
|
||||||
#formGroup = item.closest('.form-group')
|
formGroup = item.closest('.form-group')
|
||||||
formGroup = item
|
|
||||||
App.Log.debug 'UiElement.date.validation', errors
|
App.Log.debug 'UiElement.date.validation', errors
|
||||||
if !_.isEmpty(errors)
|
return if _.isEmpty(errors)
|
||||||
|
|
||||||
# if field is required, if not do not show error
|
# show invalid options
|
||||||
if params.year is '' && params.day is '' && params.month is ''
|
for key, value of errors
|
||||||
return if attribute.null
|
formGroup.addClass('has-error')
|
||||||
item.closest('.form-group').addClass('has-error')
|
|
||||||
item.closest('.form-group').find('.help-inline').text( 'is required' )
|
|
||||||
return
|
|
||||||
|
|
||||||
# show invalid options
|
|
||||||
for key, value of errors
|
|
||||||
formGroup.addClass('has-error')
|
|
||||||
formGroup.find("[data-item=#{key}]").addClass('has-error')
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
|
@ -6,66 +6,39 @@ class App.UiElement.datetime
|
||||||
attribute.nameRaw = attribute.name
|
attribute.nameRaw = attribute.name
|
||||||
attribute.name = "{datetime}#{attribute.name}"
|
attribute.name = "{datetime}#{attribute.name}"
|
||||||
|
|
||||||
# get time object
|
|
||||||
if attribute.value
|
|
||||||
if typeof attribute.value is 'string'
|
|
||||||
time = new Date( Date.parse( attribute.value ) )
|
|
||||||
else
|
|
||||||
time = new Date( attribute.value )
|
|
||||||
|
|
||||||
# time items
|
|
||||||
year = time.getFullYear()
|
|
||||||
month = time.getMonth() + 1
|
|
||||||
day = time.getDate()
|
|
||||||
hour = time.getHours()
|
|
||||||
minute = time.getMinutes()
|
|
||||||
|
|
||||||
# create element
|
|
||||||
item = $( App.view('generic/datetime')(
|
item = $( App.view('generic/datetime')(
|
||||||
attribute: attribute
|
attribute: attribute
|
||||||
year: year
|
|
||||||
month: month
|
|
||||||
day: day
|
|
||||||
hour: hour
|
|
||||||
minute: minute
|
|
||||||
) )
|
) )
|
||||||
|
|
||||||
# start bindings
|
# apply date widgets
|
||||||
item.find('.js-today').bind('click', (e) =>
|
$.fn.datepicker.dates['custom'] =
|
||||||
e.preventDefault()
|
days: [App.i18n.translateInline('Sunday'), App.i18n.translateInline('Monday'), App.i18n.translateInline('Tuesday'), App.i18n.translateInline('Wednesday'), App.i18n.translateInline('Thursday'), App.i18n.translateInline('Friday'), App.i18n.translateInline('Saturday'), App.i18n.translateInline('Sunday')],
|
||||||
@setNewTime(item, attribute, 0, true)
|
daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
|
||||||
@validation(item, attribute)
|
daysMin: [App.i18n.translateInline('Su'), App.i18n.translateInline('Mo'), App.i18n.translateInline('Tu'), App.i18n.translateInline('We'), App.i18n.translateInline('Th'), App.i18n.translateInline('Fr'), App.i18n.translateInline('Sa'), App.i18n.translateInline('Su')],
|
||||||
)
|
months: [App.i18n.translateInline('January'), App.i18n.translateInline('February'), App.i18n.translateInline('March'), App.i18n.translateInline('April'), App.i18n.translateInline('May'), App.i18n.translateInline('June'), App.i18n.translateInline('July'), App.i18n.translateInline('August'), App.i18n.translateInline('September'), App.i18n.translateInline('October'), App.i18n.translateInline('November'), App.i18n.translateInline('December')],
|
||||||
item.find('.js-plus-hour').bind('click', (e) =>
|
monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
|
||||||
e.preventDefault()
|
today: App.i18n.translateInline('today'),
|
||||||
@setNewTime(item, attribute, 60, false, true)
|
clear: App.i18n.translateInline('clear')
|
||||||
@validation(item, attribute)
|
currentDate = undefined
|
||||||
)
|
if attribute.value
|
||||||
item.find('.js-minus-hour').bind('click', (e) =>
|
startDate = new Date(attribute.value)
|
||||||
e.preventDefault()
|
item.find('.js-datepicker').datepicker(
|
||||||
@setNewTime(item, attribute, -60, false, true)
|
autoclose: true
|
||||||
@validation(item, attribute)
|
todayBtn: 'linked'
|
||||||
)
|
todayHighlight: true
|
||||||
item.find('.js-plus-day').bind('click', (e) =>
|
#startDate: startDate
|
||||||
e.preventDefault()
|
format: App.i18n.timeFormat().date
|
||||||
@setNewTime(item, attribute, 60 * 24, false, true)
|
container: item
|
||||||
@validation(item, attribute)
|
language: 'custom'
|
||||||
)
|
|
||||||
item.find('.js-minus-day').bind('click', (e) =>
|
|
||||||
e.preventDefault()
|
|
||||||
@setNewTime(item, attribute, -60 * 24, false, true)
|
|
||||||
@validation(item, attribute)
|
|
||||||
)
|
|
||||||
item.find('.js-plus-week').bind('click', (e) =>
|
|
||||||
e.preventDefault()
|
|
||||||
@setNewTime(item, attribute, 60 * 24 * 7, false, true)
|
|
||||||
@validation(item, attribute)
|
|
||||||
)
|
|
||||||
item.find('.js-minus-week').bind('click', (e) =>
|
|
||||||
e.preventDefault()
|
|
||||||
@setNewTime(item, attribute, -60 * 24 * 7, false, true)
|
|
||||||
@validation(item, attribute)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# set initial date time
|
||||||
|
@setNewTimeInitial(item, attribute)
|
||||||
|
|
||||||
|
# apply time widgets
|
||||||
|
item.find('.js-timepicker').timepicker()
|
||||||
|
|
||||||
|
# observer changes
|
||||||
item.find('input').bind('keyup blur focus change', (e) =>
|
item.find('input').bind('keyup blur focus change', (e) =>
|
||||||
@setNewTime(item, attribute, 0)
|
@setNewTime(item, attribute, 0)
|
||||||
@validation(item, attribute, true)
|
@validation(item, attribute, true)
|
||||||
|
@ -73,70 +46,51 @@ class App.UiElement.datetime
|
||||||
item.bind('validate', (e) =>
|
item.bind('validate', (e) =>
|
||||||
@validation(item, attribute)
|
@validation(item, attribute)
|
||||||
)
|
)
|
||||||
#setShadowTimestamp()
|
|
||||||
@setNewTime(item, attribute, 0)
|
|
||||||
|
|
||||||
item
|
item
|
||||||
|
|
||||||
@format: (number) ->
|
@setNewTime: (item, attribute, tolerant = false) ->
|
||||||
if number isnt '' && Number(number) < 10
|
|
||||||
number = "0#{Number(number)}"
|
|
||||||
number
|
|
||||||
|
|
||||||
@setNewTime: (item, attribute, diff, reset = false, tolerant = false) ->
|
datetime = item.find('.js-datepicker').datepicker('getDate')
|
||||||
|
if !datetime || datetime.toString() is 'Invalid Date'
|
||||||
resetTimeToToday = =>
|
App.Log.debug 'UiElement.datetime.setNewTime', datetime
|
||||||
time = new Date()
|
item.find("[name=\"#{attribute.name}\"]").val('')
|
||||||
time.setMinutes( time.getMinutes() + diff )
|
|
||||||
@setParams(item, attribute, time)
|
|
||||||
|
|
||||||
return resetTimeToToday() if reset
|
|
||||||
|
|
||||||
params = @getParams(item)
|
|
||||||
if params.year is '' && params.month is '' && params.day is '' && params.hour is '' && params.minute is ''
|
|
||||||
return if !tolerant
|
|
||||||
resetTimeToToday()
|
|
||||||
params = @getParams(item)
|
|
||||||
|
|
||||||
time = new Date( Date.parse( "#{params.year}-#{@format(params.month)}-#{@format(params.day)}T#{@format(params.hour)}:#{@format(params.minute)}:00Z" ) )
|
|
||||||
time.setMinutes( time.getMinutes() + diff + time.getTimezoneOffset() )
|
|
||||||
return if !time
|
|
||||||
@setParams(item, attribute, time)
|
|
||||||
|
|
||||||
@setShadowTimestamp: (item, attribute, time) ->
|
|
||||||
timestamp = ''
|
|
||||||
if time
|
|
||||||
timestamp = time.toISOString().replace(/\d\d\.\d\d\dZ$/, '00.000Z')
|
|
||||||
item.find("[name=\"#{attribute.name}\"]").val(timestamp)
|
|
||||||
|
|
||||||
@setParams: (item, attribute, time) ->
|
|
||||||
App.Log.debug 'UiElement.datetime.setParams', time.toString()
|
|
||||||
|
|
||||||
if time.toString() is 'Invalid Date'
|
|
||||||
@setShadowTimestamp(item, attribute)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
day = time.getDate()
|
App.Log.debug 'UiElement.datetime.setNewTime', datetime
|
||||||
month = time.getMonth()+1
|
year = datetime.getFullYear()
|
||||||
year = time.getFullYear()
|
month = datetime.getMonth() + 1
|
||||||
hour = time.getHours()
|
day = datetime.getDate()
|
||||||
minute = time.getMinutes()
|
date = "#{App.Utils.formatTime(year)}-#{App.Utils.formatTime(month,2)}-#{App.Utils.formatTime(day,2)}"
|
||||||
item.find('[data-item=day]').val(day)
|
time = item.find('.js-timepicker').val()
|
||||||
item.find('[data-item=month]').val(month)
|
|
||||||
item.find('[data-item=year]').val(year)
|
|
||||||
item.find('[data-item=hour]').val(hour)
|
|
||||||
item.find('[data-item=minute]').val(minute)
|
|
||||||
@setShadowTimestamp(item, attribute, time)
|
|
||||||
|
|
||||||
@getParams: (item) ->
|
if date is '' || time is ''
|
||||||
params = {}
|
item.find("[name=\"#{attribute.name}\"]").val('')
|
||||||
params.day = item.find('[data-item=day]').val().trim()
|
return
|
||||||
params.month = item.find('[data-item=month]').val().trim()
|
|
||||||
params.year = item.find('[data-item=year]').val().trim()
|
timestamp = "#{date}T#{time}:00.000Z"
|
||||||
params.hour = item.find('[data-item=hour]').val().trim()
|
time = new Date( Date.parse(timestamp) )
|
||||||
params.minute = item.find('[data-item=minute]').val().trim()
|
time.setMinutes( time.getMinutes() + time.getTimezoneOffset() )
|
||||||
App.Log.debug 'UiElement.datetime.getParams', params
|
App.Log.debug 'UiElement.datetime.setNewTime', time.toString()
|
||||||
params
|
timestamp = time.toISOString().replace(/\d\d\.\d\d\dZ$/, '00.000Z')
|
||||||
|
item.find("[name=\"#{attribute.name}\"]").val(timestamp)
|
||||||
|
|
||||||
|
@setNewTimeInitial: (item, attribute) ->
|
||||||
|
App.Log.debug 'UiElement.datetime.setNewTimeInitial', timestamp
|
||||||
|
timestamp = item.find("[name=\"#{attribute.name}\"]").val()
|
||||||
|
if !timestamp
|
||||||
|
item.find('.js-timepicker').val('08:00')
|
||||||
|
return
|
||||||
|
|
||||||
|
timeObject = new Date( Date.parse( timestamp ) )
|
||||||
|
|
||||||
|
hour = timeObject.getHours()
|
||||||
|
minute = timeObject.getMinutes()
|
||||||
|
time = "#{App.Utils.formatTime(hour,2)}:#{App.Utils.formatTime(minute,2)}"
|
||||||
|
|
||||||
|
App.Log.debug 'UiElement.datetime.setNewTimeInitial', timestamp, timeObject
|
||||||
|
item.find('.js-datepicker').datepicker('setUTCDate', timeObject)
|
||||||
|
item.find('.js-timepicker').val(time)
|
||||||
|
|
||||||
@validation: (item, attribute, runtime) ->
|
@validation: (item, attribute, runtime) ->
|
||||||
|
|
||||||
|
@ -146,72 +100,21 @@ class App.UiElement.datetime
|
||||||
item.find('.help-inline').html('')
|
item.find('.help-inline').html('')
|
||||||
item.closest('.form-group').find('.help-inline').html('')
|
item.closest('.form-group').find('.help-inline').html('')
|
||||||
|
|
||||||
params = @getParams(item)
|
timestamp = item.find("[name=\"#{attribute.name}\"]").val()
|
||||||
|
|
||||||
# check required attributes
|
# check required attributes
|
||||||
errors = {}
|
errors = {}
|
||||||
if !runtime && !attribute.null
|
if !timestamp
|
||||||
if params.day is ''
|
if !attribute.null
|
||||||
errors.day = 'missing'
|
errors[attribute.name] = 'missing'
|
||||||
if params.month is ''
|
else
|
||||||
errors.month = 'missing'
|
timeObject = new Date( Date.parse( timestamp ) )
|
||||||
if params.year is ''
|
|
||||||
errors.year = 'missing'
|
|
||||||
if params.hour is ''
|
|
||||||
errors.hour = 'missing'
|
|
||||||
if params.minute is ''
|
|
||||||
errors.minute = 'missing'
|
|
||||||
|
|
||||||
# ranges
|
|
||||||
if params.day
|
|
||||||
daysInMonth = 31
|
|
||||||
if params.month && params.year
|
|
||||||
daysInMonth = new Date(params.year, params.month, 0).getDate()
|
|
||||||
|
|
||||||
if isNaN( Number(params.day) )
|
formGroup = item.closest('.form-group')
|
||||||
errors.day = 'invalid'
|
|
||||||
else if Number(params.day) > daysInMonth || Number(params.day) < 1
|
|
||||||
errors.day = 'invalid'
|
|
||||||
|
|
||||||
if params.month
|
|
||||||
if isNaN( Number(params.month) )
|
|
||||||
errors.month = 'invalid'
|
|
||||||
else if Number(params.month) > 12 || Number(params.month) < 1
|
|
||||||
errors.month = 'invalid'
|
|
||||||
|
|
||||||
if params.year
|
|
||||||
if isNaN( Number(params.year) )
|
|
||||||
errors.year = 'invalid'
|
|
||||||
else if Number(params.year) > 2200 || Number(params.year) < 2001
|
|
||||||
errors.year = 'invalid'
|
|
||||||
|
|
||||||
if params.hour
|
|
||||||
if isNaN( Number(params.hour) )
|
|
||||||
errors.hour = 'invalid'
|
|
||||||
else if parseInt(params.hour) > 23 || parseInt(params.hour) < 0
|
|
||||||
errors.hour = 'invalid'
|
|
||||||
|
|
||||||
if params.minute
|
|
||||||
if isNaN( Number(params.minute) )
|
|
||||||
errors.minute = 'invalid'
|
|
||||||
else if Number(params.minute) > 59
|
|
||||||
errors.minute = 'invalid'
|
|
||||||
|
|
||||||
#formGroup = item.closest('.form-group')
|
|
||||||
formGroup = item
|
|
||||||
App.Log.debug 'UiElement.datetime.validation', errors
|
App.Log.debug 'UiElement.datetime.validation', errors
|
||||||
if !_.isEmpty(errors)
|
return if _.isEmpty(errors)
|
||||||
|
|
||||||
# if field is required, if not do not show error
|
# show invalid options
|
||||||
if params.year is '' && params.day is '' && params.month is '' && params.hour is '' && params.minute is ''
|
for key, value of errors
|
||||||
return if attribute.null
|
formGroup.addClass('has-error')
|
||||||
item.closest('.form-group').addClass('has-error')
|
|
||||||
item.closest('.form-group').find('.help-inline').text( 'is required' )
|
|
||||||
return
|
|
||||||
|
|
||||||
# show invalid options
|
|
||||||
for key, value of errors
|
|
||||||
formGroup.addClass('has-error')
|
|
||||||
formGroup.find("[data-item=#{key}]").addClass('has-error')
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
|
@ -15,8 +15,11 @@ class App.UiElement.ticket_perform_action
|
||||||
|
|
||||||
# ignore passwords and relations
|
# ignore passwords and relations
|
||||||
if row.type isnt 'password' && row.name.substr(row.name.length-4,4) isnt '_ids'
|
if row.type isnt 'password' && row.name.substr(row.name.length-4,4) isnt '_ids'
|
||||||
config = _.clone(row)
|
|
||||||
elements["#{groupKey}.#{config.name}"] = config
|
# ignore readonly attributes
|
||||||
|
if !row.readonly
|
||||||
|
config = _.clone(row)
|
||||||
|
elements["#{groupKey}.#{config.name}"] = config
|
||||||
|
|
||||||
[defaults, groups, elements]
|
[defaults, groups, elements]
|
||||||
|
|
||||||
|
|
|
@ -1509,15 +1509,16 @@ class InputsRef extends App.ControllerContent
|
||||||
# date picker
|
# date picker
|
||||||
@$('.js-datepicker3').datepicker(
|
@$('.js-datepicker3').datepicker(
|
||||||
todayHighlight: true
|
todayHighlight: true
|
||||||
startDate: new Date().toLocaleDateString('de-DE') # returns 25.09.2015
|
startDate: new Date()
|
||||||
format: 'dd.mm.yyyy',
|
format: App.i18n.timeFormat().date
|
||||||
container: @$('.js-datepicker3').parent()
|
container: @$('.js-datepicker3').parent()
|
||||||
)
|
)
|
||||||
|
|
||||||
# date time picker
|
# date time picker
|
||||||
@$('.js-datepicker4').datepicker(
|
@$('.js-datepicker4').datepicker(
|
||||||
todayHighlight: true
|
todayHighlight: true
|
||||||
startDate: new Date().toLocaleDateString('en-US') # returns 9/25/2015
|
startDate: new Date()
|
||||||
|
format: App.i18n.timeFormat().date
|
||||||
container: @$('.js-datepicker4').parent()
|
container: @$('.js-datepicker4').parent()
|
||||||
)
|
)
|
||||||
@$('.js-timepicker4').timepicker()
|
@$('.js-timepicker4').timepicker()
|
||||||
|
@ -1674,7 +1675,7 @@ class PrimaryEmailRef extends App.ControllerContent
|
||||||
App.Config.set( 'layout_ref/primary_email', PrimaryEmailRef, 'Routes' )
|
App.Config.set( 'layout_ref/primary_email', PrimaryEmailRef, 'Routes' )
|
||||||
|
|
||||||
|
|
||||||
class App.CustomerChatRef extends App.ControllerContent
|
class App.CustomerChatRef extends App.Controller
|
||||||
@extend Spine.Events
|
@extend Spine.Events
|
||||||
|
|
||||||
questions: [
|
questions: [
|
||||||
|
@ -1757,6 +1758,11 @@ class App.CustomerChatRef extends App.ControllerContent
|
||||||
# @testChat @chatWindows[0], 100
|
# @testChat @chatWindows[0], 100
|
||||||
@initQuiz()
|
@initQuiz()
|
||||||
|
|
||||||
|
show: (params) =>
|
||||||
|
|
||||||
|
# highlight navbar
|
||||||
|
@navupdate '#layout_ref/customer_chat'
|
||||||
|
|
||||||
testChat: (chat, count) ->
|
testChat: (chat, count) ->
|
||||||
for i in [0..count]
|
for i in [0..count]
|
||||||
text = @questions[Math.floor(Math.random() * @questions.length)].question
|
text = @questions[Math.floor(Math.random() * @questions.length)].question
|
||||||
|
@ -1849,12 +1855,24 @@ class App.CustomerChatRef extends App.ControllerContent
|
||||||
else
|
else
|
||||||
@nextQuestion()
|
@nextQuestion()
|
||||||
|
|
||||||
|
class CustomerChatRouter extends App.ControllerPermanent
|
||||||
|
constructor: (params) ->
|
||||||
|
super
|
||||||
|
|
||||||
|
# check authentication
|
||||||
|
return if !@authenticate()
|
||||||
|
|
||||||
App.Config.set( 'layout_ref/customer_chat', App.CustomerChatRef, 'Routes' )
|
App.TaskManager.execute(
|
||||||
|
key: 'CustomerChatRef'
|
||||||
|
controller: 'CustomerChatRef'
|
||||||
|
params: {}
|
||||||
|
show: true
|
||||||
|
persistent: true
|
||||||
|
)
|
||||||
|
|
||||||
App.Config.set( 'Chat', { prio: 300, parent: '', name: 'Customer Chat', target: '#layout_ref/customer_chat', switch: true, counter: true, role: ['Agent'], class: 'chat' }, 'NavBar' )
|
App.Config.set( 'layout_ref/customer_chat', CustomerChatRouter, 'Routes' )
|
||||||
# App.Config.set( 'Chat', { controller: 'CustomerChatRef', authentication: true }, 'permanentTask' )
|
App.Config.set( 'CustomerChatRef', { controller: 'CustomerChatRef', authentication: true }, 'permanentTask' )
|
||||||
|
App.Config.set( 'CustomerChatRef', { prio: 1200, parent: '', name: 'Customer Chat', target: '#layout_ref/customer_chat', switch: true, counter: true, role: ['Agent'], class: 'chat' }, 'NavBar' )
|
||||||
|
|
||||||
|
|
||||||
class chatWindowRef extends Spine.Controller
|
class chatWindowRef extends Spine.Controller
|
||||||
|
|
|
@ -20,7 +20,7 @@ class App.TicketZoomArticleView extends App.Controller
|
||||||
@el.append( all )
|
@el.append( all )
|
||||||
|
|
||||||
class ArticleViewItem extends App.Controller
|
class ArticleViewItem extends App.Controller
|
||||||
hasChangedAttributes: ['from', 'to', 'cc', 'subject', 'body', 'internal', 'preferences']
|
hasChangedAttributes: ['from', 'to', 'cc', 'subject', 'body', 'preferences']
|
||||||
|
|
||||||
elements:
|
elements:
|
||||||
'.textBubble-content': 'textBubbleContent'
|
'.textBubble-content': 'textBubbleContent'
|
||||||
|
@ -59,7 +59,7 @@ class ArticleViewItem extends App.Controller
|
||||||
App.TicketArticle.unsubscribe(@subscribeId)
|
App.TicketArticle.unsubscribe(@subscribeId)
|
||||||
|
|
||||||
setHighlighter: =>
|
setHighlighter: =>
|
||||||
return if !@el.is(':visible')
|
return if @el.is(':hidden')
|
||||||
# use delay do no ui blocking
|
# use delay do no ui blocking
|
||||||
#@highligher.loadHighlights(@ticket_article_id)
|
#@highligher.loadHighlights(@ticket_article_id)
|
||||||
d = =>
|
d = =>
|
||||||
|
@ -69,19 +69,19 @@ class ArticleViewItem extends App.Controller
|
||||||
hasChanged: (article) =>
|
hasChanged: (article) =>
|
||||||
|
|
||||||
# if no last article exists, remember it and return true
|
# if no last article exists, remember it and return true
|
||||||
if !@article_last_updated
|
if !@articleAttributesLastUpdate
|
||||||
@article_last_updated = {}
|
@articleAttributesLastUpdate = {}
|
||||||
for item in @hasChangedAttributes
|
for item in @hasChangedAttributes
|
||||||
@article_last_updated[item] = article[item]
|
@articleAttributesLastUpdate[item] = article[item]
|
||||||
return true
|
return true
|
||||||
|
|
||||||
# compare last and current article attributes
|
# compare last and current article attributes
|
||||||
article_last_updated_check = {}
|
articleAttributesLastUpdateCheck = {}
|
||||||
for item in @hasChangedAttributes
|
for item in @hasChangedAttributes
|
||||||
article_last_updated_check[item] = article[item]
|
articleAttributesLastUpdateCheck[item] = article[item]
|
||||||
diff = difference(@article_last_updated, article_last_updated_check)
|
diff = difference(@articleAttributesLastUpdate, articleAttributesLastUpdateCheck)
|
||||||
return false if !diff || _.isEmpty( diff )
|
return false if !diff || _.isEmpty( diff )
|
||||||
@article_last_updated = article_last_updated_check
|
@articleAttributesLastUpdate = articleAttributesLastUpdateCheck
|
||||||
true
|
true
|
||||||
|
|
||||||
render: (article) =>
|
render: (article) =>
|
||||||
|
@ -90,16 +90,22 @@ class ArticleViewItem extends App.Controller
|
||||||
@article = App.TicketArticle.fullLocal( @ticket_article_id )
|
@article = App.TicketArticle.fullLocal( @ticket_article_id )
|
||||||
|
|
||||||
# set @el attributes
|
# set @el attributes
|
||||||
@el.addClass("ticket-article-item #{@article.sender.name.toLowerCase()}")
|
if !article
|
||||||
if @article.internal is true
|
@el.addClass("ticket-article-item #{@article.sender.name.toLowerCase()}")
|
||||||
@el.addClass('is-internal')
|
@el.attr('data-id', @article.id)
|
||||||
else
|
@el.attr('id', "article-#{@article.id}")
|
||||||
@el.removeClass('is-internal')
|
|
||||||
@el.attr('data-id', @article.id)
|
# set internal change directly in dom, without rerender while article
|
||||||
@el.attr('id', "article-#{@article.id}")
|
if !article || ( @lastArticle && @lastArticle.internal isnt @article.internal )
|
||||||
|
if @article.internal is true
|
||||||
|
@el.addClass('is-internal')
|
||||||
|
else
|
||||||
|
@el.removeClass('is-internal')
|
||||||
|
|
||||||
# check if rerender is needed
|
# check if rerender is needed
|
||||||
return if !@hasChanged(@article)
|
if !@hasChanged(@article)
|
||||||
|
@lastArticle = @article.attributes()
|
||||||
|
return
|
||||||
|
|
||||||
# prepare html body
|
# prepare html body
|
||||||
if @article.content_type is 'text/html'
|
if @article.content_type is 'text/html'
|
||||||
|
@ -128,14 +134,16 @@ class ArticleViewItem extends App.Controller
|
||||||
|
|
||||||
# set see more
|
# set see more
|
||||||
@shown = false
|
@shown = false
|
||||||
@setSeeMore()
|
a = =>
|
||||||
|
@setSeeMore()
|
||||||
|
@delay( a, 50 )
|
||||||
|
|
||||||
# set highlighter
|
# set highlighter
|
||||||
@setHighlighter()
|
@setHighlighter()
|
||||||
|
|
||||||
# set see more options
|
# set see more options
|
||||||
setSeeMore: =>
|
setSeeMore: =>
|
||||||
return if !@el.is(':visible')
|
return if @el.is(':hidden')
|
||||||
return if @shown
|
return if @shown
|
||||||
@shown = true
|
@shown = true
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ class App.PostmasterFilter extends App.Model
|
||||||
{ name: 'channel', display: 'Channel', type: 'input', readonly: 1 },
|
{ name: 'channel', display: 'Channel', type: 'input', readonly: 1 },
|
||||||
{ name: 'match', display: 'Match all of the following', tag: 'postmaster_match' },
|
{ name: 'match', display: 'Match all of the following', tag: 'postmaster_match' },
|
||||||
{ name: 'perform', display: 'Perform action of the following', tag: 'postmaster_set' },
|
{ name: 'perform', display: 'Perform action of the following', tag: 'postmaster_set' },
|
||||||
{ name: 'note', display: 'Note', tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, null: true },
|
{ name: 'note', display: 'Note', tag: 'textarea', limit: 250, null: true },
|
||||||
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
|
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
|
||||||
{ name: 'active', display: 'Active', tag: 'active', default: true },
|
{ name: 'active', display: 'Active', tag: 'active', default: true },
|
||||||
{ name: 'created_by_id', display: 'Created by', relation: 'User', readonly: 1 },
|
{ name: 'created_by_id', display: 'Created by', relation: 'User', readonly: 1 },
|
||||||
|
|
|
@ -3,22 +3,22 @@ class App.Ticket extends App.Model
|
||||||
@extend Spine.Model.Ajax
|
@extend Spine.Model.Ajax
|
||||||
@url: @apiPath + '/tickets'
|
@url: @apiPath + '/tickets'
|
||||||
@configure_attributes = [
|
@configure_attributes = [
|
||||||
{ name: 'number', display: '#', tag: 'input', type: 'text', limit: 100, null: true, read_only: true, style: 'width: 68px' },
|
{ name: 'number', display: '#', tag: 'input', type: 'text', limit: 100, null: true, readonly: 1, style: 'width: 68px' },
|
||||||
{ name: 'title', display: 'Title', tag: 'input', type: 'text', limit: 100, null: false },
|
{ name: 'title', display: 'Title', tag: 'input', type: 'text', limit: 100, null: false },
|
||||||
{ name: 'customer_id', display: 'Customer', tag: 'input', type: 'text', limit: 100, null: false, autocapitalize: false, relation: 'User' },
|
{ name: 'customer_id', display: 'Customer', tag: 'input', type: 'text', limit: 100, null: false, autocapitalize: false, relation: 'User' },
|
||||||
{ name: 'organization_id', display: 'Organization', tag: 'select', relation: 'Organization', tagreadonly: 1 },
|
{ name: 'organization_id', display: 'Organization', tag: 'select', relation: 'Organization', readonly: 1 },
|
||||||
{ name: 'group_id', display: 'Group', tag: 'select', multiple: false, limit: 100, null: false, relation: 'Group', style: 'width: 10%', edit: true },
|
{ name: 'group_id', display: 'Group', tag: 'select', multiple: false, limit: 100, null: false, relation: 'Group', style: 'width: 10%', edit: true },
|
||||||
{ name: 'owner_id', display: 'Owner', tag: 'select', multiple: false, limit: 100, null: true, relation: 'User', style: 'width: 12%', edit: true },
|
{ name: 'owner_id', display: 'Owner', tag: 'select', multiple: false, limit: 100, null: true, relation: 'User', style: 'width: 12%', edit: true },
|
||||||
{ name: 'state_id', display: 'State', tag: 'select', multiple: false, null: false, relation: 'TicketState', default: 'new', style: 'width: 12%', edit: true, customer: true },
|
{ name: 'state_id', display: 'State', tag: 'select', multiple: false, null: false, relation: 'TicketState', default: 'new', style: 'width: 12%', edit: true, customer: true },
|
||||||
{ name: 'pending_time', display: 'Pending Time', tag: 'datetime', null: true, style: 'width: 130px' },
|
{ name: 'pending_time', display: 'Pending Time', tag: 'datetime', null: true, style: 'width: 130px' },
|
||||||
{ name: 'priority_id', display: 'Priority', tag: 'select', multiple: false, null: false, relation: 'TicketPriority', default: '2 normal', style: 'width: 12%', edit: true, customer: true },
|
{ name: 'priority_id', display: 'Priority', tag: 'select', multiple: false, null: false, relation: 'TicketPriority', default: '2 normal', style: 'width: 12%', edit: true, customer: true },
|
||||||
{ name: 'article_count', display: 'Article#', style: 'width: 12%' },
|
{ name: 'article_count', display: 'Article#', readonly: 1, style: 'width: 12%' },
|
||||||
{ name: 'escalation_time', display: 'Escalation', tag: 'datetime', null: true, style: 'width: 130px', class: 'escalation' },
|
{ name: 'escalation_time', display: 'Escalation', tag: 'datetime', null: true, readonly: 1, style: 'width: 130px', class: 'escalation' },
|
||||||
{ name: 'last_contact', display: 'Last contact', tag: 'datetime', null: true, style: 'width: 130px' },
|
{ name: 'last_contact', display: 'Last contact', tag: 'datetime', null: true, readonly: 1, style: 'width: 130px' },
|
||||||
{ name: 'last_contact_agent', display: 'Last contact (Agent)', tag: 'datetime', null: true, style: 'width: 130px' },
|
{ name: 'last_contact_agent', display: 'Last contact (Agent)', tag: 'datetime', null: true, readonly: 1, style: 'width: 130px' },
|
||||||
{ name: 'last_contact_customer', display: 'Last contact (Customer)', tag: 'datetime', null: true, style: 'width: 130px' },
|
{ name: 'last_contact_customer', display: 'Last contact (Customer)', tag: 'datetime', null: true, readonly: 1, style: 'width: 130px' },
|
||||||
{ name: 'first_response', display: 'First response', tag: 'datetime', null: true, style: 'width: 130px' },
|
{ name: 'first_response', display: 'First response', tag: 'datetime', null: true, readonly: 1, style: 'width: 130px' },
|
||||||
{ name: 'close_time', display: 'Close time', tag: 'datetime', null: true, style: 'width: 130px' },
|
{ name: 'close_time', display: 'Close time', tag: 'datetime', null: true, readonly: 1, style: 'width: 130px' },
|
||||||
{ name: 'created_by_id', display: 'Created by', relation: 'User', readonly: 1 },
|
{ name: 'created_by_id', display: 'Created by', relation: 'User', readonly: 1 },
|
||||||
{ name: 'created_at', display: 'Created at', tag: 'datetime', style: 'width: 130px', readonly: 1 },
|
{ name: 'created_at', display: 'Created at', tag: 'datetime', style: 'width: 130px', readonly: 1 },
|
||||||
{ name: 'updated_by_id', display: 'Updated by', relation: 'User', readonly: 1 },
|
{ name: 'updated_by_id', display: 'Updated by', relation: 'User', readonly: 1 },
|
||||||
|
|
|
@ -1,15 +1,4 @@
|
||||||
<div class="horizontal form-control" style="padding: 0 0 0 4px; line-height: 40px;" data-name="<%= @attribute.nameRaw %>">
|
<div class="" data-name="<%= @attribute.nameRaw %>">
|
||||||
<input type="hidden" name="<%= @attribute.name %>" value="<%= @attribute.value %>">
|
<input type="hidden" value="<%= @attribute.value %>" name="<%= @attribute.name %>">
|
||||||
<input type="text" maxlength="2" data-item="day" value="<%= @day %>" placeholder="dd" style="width: 36px; padding: 6px 6px; border: 1px solid #ffffff; height: 39px;">
|
<input type="text" value="" class="form-control js-datepicker" data-item="date">
|
||||||
.
|
</div>
|
||||||
<input type="text" maxlength="2" data-item="month" value="<%= @month %>" placeholder="mm" style="width: 36px; padding: 6px 6px; border: 1px solid #ffffff; height: 39px;">
|
|
||||||
.
|
|
||||||
<input type="text" maxlength="4" data-item="year" value="<%= @year %>" placeholder="yyyy" style="width: 54px; padding: 6px 6px; border: 1px solid #ffffff; height: 39px;">
|
|
||||||
</div>
|
|
||||||
<% if !@attribute.disable_feature: %>
|
|
||||||
<small>
|
|
||||||
<a href="#" class="js-today"><%- @T('today') %></a> |
|
|
||||||
<a href="#" class="js-minus-day">-1</a> <a href="#" class="js-plus-day">+1</a> <%- @T('day') %> |
|
|
||||||
<a href="#" class="js-minus-week">-7</a> <a href="#" class="js-plus-week">+7</a> <%- @T('days') %>
|
|
||||||
</small>
|
|
||||||
<% end %>
|
|
|
@ -1,19 +1,6 @@
|
||||||
<div class="horizontal form-control" style="padding: 0 0 0 4px; line-height: 40px;" data-name="<%= @attribute.nameRaw %>">
|
<div class="controls--bundle" data-name="<%= @attribute.nameRaw %>">
|
||||||
<input type="hidden" name="<%= @attribute.name %>" value="<%= @attribute.value %>">
|
<input type="hidden" value="<%= @attribute.value %>" name="<%= @attribute.name %>">
|
||||||
<input type="text" maxlength="2" data-item="day" value="<%= @day %>" placeholder="dd" style="width: 36px; padding: 6px 6px; border: 1px solid #ffffff; height: 39px;">
|
<input type="text" value="" class="form-control js-datepicker" data-item="date">
|
||||||
.
|
<div class="controls-label"><%- @T('at') %></div>
|
||||||
<input type="text" maxlength="2" data-item="month" value="<%= @month %>" placeholder="mm" style="width: 36px; padding: 6px 6px; border: 1px solid #ffffff; height: 39px;">
|
<input type="text" value="" class="form-control time js-timepicker" data-item="time">
|
||||||
.
|
</div>
|
||||||
<input type="text" maxlength="4" data-item="year" value="<%= @year %>" placeholder="yyyy" style="width: 54px; padding: 6px 6px; border: 1px solid #ffffff; height: 39px;">
|
|
||||||
<input type="text" maxlength="2" data-item="hour" value="<%= @hour %>" placeholder="00" style="width: 36px; padding: 6px 6px; border: 1px solid #ffffff; height: 39px;">
|
|
||||||
:
|
|
||||||
<input type="text" maxlength="2" data-item="minute" value="<%= @minute %>" placeholder="00" style="width: 36px; padding: 6px 6px; border: 1px solid #ffffff; height: 39px;">
|
|
||||||
</div>
|
|
||||||
<% if !@attribute.disable_feature: %>
|
|
||||||
<small>
|
|
||||||
<a href="#" class="js-today"><%- @T('now') %></a> |
|
|
||||||
<a href="#" class="js-minus-hour">-1</a> <a href="#" class="js-plus-hour">+1</a> <%- @T('hour') %> |
|
|
||||||
<a href="#" class="js-minus-day">-1</a> <a href="#" class="js-plus-day">+1</a> <%- @T('day') %> |
|
|
||||||
<a href="#" class="js-minus-week">-7</a> <a href="#" class="js-plus-week">+7</a> <%- @T('days') %>
|
|
||||||
</small>
|
|
||||||
<% end %>
|
|
|
@ -12,14 +12,14 @@
|
||||||
<p>A date</p>
|
<p>A date</p>
|
||||||
<div class="date form-group">
|
<div class="date form-group">
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input type="text" value="10/28/2015" class="form-control js-datepicker3">
|
<input type="text" value="<%- @Tdate('2014-10-28') %>" class="form-control js-datepicker3">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>A date time</p>
|
<p>A date time</p>
|
||||||
<div class="date form-group formGroup--bundle">
|
<div class="datetime form-group">
|
||||||
<div class="controls">
|
<div class="controls controls--bundle">
|
||||||
<input type="text" value="10/28/2015" class="form-control js-datepicker4">
|
<input type="text" value="<%- @Tdate('2015-10-28') %>" class="form-control js-datepicker4">
|
||||||
<div class="controls-label">at</div>
|
<div class="controls-label">at</div>
|
||||||
<input type="text" value="08:00" class="form-control time js-timepicker4">
|
<input type="text" value="08:00" class="form-control time js-timepicker4">
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
<div class="bubble-arrow"></div>
|
<div class="bubble-arrow"></div>
|
||||||
<div class="textBubble-content" id="article-content-<%= @article.id %>" data-id="<%= @article.id %>">
|
<div class="textBubble-content" id="article-content-<%= @article.id %>" data-id="<%= @article.id %>">
|
||||||
<%- App.Utils.signatureIdentify( @article.html ) %>
|
<%- App.Utils.signatureIdentify( @article.html ) %>
|
||||||
<div class="textBubble-overflowContainer">
|
<div class="textBubble-overflowContainer hide">
|
||||||
<div class="btn btn--text js-unfold"><%- @T('See more') %></div>
|
<div class="btn btn--text js-unfold"><%- @T('See more') %></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -127,11 +127,10 @@ test( 'datetime validation check', function() {
|
||||||
//equal( el.find('[data-name="datetime1"]').closest('.form-group').find('.help-inline').text(), '', 'check datetime1 error message')
|
//equal( el.find('[data-name="datetime1"]').closest('.form-group').find('.help-inline').text(), '', 'check datetime1 error message')
|
||||||
|
|
||||||
// set new values
|
// set new values
|
||||||
el.find('[data-name="datetime1"] [data-item="day"]').val(1).trigger('blur')
|
el.find('[data-name="datetime1"] [data-item="date"]').val('01/01/2015').trigger('blur')
|
||||||
el.find('[data-name="datetime1"] [data-item="month"]').val(1).trigger('blur')
|
el.find('[data-name="datetime1"] [data-item="date"]').datepicker('setDate')
|
||||||
el.find('[data-name="datetime1"] [data-item="year"]').val(2015).trigger('blur')
|
el.find('[data-name="datetime1"] [data-item="time"]').val('12:42').trigger('blur')
|
||||||
el.find('[data-name="datetime1"] [data-item="hour"]').val(12).trigger('blur')
|
el.find('[data-name="datetime1"] [data-item="time"]').trigger('change')
|
||||||
el.find('[data-name="datetime1"] [data-item="minute"]').val(42).trigger('blur')
|
|
||||||
|
|
||||||
// check params
|
// check params
|
||||||
timeStamp = new Date( Date.parse('2015-01-01T12:42:00.000Z') )
|
timeStamp = new Date( Date.parse('2015-01-01T12:42:00.000Z') )
|
||||||
|
@ -151,16 +150,12 @@ test( 'datetime validation check', function() {
|
||||||
equal( el.find('[data-name="datetime1"]').closest('.form-group').hasClass('has-error'), false, 'check datetime1 has-error')
|
equal( el.find('[data-name="datetime1"]').closest('.form-group').hasClass('has-error'), false, 'check datetime1 has-error')
|
||||||
equal( el.find('[data-name="datetime1"]').closest('.form-group').find('.help-inline').text(), '', 'check datetime1 error message')
|
equal( el.find('[data-name="datetime1"]').closest('.form-group').find('.help-inline').text(), '', 'check datetime1 error message')
|
||||||
|
|
||||||
el.find('[data-name="datetime1"] [data-item="day"]').val('47').trigger('blur')
|
el.find('[data-name="datetime1"] [data-item="date"]').val('').trigger('blur')
|
||||||
deepEqual( el.find('[data-name="datetime1"] [data-item="day"]').hasClass('has-error'), true )
|
el.find('[data-name="datetime1"] [data-item="date"]').datepicker('setDate')
|
||||||
el.find('[data-name="datetime1"] [data-item="month"]').val('1').trigger('blur')
|
el.find('[data-name="datetime1"] [data-item="time"]').val('12:42').trigger('blur')
|
||||||
deepEqual( el.find('[data-name="datetime1"] [data-item="month"]').hasClass('has-error'), false )
|
el.find('[data-name="datetime1"] [data-item="time"]').trigger('change')
|
||||||
el.find('[data-name="datetime1"] [data-item="year"]').val('2015').trigger('blur')
|
|
||||||
deepEqual( el.find('[data-name="datetime1"] [data-item="year"]').hasClass('has-error'), false )
|
equal( el.find('[data-name="datetime1"]').closest('.form-group').hasClass('has-error'), true )
|
||||||
el.find('[data-name="datetime1"] [data-item="hour"]').val('12').trigger('blur')
|
|
||||||
deepEqual( el.find('[data-name="datetime1"] [data-item="hour"]').hasClass('has-error'), false )
|
|
||||||
el.find('[data-name="datetime1"] [data-item="minute"]').val('42').trigger('blur')
|
|
||||||
deepEqual( el.find('[data-name="datetime1"] [data-item="minute"]').hasClass('has-error'), false )
|
|
||||||
|
|
||||||
params = App.ControllerForm.params( el )
|
params = App.ControllerForm.params( el )
|
||||||
errors = form.validate(params)
|
errors = form.validate(params)
|
||||||
|
@ -169,10 +164,9 @@ test( 'datetime validation check', function() {
|
||||||
}
|
}
|
||||||
deepEqual( errors, test_errors, 'validation errors check' )
|
deepEqual( errors, test_errors, 'validation errors check' )
|
||||||
App.ControllerForm.validate( { errors: errors, form: el } )
|
App.ControllerForm.validate( { errors: errors, form: el } )
|
||||||
equal( el.find('[data-name="datetime1"]').closest('.form-group').hasClass('has-error'), false, 'check datetime1 no has-error')
|
|
||||||
equal( el.find('[data-name="datetime1"] [data-item="day"]').hasClass('has-error'), true, 'check datetime1 no has-error')
|
equal( el.find('[data-name="datetime1"]').closest('.form-group').hasClass('has-error'), true, 'check datetime1 no has-error')
|
||||||
equal( el.find('[data-name="datetime1"] [data-item="month"]').hasClass('has-error'), false, 'check datetime1 no has-error')
|
equal( el.find('[data-name="datetime1"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check datetime1 error message')
|
||||||
equal( el.find('[data-name="datetime1"]').closest('.form-group').find('.help-inline').text(), '', 'check datetime1 error message')
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -186,7 +180,7 @@ test( 'date validation check', function() {
|
||||||
el: el,
|
el: el,
|
||||||
model: {
|
model: {
|
||||||
configure_attributes: [
|
configure_attributes: [
|
||||||
{ name: 'date1', display: 'Date1', tag: 'date', null: false, default: defaults['time1'] },
|
{ name: 'date2', display: 'Date2', tag: 'date', null: false, default: defaults['time1'] },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
params: defaults,
|
params: defaults,
|
||||||
|
@ -197,29 +191,29 @@ test( 'date validation check', function() {
|
||||||
// check params
|
// check params
|
||||||
params = App.ControllerForm.params( el )
|
params = App.ControllerForm.params( el )
|
||||||
test_params = {
|
test_params = {
|
||||||
date1: undefined,
|
date2: undefined,
|
||||||
}
|
}
|
||||||
deepEqual( params, test_params, 'params check' )
|
deepEqual( params, test_params, 'params check' )
|
||||||
|
|
||||||
errors = form.validate(params)
|
errors = form.validate(params)
|
||||||
test_errors = {
|
test_errors = {
|
||||||
date1: 'is required',
|
date2: 'is required',
|
||||||
}
|
}
|
||||||
deepEqual( errors, test_errors, 'validation errors check' )
|
deepEqual( errors, test_errors, 'validation errors check' )
|
||||||
App.ControllerForm.validate( { errors: errors, form: el } )
|
App.ControllerForm.validate( { errors: errors, form: el } )
|
||||||
|
|
||||||
equal( el.find('[data-name="date1"]').closest('.form-group').hasClass('has-error'), true, 'check date1 has-error')
|
equal( el.find('[data-name="date2"]').closest('.form-group').hasClass('has-error'), true, 'check date2 has-error')
|
||||||
equal( el.find('[data-name="date1"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check date1 error message')
|
equal( el.find('[data-name="date2"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check date2 error message')
|
||||||
|
|
||||||
// set new values
|
// set new values
|
||||||
el.find('[data-name="date1"] [data-item="day"]').val('1').trigger('blur')
|
el.find('[data-name="date2"] [data-item="date"]').val('01/01/2015').trigger('blur')
|
||||||
el.find('[data-name="date1"] [data-item="month"]').val('1').trigger('blur')
|
el.find('[data-name="date2"] [data-item="date"]').datepicker('setDate')
|
||||||
el.find('[data-name="date1"] [data-item="year"]').val('2015').trigger('blur')
|
el.find('[data-name="date2"] [data-item="date"]').trigger('change')
|
||||||
|
|
||||||
// check params
|
// check params
|
||||||
params = App.ControllerForm.params( el )
|
params = App.ControllerForm.params( el )
|
||||||
test_params = {
|
test_params = {
|
||||||
date1: '2015-01-01',
|
date2: '2015-01-01',
|
||||||
}
|
}
|
||||||
deepEqual( params, test_params, 'params check' )
|
deepEqual( params, test_params, 'params check' )
|
||||||
|
|
||||||
|
@ -228,37 +222,32 @@ test( 'date validation check', function() {
|
||||||
test_errors = undefined
|
test_errors = undefined
|
||||||
deepEqual( errors, test_errors, 'validation errors check' )
|
deepEqual( errors, test_errors, 'validation errors check' )
|
||||||
App.ControllerForm.validate( { errors: errors, form: el } )
|
App.ControllerForm.validate( { errors: errors, form: el } )
|
||||||
equal( el.find('[data-name="date1"]').closest('.form-group').hasClass('has-error'), false, 'check date1 has-error')
|
equal( el.find('[data-name="date2"]').closest('.form-group').hasClass('has-error'), false, 'check date1 has-error')
|
||||||
equal( el.find('[data-name="date1"]').closest('.form-group').find('.help-inline').text(), '', 'check date1 error message')
|
equal( el.find('[data-name="date2"]').closest('.form-group').find('.help-inline').text(), '', 'check date1 error message')
|
||||||
|
|
||||||
// set invalid values
|
// set invalid values
|
||||||
el.find('[data-name="date1"] [data-item="day"]').val('47').trigger('blur')
|
el.find('[data-name="date2"] [data-item="date"]').val('').trigger('blur')
|
||||||
deepEqual( el.find('[data-name="date1"] [data-item="day"]').hasClass('has-error'), true )
|
el.find('[data-name="date2"] [data-item="date"]').datepicker('setDate')
|
||||||
el.find('[data-name="date1"] [data-item="month"]').val('1').trigger('blur')
|
el.find('[data-name="date2"] [data-item="date"]').trigger('change')
|
||||||
deepEqual( el.find('[data-name="date1"] [data-item="month"]').hasClass('has-error'), false )
|
equal( el.find('[data-name="date2"]').closest('.form-group').hasClass('has-error'), true, 'check date2 has-error')
|
||||||
el.find('[data-name="date1"] [data-item="year"]').val('2015').trigger('blur')
|
|
||||||
deepEqual( el.find('[data-name="date1"] [data-item="year"]').hasClass('has-error'), false )
|
|
||||||
|
|
||||||
// check params
|
// check params
|
||||||
params = App.ControllerForm.params( el )
|
params = App.ControllerForm.params( el )
|
||||||
test_params = {
|
test_params = {
|
||||||
date1: undefined,
|
date2: undefined,
|
||||||
}
|
}
|
||||||
deepEqual( params, test_params, 'params check' )
|
deepEqual( params, test_params, 'params check' )
|
||||||
|
|
||||||
// check errors
|
// check errors
|
||||||
errors = form.validate(params)
|
errors = form.validate(params)
|
||||||
test_errors = {
|
test_errors = {
|
||||||
date1: 'is required',
|
date2: 'is required',
|
||||||
}
|
}
|
||||||
deepEqual( errors, test_errors, 'validation errors check' )
|
deepEqual( errors, test_errors, 'validation errors check' )
|
||||||
App.ControllerForm.validate( { errors: errors, form: el } )
|
App.ControllerForm.validate( { errors: errors, form: el } )
|
||||||
|
|
||||||
equal( el.find('[data-name="date1"]').closest('.form-group').hasClass('has-error'), false, 'check date1 no has-error')
|
equal( el.find('[data-name="date2"]').closest('.form-group').hasClass('has-error'), true, 'check date2 has-error')
|
||||||
equal( el.find('[data-name="date1"] [data-item="day"]').hasClass('has-error'), true, 'check date1 no has-error')
|
equal( el.find('[data-name="date2"]').closest('.form-group').find('.help-inline').text(), 'is required', 'check date2 error message')
|
||||||
equal( el.find('[data-name="date1"] [data-item="month"]').hasClass('has-error'), false, 'check date1 no has-error')
|
|
||||||
equal( el.find('[data-name="date1"]').closest('.form-group').find('.help-inline').text(), '', 'check date1 error message')
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test( "datetime selector check", function() {
|
test( "datetime selector check", function() {
|
||||||
|
@ -284,12 +273,14 @@ test( "datetime selector check", function() {
|
||||||
}
|
}
|
||||||
deepEqual( params, test_params, 'params check' )
|
deepEqual( params, test_params, 'params check' )
|
||||||
|
|
||||||
el.find('.js-today').click()
|
timeStamp = new Date()
|
||||||
|
|
||||||
|
el.find('.js-datepicker').datepicker('setDate', timeStamp)
|
||||||
|
el.find('.js-datepicker').trigger('blur')
|
||||||
|
|
||||||
// check params
|
// check params
|
||||||
timeStamp = new Date()
|
|
||||||
currentTime = timeStamp.toISOString()
|
currentTime = timeStamp.toISOString()
|
||||||
currentTime = currentTime.replace(/(\d\d\.\d\d\dZ)$/, '00.000Z')
|
currentTime = currentTime.replace(/(\d\d.\d\d.\d\d\.\d\d\dZ)$/, '07:00:00.000Z')
|
||||||
params = App.ControllerForm.params( el )
|
params = App.ControllerForm.params( el )
|
||||||
test_params = {
|
test_params = {
|
||||||
datetime1: currentTime,
|
datetime1: currentTime,
|
||||||
|
@ -308,7 +299,7 @@ test( "date selector check", function() {
|
||||||
el: el,
|
el: el,
|
||||||
model: {
|
model: {
|
||||||
configure_attributes: [
|
configure_attributes: [
|
||||||
{ name: 'date1', display: 'Datet1', tag: 'date', null: false, default: defaults['date1'] },
|
{ name: 'date3', display: 'Datet1', tag: 'date', null: false, default: defaults['date3'] },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
params: defaults,
|
params: defaults,
|
||||||
|
@ -317,11 +308,14 @@ test( "date selector check", function() {
|
||||||
// check params
|
// check params
|
||||||
params = App.ControllerForm.params( el )
|
params = App.ControllerForm.params( el )
|
||||||
test_params = {
|
test_params = {
|
||||||
date1: undefined,
|
date3: undefined,
|
||||||
}
|
}
|
||||||
deepEqual( params, test_params, 'params check' )
|
deepEqual( params, test_params, 'params check' )
|
||||||
|
|
||||||
el.find('.js-today').click()
|
timeStamp = new Date()
|
||||||
|
|
||||||
|
el.find('.js-datepicker').datepicker('setDate', timeStamp)
|
||||||
|
el.find('.js-datepicker').trigger('blur')
|
||||||
|
|
||||||
// check params
|
// check params
|
||||||
format = function (number) {
|
format = function (number) {
|
||||||
|
@ -331,11 +325,10 @@ test( "date selector check", function() {
|
||||||
return number
|
return number
|
||||||
}
|
}
|
||||||
|
|
||||||
timeStamp = new Date()
|
|
||||||
currentTime = timeStamp.getFullYear() + '-' + format(timeStamp.getMonth()+1) + '-' + format(timeStamp.getDate())
|
currentTime = timeStamp.getFullYear() + '-' + format(timeStamp.getMonth()+1) + '-' + format(timeStamp.getDate())
|
||||||
params = App.ControllerForm.params( el )
|
params = App.ControllerForm.params( el )
|
||||||
test_params = {
|
test_params = {
|
||||||
date1: currentTime,
|
date3: currentTime,
|
||||||
}
|
}
|
||||||
deepEqual( params, test_params, 'params check' )
|
deepEqual( params, test_params, 'params check' )
|
||||||
|
|
||||||
|
|
|
@ -28,24 +28,24 @@ class AgentTicketOverviewLevel1Test < TestCase
|
||||||
overview_create(
|
overview_create(
|
||||||
browser: browser1,
|
browser: browser1,
|
||||||
data: {
|
data: {
|
||||||
:name => name1,
|
name: name1,
|
||||||
:role => 'Agent',
|
role: 'Agent',
|
||||||
:selector => {
|
selector: {
|
||||||
'Priority' => '1 low',
|
'Priority' => '1 low',
|
||||||
},
|
},
|
||||||
:prio => 1000,
|
prio: 1000,
|
||||||
'order::direction' => 'down',
|
'order::direction' => 'down',
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
overview_create(
|
overview_create(
|
||||||
browser: browser1,
|
browser: browser1,
|
||||||
data: {
|
data: {
|
||||||
:name => name2,
|
name: name2,
|
||||||
:role => 'Agent',
|
role: 'Agent',
|
||||||
:selector => {
|
selector: {
|
||||||
'Priority' => '3 high',
|
'Priority' => '3 high',
|
||||||
},
|
},
|
||||||
:prio => 1001,
|
prio: 1001,
|
||||||
'order::direction' => 'down',
|
'order::direction' => 'down',
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -138,7 +138,7 @@ class TestCase < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
instance.find_elements( { css: '#login button' } )[0].click
|
instance.find_elements( { css: '#login button' } )[0].click
|
||||||
|
|
||||||
sleep 4
|
sleep 5
|
||||||
login = instance.find_elements( { css: '.user-menu .user a' } )[0].attribute('title')
|
login = instance.find_elements( { css: '.user-menu .user a' } )[0].attribute('title')
|
||||||
if login != params[:username]
|
if login != params[:username]
|
||||||
screenshot( browser: instance, comment: 'login_failed' )
|
screenshot( browser: instance, comment: 'login_failed' )
|
||||||
|
|
Loading…
Reference in a new issue