Merge branch 'develop' of github.com:martini/zammad into develop

# Conflicts:
#	app/assets/javascripts/app/controllers/widget/online_notification.coffee
This commit is contained in:
Felix Niklas 2016-03-22 08:33:39 +01:00
commit b49b1fd00b
28 changed files with 957 additions and 320 deletions

View file

@ -43,7 +43,7 @@ GEM
addressable (2.4.0) addressable (2.4.0)
arel (6.0.3) arel (6.0.3)
ast (2.2.0) ast (2.2.0)
autoprefixer-rails (6.3.3.1) autoprefixer-rails (6.3.4)
execjs execjs
biz (1.4.0) biz (1.4.0)
clavius (~> 1.0) clavius (~> 1.0)
@ -76,7 +76,7 @@ GEM
diffy (3.1.0) diffy (3.1.0)
dnsruby (1.59.2) dnsruby (1.59.2)
docile (1.1.5) docile (1.1.5)
domain_name (0.5.20160309) domain_name (0.5.20160310)
unf (>= 0.0.5, < 1.0.0) unf (>= 0.0.5, < 1.0.0)
eco (1.0.0) eco (1.0.0)
coffee-script coffee-script
@ -115,7 +115,7 @@ GEM
multi_json (~> 1.8) multi_json (~> 1.8)
hashie (3.4.3) hashie (3.4.3)
htmlentities (4.3.4) htmlentities (4.3.4)
http (1.0.2) http (1.0.4)
addressable (~> 2.3) addressable (~> 2.3)
http-cookie (~> 1.0) http-cookie (~> 1.0)
http-form_data (~> 1.0.1) http-form_data (~> 1.0.1)
@ -199,7 +199,7 @@ GEM
coderay (~> 1.1.0) coderay (~> 1.1.0)
method_source (~> 0.8.1) method_source (~> 0.8.1)
slop (~> 3.4) slop (~> 3.4)
puma (3.1.0) puma (3.2.0)
rack (1.6.4) rack (1.6.4)
rack-livereload (0.3.16) rack-livereload (0.3.16)
rack rack
@ -277,7 +277,7 @@ GEM
activesupport (>= 4.0) activesupport (>= 4.0)
sprockets (>= 3.0.0) sprockets (>= 3.0.0)
sqlite3 (1.3.11) sqlite3 (1.3.11)
test-unit (3.1.7) test-unit (3.1.8)
power_assert power_assert
therubyracer (0.12.2) therubyracer (0.12.2)
libv8 (~> 3.16.14.0) libv8 (~> 3.16.14.0)

View file

@ -542,7 +542,7 @@ class App.Controller extends Spine.Controller
el.html App.view('generic/page_loading')() el.html App.view('generic/page_loading')()
else else
@html App.view('generic/page_loading')() @html App.view('generic/page_loading')()
@initLoadingDoneDelay = @delay(later, 2800) @initLoadingDoneDelay = @delay(later, 1800)
stopLoading: => stopLoading: =>
return if !@initLoadingDoneDelay return if !@initLoadingDoneDelay

View file

@ -124,7 +124,10 @@ class App.ControllerGenericIndex extends App.Controller
# fetch all # fetch all
if !@disableInitFetch if !@disableInitFetch
App[ @genericObject ].fetch() App[ @genericObject ].fetchFull(
->
clear: true
)
release: => release: =>
if @subscribeId if @subscribeId

View file

@ -12,7 +12,7 @@ class App.ChannelForm extends App.Controller
constructor: -> constructor: ->
super super
@title 'Form' @title 'Form'
@subscribeId = App.Setting.subscribe(@render, initFetch: true) @subscribeId = App.Setting.subscribe(@render, initFetch: true, clear: false)
render: => render: =>
App.Setting.unsubscribe(@subscribeId) App.Setting.unsubscribe(@subscribeId)

View file

@ -5,20 +5,7 @@ class App.SettingsArea extends App.Controller
# check authentication # check authentication
return if !@authenticate() return if !@authenticate()
@load() @subscribeId = App.Setting.subscribe(@render, initFetch: true, clear: false)
load: ->
@startLoading()
@ajax(
id: "setting_area_#{@area}"
type: 'GET'
url: "#{@apiPath}/settings/area/#{@area}"
processData: true
success: (data, status, xhr) =>
@stopLoading()
App.Collection.load( sessionStorage: false, type: 'Setting', data: data )
@render()
)
render: => render: =>

View file

@ -12,26 +12,17 @@ class Index extends App.ControllerContent
# check authentication # check authentication
return if !@authenticate(false, 'Admin') return if !@authenticate(false, 'Admin')
@interval(@load, 60000) @subscribeId = App.Calendar.subscribe(@render)
#@load()
load: =>
@startLoading()
@ajax(
id: 'calendar_index'
type: 'GET'
url: @apiPath + '/calendars'
processData: true
success: (data, status, xhr) =>
callback = (data) =>
App.Config.set('ical_feeds', data.ical_feeds) App.Config.set('ical_feeds', data.ical_feeds)
App.Config.set('timezones', data.timezones) App.Config.set('timezones', data.timezones)
# load assets
App.Collection.loadAssets(data.assets)
@stopLoading() @stopLoading()
@render(data) @render()
@startLoading()
App.Calendar.fetchFull(
callback
clear: true
) )
render: => render: =>

View file

@ -329,7 +329,7 @@ class App.Navigation extends App.ControllerWidgetPermanent
level1 = [] level1 = []
dropdown = {} dropdown = {}
roles = App.Session.get( 'roles' ) roles = App.Session.get('roles')
for item in navbar for item in navbar
if typeof item.callback is 'function' if typeof item.callback is 'function'
@ -341,11 +341,11 @@ class App.Navigation extends App.ControllerWidgetPermanent
if !item.role if !item.role
match = 1 match = 1
if !roles && item.role if !roles && item.role
match = _.include( item.role, 'Anybody' ) match = _.include(item.role, 'Anybody')
if roles if roles
for role in roles for role in roles
if !match if !match
match = _.include( item.role, role.name ) match = _.include(item.role, role.name)
if match if match
level1.push item level1.push item
@ -361,11 +361,11 @@ class App.Navigation extends App.ControllerWidgetPermanent
if !itemSub.role if !itemSub.role
match = 1 match = 1
if !roles if !roles
match = _.include( itemSub.role, 'Anybody' ) match = _.include(itemSub.role, 'Anybody')
if roles if roles
for role in roles for role in roles
if !match if !match
match = _.include( itemSub.role, role.name ) match = _.include(itemSub.role, role.name)
if match if match
dropdown[ item.parent ].push itemSub dropdown[ item.parent ].push itemSub
@ -373,13 +373,13 @@ class App.Navigation extends App.ControllerWidgetPermanent
# find parent # find parent
for itemLevel1 in level1 for itemLevel1 in level1
if itemLevel1.target is item.parent if itemLevel1.target is item.parent
sub = @getOrder( dropdown[ item.parent ] ) sub = @getOrder(dropdown[ item.parent ])
itemLevel1.child = sub itemLevel1.child = sub
# clean up, only show navbar items with existing childrens # clean up, only show navbar items with existing childrens
clean_list = [] clean_list = []
for item in level1 for item in level1
if !item.child || item.child && !_.isEmpty( item.child ) if !item.child || item.child && !_.isEmpty(item.child)
clean_list.push item clean_list.push item
nav = @getOrder(clean_list) nav = @getOrder(clean_list)
return nav return nav
@ -437,11 +437,11 @@ class App.Navigation extends App.ControllerWidgetPermanent
delete NavBarRight[key] delete NavBarRight[key]
if !@Session.get() if !@Session.get()
@Config.set( 'NavBarRight', NavBarRight ) @Config.set('NavBarRight', NavBarRight)
return return
# add new views # add new views
items = App.RecentView.search(sortBy: 'created_at', order: 'DESC' ) items = App.RecentView.search(sortBy: 'created_at', order: 'DESC')
items = @prepareForObjectList(items) items = @prepareForObjectList(items)
prio = 80 prio = 80
for item in items for item in items
@ -462,11 +462,11 @@ class App.Navigation extends App.ControllerWidgetPermanent
type: 'recentViewed' type: 'recentViewed'
} }
@Config.set( 'NavBarRight', NavBarRight ) @Config.set('NavBarRight', NavBarRight)
fetchRecentView: => fetchRecentView: =>
load = (items) => load = (data) =>
App.RecentView.refresh( items, { clear: true } ) App.RecentView.refresh(data.stream, clear: true)
@renderPersonal() @renderPersonal()
App.RecentView.fetchFull(load) App.RecentView.fetchFull(load)
@ -474,4 +474,4 @@ class App.Navigation extends App.ControllerWidgetPermanent
event.stopPropagation() event.stopPropagation()
@notificationWidget.toggle() @notificationWidget.toggle()
App.Config.set( 'navigation', App.Navigation, 'Navigations' ) App.Config.set('navigation', App.Navigation, 'Navigations')

View file

@ -11,20 +11,16 @@ class Index extends App.ControllerContent
# check authentication # check authentication
return if !@authenticate(false, 'Admin') return if !@authenticate(false, 'Admin')
@interval(@load, 60000) @subscribeCalendarId = App.Calendar.subscribe(@render)
#@load() @subscribeSlaId = App.Sla.subscribe(@render)
load: => callback = =>
@startLoading()
@ajax(
id: 'sla_index'
type: 'GET'
url: @apiPath + '/slas'
processData: true
success: (data, status, xhr) =>
App.Collection.loadAssets(data.assets)
@stopLoading() @stopLoading()
@render(data) @render()
@startLoading()
App.Sla.fetchFull(
callback
clear: true
) )
render: => render: =>
@ -56,8 +52,10 @@ class Index extends App.ControllerContent
) )
release: => release: =>
if @subscribeId if @subscribeCalendarId
App.Calendar.unsubscribe(@subscribeId) App.Calendar.unsubscribe(@subscribeCalendarId)
if @subscribeSlaId
App.Sla.unsubscribe(@subscribeSlaId)
new: (e) -> new: (e) ->
e.preventDefault() e.preventDefault()

View file

@ -1,7 +1,7 @@
class App.OnlineNotificationWidget extends App.Controller class App.OnlineNotificationWidget extends App.Controller
alreadyShown: {} alreadyShown: {}
shown: false shown: false
className: 'popover popover--notifications right' className: 'popover popover--notifications right js-notificationsContainer'
attributes: attributes:
role: 'tooltip' role: 'tooltip'
@ -10,13 +10,13 @@ class App.OnlineNotificationWidget extends App.Controller
'click .js-item': 'hide' 'click .js-item': 'hide'
'click .js-remove': 'removeItem' 'click .js-remove': 'removeItem'
'click .js-locationVerify': 'onItemClick' 'click .js-locationVerify': 'onItemClick'
'keydown': 'listNavigate' 'click': 'stopPropagation'
elements: elements:
'.js-notificationsContainer': 'container'
'.js-mark': 'mark' '.js-mark': 'mark'
'.js-item': 'item' '.js-item': 'item'
'.js-content': 'content' '.js-content': 'content'
'.js-header': 'header'
constructor: -> constructor: ->
super super
@ -50,7 +50,7 @@ class App.OnlineNotificationWidget extends App.Controller
return return
if @access() if @access()
@subscribeId = App.OnlineNotification.subscribe(@show) @subscribeId = App.OnlineNotification.subscribe(@updateContent)
@bind('ui:reshow', => @bind('ui:reshow', =>
@show() @show()
@ -58,9 +58,13 @@ class App.OnlineNotificationWidget extends App.Controller
) )
$(window).on 'click.notifications', @hide $(window).on 'click.notifications', @hide
$(window).on 'keydown.notifications', @listNavigate
@updateContent()
release: -> release: ->
$(window).off 'click.notifications' $(window).off 'click.notifications'
$(window).off 'keydown.notifications'
App.OnlineNotification.unsubscribe(@subscribeId) App.OnlineNotification.unsubscribe(@subscribeId)
super super
@ -97,7 +101,7 @@ class App.OnlineNotificationWidget extends App.Controller
current.removeClass('is-hover') current.removeClass('is-hover')
next.addClass('is-hover') next.addClass('is-hover')
else else
prev = current.prev('.is-item') prev = current.prev('.js-item')
if prev.size() if prev.size()
current.removeClass('is-hover') current.removeClass('is-hover')
prev.addClass('is-hover') prev.addClass('is-hover')
@ -131,29 +135,29 @@ class App.OnlineNotificationWidget extends App.Controller
) )
updateHeight: -> updateHeight: ->
# set height of notification popover # set height of notification popover
heightApp = $('#app').height() heightApp = $('#app').height()
heightPopoverSpacer = 22 heightPopoverSpacer = 22
heightPopoverHeader = @header.outerHeight(true) heightPopoverHeader = @header.outerHeight(true)
heightPopoverContent = 0
isOverflowing = false isOverflowing = false
@item.each -> @item.each (i, el) =>
# accumulate height of items # accumulate height of items
heightPopoverContent += @clientHeight heightPopoverContent += el.clientHeight
if (heightPopoverHeader + heightPopoverContent + heightPopoverSpacer) > heightApp if (heightPopoverHeader + heightPopoverContent + heightPopoverSpacer) > heightApp
heightPopoverContent = heightApp - heightPopoverHeader - heightPopoverSpacer @content.css 'height', heightApp - heightPopoverHeader - heightPopoverSpacer
isOverflowing = true isOverflowing = true
return false # exit .each loop return false # exit .each loop
@container.toggleClass('is-overflowing', isOverflowing) @el.toggleClass('is-overflowing', isOverflowing)
@content.css('height', heightPopoverContent) @content.css 'height', '' if !isOverflowing
fetch: => fetch: =>
load = (items) => load = (data) =>
@fetchedData = true @fetchedData = true
App.OnlineNotification.refresh(items, { clear: true }) App.OnlineNotification.refresh(data.stream, clear: true)
@show() @updateContent()
App.OnlineNotification.fetchFull(load) App.OnlineNotification.fetchFull(load)
toggle: => toggle: =>
@ -162,8 +166,7 @@ class App.OnlineNotificationWidget extends App.Controller
else else
@show() @show()
show: => updateContent: =>
@shown = true
if !@Session.get() if !@Session.get()
@content.html('') @content.html('')
return return
@ -195,23 +198,33 @@ class App.OnlineNotificationWidget extends App.Controller
) )
App.OnlineNotification.play() App.OnlineNotification.play()
@html App.view('widget/online_notification') @html App.view('widget/online_notification')(
items: items items: items
count: @count count: @count
)
return if !@shown
@show()
show: =>
@shown = true
@el.show() @el.show()
@updateHeight()
hide: => hide: =>
@shown = false @shown = false
@el.hide() @el.hide()
onItemClick: (event) -> onItemClick: (e) ->
@locationVerify(event) @locationVerify(e)
@hide() @hide()
removeItem: (event) -> stopPropagation: (e) ->
event.preventDefault() e.stopPropagation()
event.stopPropagation()
removeItem: (e) =>
e.preventDefault()
e.stopPropagation()
row = $(e.target).closest('.js-item') row = $(e.target).closest('.js-item')
id = row.data('id') id = row.data('id')
App.OnlineNotification.destroy(id) App.OnlineNotification.destroy(id)

View file

@ -85,16 +85,23 @@ class _collectionSingleton extends Spine.Module
return return
# load data from object # load data from object
listToRefresh = []
for key, object of params.data for key, object of params.data
if !params.refresh && appObject if !params.refresh && appObject
@log 'debug', 'refrest try', params.type, key
# check if new object is newer, just load newer objects # check if new object is newer, just load newer objects
if object.updated_at && appObject.exists(key) if object.updated_at && appObject.exists(key)
exists = appObject.find(key) exists = appObject.find(key)
if exists.updated_at if exists.updated_at
if exists.updated_at < object.updated_at if exists.updated_at < object.updated_at
appObject.refresh(object) listToRefresh.push object
@log 'debug', 'refrest newser', params.type, key
else else
appObject.refresh(object) listToRefresh.push object
@log 'debug', 'refrest try no updated_at', params.type, key
else else
appObject.refresh(object) listToRefresh.push object
@log 'debug', 'refrest new', params.type, key
return if _.isEmpty(listToRefresh)
appObject.refresh(listToRefresh)

View file

@ -155,6 +155,7 @@ class App.UserOrganizationAutocompletion extends App.Controller
# enter / take item # enter / take item
if e.keyCode is 13 if e.keyCode is 13
e.preventDefault() e.preventDefault()
e.stopPropagation()
userId = @$('.recipientList').find('li.is-active').data('user-id') userId = @$('.recipientList').find('li.is-active').data('user-id')
if !userId if !userId
organizationId = @$('.recipientList').find('li.is-active').data('organization-id') organizationId = @$('.recipientList').find('li.is-active').data('organization-id')

View file

@ -63,15 +63,15 @@ class App.Model extends Spine.Model
iconActivity: (user) -> iconActivity: (user) ->
'' ''
@validate: ( data = {} ) -> @validate: (data = {}) ->
# based on model attrbutes # based on model attrbutes
if App[ data['model'] ] && App[ data['model'] ].attributesGet if App[ data['model'] ] && App[ data['model'] ].attributesGet
attributes = App[ data['model'] ].attributesGet( data['screen'] ) attributes = App[ data['model'] ].attributesGet(data['screen'])
# based on custom attributes # based on custom attributes
else if data['model'].configure_attributes else if data['model'].configure_attributes
attributes = App.Model.attributesGet( data['screen'], data['model'].configure_attributes ) attributes = App.Model.attributesGet(data['screen'], data['model'].configure_attributes)
# check required_if attributes # check required_if attributes
for attributeName, attribute of attributes for attributeName, attribute of attributes
@ -186,9 +186,9 @@ class App.Model extends Spine.Model
@attributesGet: (screen = undefined, attributes = false) -> @attributesGet: (screen = undefined, attributes = false) ->
if !attributes if !attributes
attributes = clone( App[ @.className ].configure_attributes, true ) attributes = clone(App[ @.className ].configure_attributes, true)
else else
attributes = clone( attributes, true ) attributes = clone(attributes, true)
# in case if no configure_attributes exist # in case if no configure_attributes exist
return {} if !attributes return {} if !attributes
@ -198,13 +198,13 @@ class App.Model extends Spine.Model
if screen if screen
for attribute in attributes for attribute in attributes
if attribute.screen if attribute.screen
if attribute && attribute.screen && attribute.screen[ screen ] && !_.isEmpty( attribute.screen[ screen ] ) if attribute && attribute.screen && attribute.screen[ screen ] && !_.isEmpty(attribute.screen[ screen ])
for item, value of attribute.screen[ screen ] for item, value of attribute.screen[ screen ]
attribute[item] = value attribute[item] = value
attributesNew[ attribute.name ] = attribute attributesNew[ attribute.name ] = attribute
# if no screen is given or no attribute has this screen - use default attributes # if no screen is given or no attribute has this screen - use default attributes
if !screen || _.isEmpty( attributesNew ) if !screen || _.isEmpty(attributesNew)
for attribute in attributes for attribute in attributes
attributesNew[ attribute.name ] = attribute attributesNew[ attribute.name ] = attribute
@ -238,11 +238,11 @@ class App.Model extends Spine.Model
subscribeId = App[ @className ].subscribe_item(id, callback) subscribeId = App[ @className ].subscribe_item(id, callback)
# execute if object already exists # execute if object already exists
if !force && App[ @className ].exists( id ) if !force && App[ @className ].exists(id)
data = App[ @className ].find( id ) data = App[ @className ].find(id)
data = @_fillUp( data ) data = @_fillUp(data)
if callback if callback
callback( data, 'full' ) callback(data, 'full')
return subscribeId return subscribeId
# store callback and requested id # store callback and requested id
@ -270,16 +270,16 @@ class App.Model extends Spine.Model
# full / load assets # full / load assets
if data.assets if data.assets
App.Collection.loadAssets( data.assets ) App.Collection.loadAssets(data.assets)
# find / load object # find / load object
else else
App[ @className ].refresh( data ) App[ @className ].refresh(data)
# execute callbacks # execute callbacks
if @FULL_CALLBACK[ data.id ] if @FULL_CALLBACK[ data.id ]
for key, callback of @FULL_CALLBACK[ data.id ] for key, callback of @FULL_CALLBACK[ data.id ]
callback( @_fillUp( App[ @className ].find( data.id ) ) ) callback( @_fillUp( App[ @className ].find(data.id) ) )
delete @FULL_CALLBACK[ data.id ][ key ] delete @FULL_CALLBACK[ data.id ][ key ]
if _.isEmpty @FULL_CALLBACK[ data.id ] if _.isEmpty @FULL_CALLBACK[ data.id ]
delete @FULL_CALLBACK[ data.id ] delete @FULL_CALLBACK[ data.id ]
@ -297,11 +297,13 @@ class App.Model extends Spine.Model
params = params =
initFetch: true # fetch initial collection initFetch: true # fetch initial collection
@subscribeId = App.Model.subscribe( methodWhichIsCalledAtLocalOrServerSiteChange ) @subscribeId = App.Model.subscribe(methodWhichIsCalledAtLocalOrServerSiteChange)
### ###
@subscribe: (callback, param = {}) -> @subscribe: (callback, param = {}) ->
# global bind to changes
if !@SUBSCRIPTION_COLLECTION if !@SUBSCRIPTION_COLLECTION
@SUBSCRIPTION_COLLECTION = {} @SUBSCRIPTION_COLLECTION = {}
@ -320,7 +322,10 @@ class App.Model extends Spine.Model
events events
=> =>
App.Log.debug('Model', "server notify collection change #{@className}") App.Log.debug('Model', "server notify collection change #{@className}")
@fetch( {}, { clear: true } ) @fetchFull(
->
clear: true
)
'Collection::Subscribe::' + @className 'Collection::Subscribe::' + @className
) )
@ -330,13 +335,19 @@ class App.Model extends Spine.Model
# fetch init collection # fetch init collection
if param.initFetch is true if param.initFetch is true
clear = true
if param.clear is true || param.clear is false
clear = param.clear
if !@initFetchActive if !@initFetchActive
@one 'refresh', (collection) => @one 'refresh', (collection) =>
@initFetchActive = true @initFetchActive = true
callback(collection) callback(collection)
@fetch( {}, { clear: true } ) @fetchFull(
->
clear: clear
)
else else
callback( @all() ) callback(@all())
# return key # return key
key key
@ -347,7 +358,7 @@ class App.Model extends Spine.Model
console.log("Item has changed", changedItem, localOrServer) console.log("Item has changed", changedItem, localOrServer)
model = App.Model.find(1) model = App.Model.find(1)
@subscribeId = model.subscribe( methodWhichIsCalledAtLocalOrServerSiteChange ) @subscribeId = model.subscribe(methodWhichIsCalledAtLocalOrServerSiteChange)
### ###
@ -373,7 +384,7 @@ class App.Model extends Spine.Model
App.Log.debug('Model', "local change #{@className}", items) App.Log.debug('Model', "local change #{@className}", items)
for item in items for item in items
for key, callback of App[ @className ].SUBSCRIPTION_ITEM[ item.id ] for key, callback of App[ @className ].SUBSCRIPTION_ITEM[ item.id ]
item = App[ @className ]._fillUp( item ) item = App[ @className ]._fillUp(item)
callback(item, 'change') callback(item, 'change')
) )
@bind( @bind(
@ -386,7 +397,7 @@ class App.Model extends Spine.Model
App.Log.debug('Model', "local remove #{@className}", items) App.Log.debug('Model', "local remove #{@className}", items)
for item in items for item in items
for key, callback of App[ @className ].SUBSCRIPTION_ITEM[ item.id ] for key, callback of App[ @className ].SUBSCRIPTION_ITEM[ item.id ]
item = App[ @className ]._fillUp( item ) item = App[ @className ]._fillUp(item)
callback(item, 'remove') callback(item, 'remove')
) )
@ -405,7 +416,7 @@ class App.Model extends Spine.Model
# only trigger callbacks if object has changed # only trigger callbacks if object has changed
if !@changeTable[key] || @changeTable[key] isnt item.updated_at if !@changeTable[key] || @changeTable[key] isnt item.updated_at
@changeTable[key] = item.updated_at @changeTable[key] = item.updated_at
item = App[ @className ]._fillUp( item ) item = App[ @className ]._fillUp(item)
callback(item, 'refresh') callback(item, 'refresh')
) )
@ -416,14 +427,13 @@ class App.Model extends Spine.Model
(item) => (item) =>
if @SUBSCRIPTION_ITEM && @SUBSCRIPTION_ITEM[ item.id ] if @SUBSCRIPTION_ITEM && @SUBSCRIPTION_ITEM[ item.id ]
genericObject = undefined genericObject = undefined
if App[ @className ].exists( item.id ) if App[ @className ].exists(item.id)
genericObject = App[ @className ].find( item.id ) genericObject = App[ @className ].find(item.id)
App.Log.debug('Model', "server change on #{@className}.find(#{item.id}) #{item.updated_at}") App.Log.debug('Model', "server change on #{@className}.find(#{item.id}) #{item.updated_at}")
callback = => callback = =>
if !genericObject || new Date(item.updated_at) >= new Date(genericObject.updated_at) if !genericObject || new Date(item.updated_at) >= new Date(genericObject.updated_at)
App.Log.debug('Model', "request #{@className}.find(#{item.id}) from server") App.Log.debug('Model', "request #{@className}.find(#{item.id}) from server")
@full( item.id, false, true ) @full(item.id, false, true)
App.Delay.set(callback, 500, item.id, "full-#{@className}") App.Delay.set(callback, 500, item.id, "full-#{@className}")
'Item::Subscribe::' + @className 'Item::Subscribe::' + @className
@ -460,10 +470,16 @@ class App.Model extends Spine.Model
fetch full collection (with assets) fetch full collection (with assets)
App.Model.fetchFull( @callback ) App.Model.fetchFull(@callback)
App.Model.fetchFull(
@callback
clear: true
)
### ###
@fetchFull: (callback) -> @fetchFull: (callback, params = {}) ->
url = "#{@url}/?full=true" url = "#{@url}/?full=true"
App.Log.debug('Model', "fetchFull collection #{@className}", url) App.Log.debug('Model', "fetchFull collection #{@className}", url)
App.Ajax.request( App.Ajax.request(
@ -474,16 +490,20 @@ class App.Model extends Spine.Model
App.Log.debug('Model', "got fetchFull collection #{@className}", data) App.Log.debug('Model', "got fetchFull collection #{@className}", data)
# clear collection
if params.clear
App[@className].deleteAll()
# full / load assets # full / load assets
if data.assets if data.assets
App.Collection.loadAssets( data.assets ) App.Collection.loadAssets(data.assets)
# find / load object # find / load object
else else
App[ @className ].refresh( data ) App[@className].refresh(data)
# execute callbacks if callback
callback(data.stream) callback(data)
error: (xhr, statusText, error) -> error: (xhr, statusText, error) ->
App.Log.error('Model', statusText, error, url) App.Log.error('Model', statusText, error, url)
@ -494,7 +514,7 @@ class App.Model extends Spine.Model
for id, keys of @SUBSCRIPTION_ITEM for id, keys of @SUBSCRIPTION_ITEM
return false if !_.isEmpty(keys) return false if !_.isEmpty(keys)
if @SUBSCRIPTION_COLLECTION && !_.isEmpty( @SUBSCRIPTION_COLLECTION ) if @SUBSCRIPTION_COLLECTION && !_.isEmpty(@SUBSCRIPTION_COLLECTION)
return false return false
return true return true
@ -502,8 +522,8 @@ class App.Model extends Spine.Model
@_fillUp: (data, classNames = []) -> @_fillUp: (data, classNames = []) ->
# fill up via relations # fill up via relations
return data if !App[ @className ].configure_attributes return data if !App[@className].configure_attributes
for attribute in App[ @className ].configure_attributes for attribute in App[@className].configure_attributes
# lookup relations # lookup relations
if attribute.relation if attribute.relation
@ -512,19 +532,19 @@ class App.Model extends Spine.Model
if !_.contains(classNames, @className) if !_.contains(classNames, @className)
# only if relation model exists # only if relation model exists
if App[ attribute.relation ] if App[attribute.relation]
withoutId = attribute.name.substr( 0, attribute.name.length - 3 ) withoutId = attribute.name.substr(0, attribute.name.length - 3)
if attribute.name.substr( attribute.name.length - 3, attribute.name.length ) is '_id' if attribute.name.substr(attribute.name.length - 3, attribute.name.length) is '_id'
if data[attribute.name] if data[attribute.name]
# only if relation record exists in collection # only if relation record exists in collection
if App[ attribute.relation ].exists( data[attribute.name] ) if App[ attribute.relation ].exists(data[attribute.name])
item = App[ attribute.relation ].find( data[attribute.name] ) item = App[attribute.relation].find(data[attribute.name])
item = App[ attribute.relation ]._fillUp(item, classNames.concat(@className)) item = App[attribute.relation]._fillUp(item, classNames.concat(@className))
data[ withoutId ] = item data[withoutId] = item
else else
if !attribute.do_not_log if !attribute.do_not_log
console.log("ERROR, cant find #{ attribute.name } App.#{ attribute.relation }.find(#{ data[attribute.name] }) for '#{ data.constructor.className }' #{ data.displayName() }") console.log("ERROR, cant find #{attribute.name} App.#{attribute.relation}.find(#{data[attribute.name]}) for '#{data.constructor.className}' #{data.displayName()}")
data data
### ###

View file

@ -1,6 +1,6 @@
<div class="arrow js-arrow"></div> <div class="arrow js-arrow"></div>
<div class="popover-notificationsHeader js-header"> <div class="popover-notificationsHeader js-header">
<div class="popover-title"><%- @T('Notifications') %><span class='popover-notificationsCounter js-notificationsCounter'><%- @count %></span></div> <div class="popover-title"><%- @T('Notifications') %> <span class='popover-notificationsCounter js-notificationsCounter'><%- @count %></span></div>
<a class="btn btn--text btn--subtle js-mark<%- ' hidden' if !@count %>"><%- @T( 'Mark all as read' ) %></a> <a class="btn btn--text btn--subtle js-mark<%- ' hidden' if !@count %>"><%- @T( 'Mark all as read' ) %></a>
</div> </div>
<div class="popover-content js-content"> <div class="popover-content js-content">

View file

@ -378,6 +378,21 @@ class ApplicationController < ActionController::Base
def model_index_render (object, _params) def model_index_render (object, _params)
generic_objects = object.all generic_objects = object.all
if params[:full]
assets = {}
item_ids = []
generic_objects.each {|item|
item_ids.push item.id
assets = item.assets(assets)
}
render json: {
record_ids: item_ids,
assets: assets,
}, status: :ok
return
end
generic_objects_with_associations = [] generic_objects_with_associations = []
generic_objects.each {|item| generic_objects.each {|item|
generic_objects_with_associations.push item.attributes_with_associations generic_objects_with_associations.push item.attributes_with_associations

View file

@ -6,9 +6,8 @@ class CalendarsController < ApplicationController
def index def index
return if deny_if_not_role(Z_ROLENAME_ADMIN) return if deny_if_not_role(Z_ROLENAME_ADMIN)
assets = {}
# calendars # calendars
assets = {}
calendar_ids = [] calendar_ids = []
Calendar.all.order(:name, :created_at).each {|calendar| Calendar.all.order(:name, :created_at).each {|calendar|
calendar_ids.push calendar.id calendar_ids.push calendar.id

View file

@ -6,14 +6,6 @@ class SettingsController < ApplicationController
# GET /settings # GET /settings
def index def index
return if deny_if_not_role(Z_ROLENAME_ADMIN) return if deny_if_not_role(Z_ROLENAME_ADMIN)
# only serve requested items
if params[:area]
model_index_render_result( Setting.where(area: params[:area]) )
return
end
# serve all items
model_index_render(Setting, params) model_index_render(Setting, params)
end end

View file

@ -49,51 +49,29 @@ curl http://localhost/api/v1/slas.json -v -u #{login}:#{password}
def index def index
return if deny_if_not_role(Z_ROLENAME_ADMIN) return if deny_if_not_role(Z_ROLENAME_ADMIN)
assets = {} if params[:full]
# calendars # calendars
assets = {}
calendar_ids = [] calendar_ids = []
Calendar.all.order(:name, :created_at).each {|calendar| Calendar.all.each {|calendar|
calendar_ids.push calendar.id
assets = calendar.assets(assets) assets = calendar.assets(assets)
} }
# slas # slas
sla_ids = [] sla_ids = []
models = Models.all Sla.all.each {|item|
Sla.all.order(:name, :created_at).each {|sla| sla_ids.push item.id
sla_ids.push sla.id assets = item.assets(assets)
assets = sla.assets(assets)
# get assets of condition
sla.condition.each {|item, content|
attribute = item.split(/\./)
next if !attribute[1]
attribute_class = attribute[0].to_classname.constantize
reflection = attribute[1].sub(/_id$/, '')
reflection = reflection.to_sym
next if !models[attribute_class]
next if !models[attribute_class][:reflections]
next if !models[attribute_class][:reflections][reflection]
next if !models[attribute_class][:reflections][reflection].klass
attribute_ref_class = models[attribute_class][:reflections][reflection].klass
if content['value'].class == Array
content['value'].each {|item_id|
attribute_object = attribute_ref_class.find_by(id: item_id)
assets = attribute_object.assets(assets)
} }
else
attribute_object = attribute_ref_class.find_by(id: content['value'])
assets = attribute_object.assets(assets)
end
}
}
render json: { render json: {
calendar_ids: calendar_ids, record_ids: sla_ids,
sla_ids: sla_ids,
assets: assets, assets: assets,
}, status: :ok }, status: :ok
return
end
model_index_render(Sla, params)
end end
=begin =begin

View file

@ -1131,6 +1131,48 @@ get assets of object list
assets assets
end end
=begin
get assets and record_ids of selector
model = Model.find(123)
assets = model.assets_of_selector('attribute_name_of_selector', assets)
=end
def assets_of_selector(selector, assets = {})
# get assets of condition
models = Models.all
send(selector).each {|item, content|
attribute = item.split(/\./)
next if !attribute[1]
attribute_class = attribute[0].to_classname.constantize
reflection = attribute[1].sub(/_id$/, '')
#reflection = reflection.to_sym
next if !models[attribute_class]
next if !models[attribute_class][:reflections]
next if !models[attribute_class][:reflections][reflection]
next if !models[attribute_class][:reflections][reflection].klass
attribute_ref_class = models[attribute_class][:reflections][reflection].klass
if content['value'].class == Array
content['value'].each {|item_id|
attribute_object = attribute_ref_class.find_by(id: item_id)
if attribute_object
assets = attribute_object.assets(assets)
end
}
else
attribute_object = attribute_ref_class.find_by(id: content['value'])
if attribute_object
assets = attribute_object.assets(assets)
end
end
}
assets
end
private private
def attachments_buffer def attachments_buffer

View file

@ -10,6 +10,8 @@ class Calendar < ApplicationModel
after_update :sync_default, :min_one_check after_update :sync_default, :min_one_check
after_destroy :min_one_check after_destroy :min_one_check
notify_clients_support
=begin =begin
set inital default calendar set inital default calendar

View file

@ -1,6 +1,9 @@
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/ # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
class Job < ApplicationModel class Job < ApplicationModel
load 'job/assets.rb'
include Job::Assets
store :timeplan store :timeplan
store :condition store :condition
store :perform store :perform

47
app/models/job/assets.rb Normal file
View file

@ -0,0 +1,47 @@
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
class Job
module Assets
=begin
get all assets / related models for this job
job = Job.find(123)
result = job.assets(assets_if_exists)
returns
result = {
:jobs => {
123 => job_model_123,
1234 => job_model_1234,
}
}
=end
def assets (data)
if !data[ Job.to_app_model ]
data[ Job.to_app_model ] = {}
end
if !data[ User.to_app_model ]
data[ User.to_app_model ] = {}
end
if !data[ Job.to_app_model ][ id ]
data[ Job.to_app_model ][ id ] = attributes_with_associations
data = assets_of_selector('condition', data)
data = assets_of_selector('perform', data)
end
%w(created_by_id updated_by_id).each {|local_user_id|
next if !self[ local_user_id ]
next if data[ User.to_app_model ][ self[ local_user_id ] ]
user = User.lookup(id: self[ local_user_id ])
next if !user
data = user.assets(data)
}
data
end
end
end

View file

@ -1,6 +1,9 @@
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/ # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
class Overview < ApplicationModel class Overview < ApplicationModel
load 'overview/assets.rb'
include Overview::Assets
has_and_belongs_to_many :users, after_add: :cache_update, after_remove: :cache_update has_and_belongs_to_many :users, after_add: :cache_update, after_remove: :cache_update
store :condition store :condition
store :order store :order

View file

@ -0,0 +1,56 @@
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
class Overview
module Assets
=begin
get all assets / related models for this overview
overview = Overview.find(123)
result = overview.assets(assets_if_exists)
returns
result = {
:overviews => {
123 => overview_model_123,
1234 => overview_model_1234,
}
}
=end
def assets (data)
if !data[ Overview.to_app_model ]
data[ Overview.to_app_model ] = {}
end
if !data[ User.to_app_model ]
data[ User.to_app_model ] = {}
end
if !data[ Overview.to_app_model ][ id ]
data[ Overview.to_app_model ][ id ] = attributes_with_associations
if user_ids
user_ids.each {|local_user_id|
next if data[ User.to_app_model ][ local_user_id ]
user = User.lookup(id: local_user_id)
next if !user
data = user.assets(data)
}
end
data = assets_of_selector('condition', data)
end
%w(created_by_id updated_by_id).each {|local_user_id|
next if !self[ local_user_id ]
next if data[ User.to_app_model ][ self[ local_user_id ] ]
user = User.lookup(id: self[ local_user_id ])
next if !user
data = user.assets(data)
}
data
end
end
end

View file

@ -1,8 +1,14 @@
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/ # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
class Sla < ApplicationModel class Sla < ApplicationModel
load 'sla/assets.rb'
include Sla::Assets
store :condition store :condition
store :data store :data
validates :name, presence: true validates :name, presence: true
belongs_to :calendar belongs_to :calendar
notify_clients_support
end end

52
app/models/sla/assets.rb Normal file
View file

@ -0,0 +1,52 @@
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
class Sla
module Assets
=begin
get all assets / related models for this sla
sla = Sla.find(123)
result = sla.assets(assets_if_exists)
returns
result = {
:slas => {
123 => sla_model_123,
1234 => sla_model_1234,
}
}
=end
def assets (data)
if !data[ Sla.to_app_model ]
data[ Sla.to_app_model ] = {}
end
if !data[ User.to_app_model ]
data[ User.to_app_model ] = {}
end
if !data[ Sla.to_app_model ][ id ]
data[ Sla.to_app_model ][ id ] = attributes_with_associations
data = assets_of_selector('condition', data)
if calendar_id
calendar = Calendar.lookup(id: calendar_id)
if calendar
data = calendar.assets(data)
end
end
end
%w(created_by_id updated_by_id).each {|local_user_id|
next if !self[ local_user_id ]
next if data[ User.to_app_model ][ self[ local_user_id ] ]
user = User.lookup(id: self[ local_user_id ])
next if !user
data = user.assets(data)
}
data
end
end
end

View file

@ -70,6 +70,7 @@ class TestCase < Test::Unit::TestCase
rescue rescue
# just try again # just try again
sleep 10 sleep 10
log('browser_instance', { rescure: true })
browser_instance_preferences(local_browser) browser_instance_preferences(local_browser)
end end
@ -148,7 +149,7 @@ class TestCase < Test::Unit::TestCase
value: 'auto wizard is enabled', value: 'auto wizard is enabled',
timeout: 10, timeout: 10,
) )
location( url: "#{browser_url}/#getting_started/auto_wizard" ) location(url: "#{browser_url}/#getting_started/auto_wizard")
sleep 10 sleep 10
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]
@ -213,9 +214,17 @@ class TestCase < Test::Unit::TestCase
instance = params[:browser] || @browser instance = params[:browser] || @browser
instance.find_elements(css: 'a[href="#current_user"]')[0].click click(
sleep 0.1 browser: instance,
instance.find_elements(css: 'a[href="#logout"]')[0].click css: 'a[href="#current_user"]',
mute_log: true,
)
click(
browser: instance,
css: 'a[href="#logout"]',
mute_log: true,
)
(1..6).each { (1..6).each {
sleep 1 sleep 1
login = instance.find_elements(css: '#login')[0] login = instance.find_elements(css: '#login')[0]
@ -349,16 +358,26 @@ class TestCase < Test::Unit::TestCase
instance = params[:browser] || @browser instance = params[:browser] || @browser
if params[:css] if params[:css]
begin
element = instance.find_elements(css: params[:css])[0] element = instance.find_elements(css: params[:css])[0]
#instance.mouse.move_to(element) #if element
#sleep 0.2 # instance.mouse.move_to(element)
element.click
# trigger also focus on input/select and textarea fields
#if params[:css] =~ /(input|select|textarea)/
# instance.execute_script("$('#{params[:css]}').trigger('focus')")
# sleep 0.2
#end #end
sleep 0.2
element.click
rescue => e
sleep 0.5
# just try again
log('click', { rescure: true })
element = instance.find_elements(css: params[:css])[0]
#if element
# instance.mouse.move_to(element)
#end
sleep 0.2
element.click
end
else else
sleep 1 sleep 1
instance.find_elements(partial_link_text: params[:text])[0].click instance.find_elements(partial_link_text: params[:text])[0].click
@ -507,6 +526,7 @@ class TestCase < Test::Unit::TestCase
browser: browser1, browser: browser1,
css: '.some_class', css: '.some_class',
value: 'Some Value', value: 'Some Value',
deselect_all: false, # default false
) )
=end =end
@ -535,15 +555,25 @@ class TestCase < Test::Unit::TestCase
begin begin
element = instance.find_elements(css: params[:css])[0] element = instance.find_elements(css: params[:css])[0]
dropdown = Selenium::WebDriver::Support::Select.new(element) dropdown = Selenium::WebDriver::Support::Select.new(element)
if params[:deselect_all]
dropdown.deselect_all
end
dropdown.select_by(:text, params[:value]) dropdown.select_by(:text, params[:value])
puts "select - #{params.inspect}" #puts "select - #{params.inspect}"
rescue rescue
sleep 0.5
# just try again # just try again
log('select', { rescure: true })
element = instance.find_elements(css: params[:css])[0] element = instance.find_elements(css: params[:css])[0]
dropdown = Selenium::WebDriver::Support::Select.new(element) dropdown = Selenium::WebDriver::Support::Select.new(element)
dropdown.select_by(:text, params[:value]) if params[:deselect_all]
puts "select2 - #{params.inspect}" dropdown.deselect_all
end end
dropdown.select_by(:text, params[:value])
#puts "select2 - #{params.inspect}"
end
sleep 0.8
end end
=begin =begin
@ -1290,41 +1320,65 @@ wait untill text in selector disabppears
instance = params[:browser] || @browser instance = params[:browser] || @browser
data = params[:data] data = params[:data]
instance.find_elements(css: 'a[href="#manage"]')[0].click click(
sleep 0.2 browser: instance,
instance.find_elements(css: 'a[href="#manage/overviews"]')[0].click css: 'a[href="#manage"]',
sleep 0.2 mute_log: true,
instance.find_elements(css: '#content a[data-type="new"]')[0].click )
sleep 2 click(
browser: instance,
css: 'a[href="#manage/overviews"]',
mute_log: true,
)
click(
browser: instance,
css: '#content a[data-type="new"]',
mute_log: true,
)
if data[:name] if data[:name]
element = instance.find_elements(css: '.modal input[name=name]')[0] set(
element.clear browser: instance,
element.send_keys(data[:name]) css: '.modal input[name=name]',
value: data[:name],
mute_log: true,
)
end end
if data[:role] if data[:role]
element = instance.find_elements(css: '.modal select[name="role_id"]')[0] select(
dropdown = Selenium::WebDriver::Support::Select.new(element) browser: instance,
dropdown.select_by(:text, data[:role]) css: '.modal select[name="role_id"]',
value: data[:role],
mute_log: true,
)
end end
if data[:selector] if data[:selector]
data[:selector].each {|key, value| data[:selector].each {|key, value|
element = instance.find_elements(css: '.modal .ticket_selector .js-attributeSelector select')[0] select(
dropdown = Selenium::WebDriver::Support::Select.new(element) browser: instance,
dropdown.select_by(:text, key) css: '.modal .ticket_selector .js-attributeSelector select',
value: key,
mute_log: true,
)
sleep 0.5 sleep 0.5
element = instance.find_elements(css: '.modal .ticket_selector .js-value select')[0] select(
dropdown = Selenium::WebDriver::Support::Select.new(element) browser: instance,
dropdown.deselect_all css: '.modal .ticket_selector .js-value select',
dropdown.select_by(:text, value) value: value,
deselect_all: true,
mute_log: true,
)
} }
end end
if data['order::direction'] if data['order::direction']
element = instance.find_elements(css: '.modal select[name="order::direction"]')[0] select(
dropdown = Selenium::WebDriver::Support::Select.new(element) browser: instance,
dropdown.select_by(:text, data['order::direction']) css: '.modal select[name="order::direction"]',
value: data['order::direction'],
mute_log: true,
)
end end
instance.find_elements(css: '.modal button.js-submit')[0].click instance.find_elements(css: '.modal button.js-submit')[0].click
@ -1368,44 +1422,63 @@ wait untill text in selector disabppears
instance = params[:browser] || @browser instance = params[:browser] || @browser
data = params[:data] data = params[:data]
instance.find_elements(css: 'a[href="#manage"]')[0].click click(
sleep 0.2 browser: instance,
instance.find_elements(css: 'a[href="#manage/overviews"]')[0].click css: 'a[href="#manage"]',
sleep 1 mute_log: true,
#instance.find_elements(css: '#content a[data-type="new"]')[0].click )
#sleep 2 click(
browser: instance,
css: 'a[href="#manage/overviews"]',
mute_log: true,
)
instance.execute_script("$(\"#content td:contains('#{data[:name]}')\").first().click()") instance.execute_script("$(\"#content td:contains('#{data[:name]}')\").first().click()")
sleep 2 sleep 2
if data[:name] if data[:name]
element = instance.find_elements(css: '.modal input[name=name]')[0] set(
element.clear browser: instance,
element.send_keys(data[:name]) css: '.modal input[name=name]',
value: data[:name],
mute_log: true,
)
end end
if data[:role] if data[:role]
element = instance.find_elements(css: '.modal select[name="role_id"]')[0] select(
dropdown = Selenium::WebDriver::Support::Select.new(element) browser: instance,
dropdown.select_by(:text, data[:role]) css: '.modal select[name="role_id"]',
value: data[:role],
mute_log: true,
)
end end
if data[:selector] if data[:selector]
data[:selector].each {|key, value| data[:selector].each {|key, value|
element = instance.find_elements(css: '.modal .ticket_selector .js-attributeSelector select')[0] select(
dropdown = Selenium::WebDriver::Support::Select.new(element) browser: instance,
dropdown.select_by(:text, key) css: '.modal .ticket_selector .js-attributeSelector select',
instance.execute_script("$('#content .modal .ticket_selector .js-attributeSelector select').first().trigger('change')") value: key,
element = instance.find_elements(css: '.modal .ticket_selector .js-value select')[0] mute_log: true,
dropdown = Selenium::WebDriver::Support::Select.new(element) )
dropdown.deselect_all sleep 0.5
dropdown.select_by(:text, value) select(
browser: instance,
css: '.modal .ticket_selector .js-value select',
value: value,
deselect_all: true,
mute_log: true,
)
} }
end end
if data['order::direction'] if data['order::direction']
element = instance.find_elements(css: '.modal select[name="order::direction"]')[0] select(
dropdown = Selenium::WebDriver::Support::Select.new(element) browser: instance,
dropdown.select_by(:text, data['order::direction']) css: '.modal select[name="order::direction"]',
value: data['order::direction'],
mute_log: true,
)
end end
instance.find_elements(css: '.modal button.js-submit')[0].click instance.find_elements(css: '.modal button.js-submit')[0].click
@ -1456,8 +1529,17 @@ wait untill text in selector disabppears
instance = params[:browser] || @browser instance = params[:browser] || @browser
data = params[:data] data = params[:data]
instance.find_elements(css: 'a[href="#new"]')[0].click click(
instance.find_elements(css: 'a[href="#ticket/create"]')[0].click browser: instance,
css: 'a[href="#new"]',
mute_log: true,
)
click(
browser: instance,
css: 'a[href="#ticket/create"]',
mute_log: true,
)
element = instance.find_elements(css: '.active .newTicket')[0] element = instance.find_elements(css: '.active .newTicket')[0]
if !element if !element
screenshot(browser: instance, comment: 'ticket_create_failed') screenshot(browser: instance, comment: 'ticket_create_failed')
@ -1481,31 +1563,40 @@ wait untill text in selector disabppears
# check count of agents, should be only 1 / - selection on init screen # check count of agents, should be only 1 / - selection on init screen
count = instance.find_elements(css: '.active .newTicket select[name="owner_id"] option').count count = instance.find_elements(css: '.active .newTicket select[name="owner_id"] option').count
assert_equal(1, count, 'check if owner selection is empty per default') assert_equal(1, count, 'check if owner selection is empty per default')
select(
element = instance.find_elements(css: '.active .newTicket select[name="group_id"]')[0] browser: instance,
dropdown = Selenium::WebDriver::Support::Select.new(element) css: '.active .newTicket select[name="group_id"]',
dropdown.select_by(:text, data[:group]) value: data[:group],
mute_log: true,
)
sleep 0.2 sleep 0.2
end end
end end
if data[:priority] if data[:priority]
element = instance.find_elements(css: '.active .newTicket select[name="priority_id"]')[0] select(
dropdown = Selenium::WebDriver::Support::Select.new(element) browser: instance,
dropdown.select_by(:text, data[:priority]) css: '.active .newTicket select[name="priority_id"]',
sleep 0.2 value: data[:priority],
mute_log: true,
)
end end
if data[:title] if data[:title]
element = instance.find_elements(css: '.active .newTicket input[name="title"]')[0] set(
element.clear browser: instance,
element.send_keys(data[:title]) css: '.active .newTicket input[name="title"]',
sleep 0.2 value: data[:title],
clear: true,
mute_log: true,
)
end end
if data[:body] if data[:body]
#instance.execute_script('$(".active .newTicket div[data-name=body]").focus()') set(
sleep 0.5 browser: instance,
element = instance.find_elements(css: '.active .newTicket div[data-name=body]')[0] css: '.active .newTicket div[data-name=body]',
element.clear value: data[:body],
element.send_keys(data[:body]) clear: true,
mute_log: true,
)
# it's not working stable via selenium, use js # it's not working stable via selenium, use js
value = instance.find_elements(css: '.content .newTicket div[data-name=body]')[0].text value = instance.find_elements(css: '.content .newTicket div[data-name=body]')[0].text
@ -1546,9 +1637,14 @@ wait untill text in selector disabppears
assert(true, 'ticket created without submit') assert(true, 'ticket created without submit')
return return
end end
sleep 0.8 sleep 0.5
#instance.execute_script('$(".content.active .newTicket form").submit();') #instance.execute_script('$(".content.active .newTicket form").submit();')
instance.find_elements(css: '.active .newTicket button.js-submit')[0].click click(
browser: instance,
css: '.active .newTicket button.js-submit',
mute_log: true,
)
sleep 1 sleep 1
(1..10).each { (1..10).each {
if instance.current_url =~ /#{Regexp.quote('#ticket/zoom/')}/ if instance.current_url =~ /#{Regexp.quote('#ticket/zoom/')}/
@ -1675,11 +1771,13 @@ wait untill text in selector disabppears
end end
if data[:body] if data[:body]
#instance.execute_script('$(".content.active div[data-name=body]").focus()') set(
sleep 0.5 browser: instance,
element = instance.find_elements(css: '.content.active div[data-name=body]')[0] css: '.content.active div[data-name=body]',
element.clear value: data[:body],
element.send_keys(data[:body]) no_click: true,
mute_log: true,
)
# it's not working stable via selenium, use js # it's not working stable via selenium, use js
value = instance.find_elements(css: '.content.active div[data-name=body]')[0].text value = instance.find_elements(css: '.content.active div[data-name=body]')[0].text
@ -1702,26 +1800,32 @@ wait untill text in selector disabppears
assert_equal(3, count, 'check if owner selection is - selection + master + agent per default') assert_equal(3, count, 'check if owner selection is - selection + master + agent per default')
else else
select(
element = instance.find_elements(css: '.active .sidebar select[name="group_id"]')[0] browser: instance,
dropdown = Selenium::WebDriver::Support::Select.new(element) css: '.active .sidebar select[name="group_id"]',
dropdown.select_by(:text, data[:group]) value: data[:group],
mute_log: true,
)
sleep 0.2 sleep 0.2
end end
end end
if data[:priority] if data[:priority]
element = instance.find_elements(css: '.active .sidebar select[name="priority_id"]')[0] select(
dropdown = Selenium::WebDriver::Support::Select.new(element) browser: instance,
dropdown.select_by(:text, data[:priority]) css: '.active .sidebar select[name="priority_id"]',
sleep 0.2 value: data[:priority],
mute_log: true,
)
end end
if data[:state] if data[:state]
element = instance.find_elements(css: '.active .sidebar select[name="state_id"]')[0] select(
dropdown = Selenium::WebDriver::Support::Select.new(element) browser: instance,
dropdown.select_by(:text, data[:state]) css: '.active .sidebar select[name="state_id"]',
sleep 0.2 value: data[:state],
mute_log: true,
)
end end
if data[:state] || data[:group] || data[:body] if data[:state] || data[:group] || data[:body]
@ -2080,11 +2184,22 @@ wait untill text in selector disabppears
instance = params[:browser] || @browser instance = params[:browser] || @browser
data = params[:data] data = params[:data]
instance.find_elements(css: 'a[href="#manage"]')[0].click click(
sleep 1 browser: instance,
instance.find_elements(css: 'a[href="#manage/users"]')[0].click css: 'a[href="#manage"]',
sleep 2 mute_log: true,
instance.find_elements(css: 'a[data-type="new"]')[0].click )
click(
browser: instance,
css: 'a[href="#manage/users"]',
mute_log: true,
)
click(
browser: instance,
css: 'a[data-type="new"]',
mute_log: true,
)
sleep 2 sleep 2
element = instance.find_elements(css: '.modal input[name=firstname]')[0] element = instance.find_elements(css: '.modal input[name=firstname]')[0]
element.clear element.clear
@ -2140,11 +2255,22 @@ wait untill text in selector disabppears
instance = params[:browser] || @browser instance = params[:browser] || @browser
data = params[:data] data = params[:data]
instance.find_elements(css: 'a[href="#manage"]')[0].click click(
sleep 1 browser: instance,
instance.find_elements(css: 'a[href="#manage/slas"]')[0].click css: 'a[href="#manage"]',
sleep 2 mute_log: true,
instance.find_elements(css: 'a.js-new')[0].click )
click(
browser: instance,
css: 'a[href="#manage/slas"]',
mute_log: true,
)
click(
browser: instance,
css: 'a.js-new',
mute_log: true,
)
sleep 2 sleep 2
element = instance.find_elements(css: '.modal input[name=name]')[0] element = instance.find_elements(css: '.modal input[name=name]')[0]
element.clear element.clear
@ -2187,11 +2313,22 @@ wait untill text in selector disabppears
instance = params[:browser] || @browser instance = params[:browser] || @browser
data = params[:data] data = params[:data]
instance.find_elements(css: 'a[href="#manage"]')[0].click click(
sleep 1 browser: instance,
instance.find_elements(css: 'a[href="#manage/text_modules"]')[0].click css: 'a[href="#manage"]',
sleep 2 mute_log: true,
instance.find_elements(css: 'a[data-type="new"]')[0].click )
click(
browser: instance,
css: 'a[href="#manage/text_modules"]',
mute_log: true,
)
click(
browser: instance,
css: 'a[data-type="new"]',
mute_log: true,
)
sleep 2 sleep 2
element = instance.find_elements(css: '.modal input[name=name]')[0] element = instance.find_elements(css: '.modal input[name=name]')[0]
element.clear element.clear
@ -2236,13 +2373,28 @@ wait untill text in selector disabppears
instance = params[:browser] || @browser instance = params[:browser] || @browser
data = params[:data] data = params[:data]
instance.find_elements(css: 'a[href="#manage"]')[0].click click(
sleep 1 browser: instance,
instance.find_elements(css: 'a[href="#channels/email"]')[0].click css: 'a[href="#manage"]',
sleep 1 mute_log: true,
instance.find_elements(css: 'a[href="#c-signature"]')[0].click )
sleep 8 click(
instance.find_elements(css: '#content #c-signature a[data-type="new"]')[0].click browser: instance,
css: 'a[href="#channels/email"]',
mute_log: true,
)
click(
browser: instance,
css: 'a[href="#c-signature"]',
mute_log: true,
)
sleep 4
click(
browser: instance,
css: '#content #c-signature a[data-type="new"]',
mute_log: true,
)
sleep 2 sleep 2
element = instance.find_elements(css: '.modal input[name=name]')[0] element = instance.find_elements(css: '.modal input[name=name]')[0]
element.clear element.clear
@ -2287,11 +2439,22 @@ wait untill text in selector disabppears
instance = params[:browser] || @browser instance = params[:browser] || @browser
data = params[:data] data = params[:data]
instance.find_elements(css: 'a[href="#manage"]')[0].click click(
sleep 0.5 browser: instance,
instance.find_elements(css: 'a[href="#manage/groups"]')[0].click css: 'a[href="#manage"]',
sleep 2 mute_log: true,
instance.find_elements(css: 'a[data-type="new"]')[0].click )
click(
browser: instance,
css: 'a[href="#manage/groups"]',
mute_log: true,
)
click(
browser: instance,
css: 'a[data-type="new"]',
mute_log: true,
)
sleep 2 sleep 2
element = instance.find_elements(css: '.modal input[name=name]')[0] element = instance.find_elements(css: '.modal input[name=name]')[0]
element.clear element.clear

View file

@ -4,7 +4,7 @@ require 'test_helper'
class AssetsTest < ActiveSupport::TestCase class AssetsTest < ActiveSupport::TestCase
test 'user' do test 'user' do
roles = Role.where( name: %w(Agent Admin) ) roles = Role.where(name: %w(Agent Admin))
groups = Group.all groups = Group.all
org = Organization.create_or_update( org = Organization.create_or_update(
name: 'some user org', name: 'some user org',
@ -278,4 +278,263 @@ class AssetsTest < ActiveSupport::TestCase
#puts "ERROR: difference \n1: #{o1.inspect}\n2: #{o2.inspect}\ndiff: #{(o1.to_a - o2.to_a).inspect}" #puts "ERROR: difference \n1: #{o1.inspect}\n2: #{o2.inspect}\ndiff: #{(o1.to_a - o2.to_a).inspect}"
false false
end end
test 'overview' do
UserInfo.current_user_id = 1
roles = Role.where(name: %w(Customer))
user1 = User.create_or_update(
login: 'assets_overview1@example.org',
firstname: 'assets_overview1',
lastname: 'assets_overview1',
email: 'assets_overview1@example.org',
password: 'some_pass',
active: true,
roles: roles,
)
user2 = User.create_or_update(
login: 'assets_overview2@example.org',
firstname: 'assets_overview2',
lastname: 'assets_overview2',
email: 'assets_overview2@example.org',
password: 'some_pass',
active: true,
roles: roles,
)
user3 = User.create_or_update(
login: 'assets_overview3@example.org',
firstname: 'assets_overview3',
lastname: 'assets_overview3',
email: 'assets_overview3@example.org',
password: 'some_pass',
active: true,
roles: roles,
)
user4 = User.create_or_update(
login: 'assets_overview4@example.org',
firstname: 'assets_overview4',
lastname: 'assets_overview4',
email: 'assets_overview4@example.org',
password: 'some_pass',
active: true,
roles: roles,
)
user5 = User.create_or_update(
login: 'assets_overview5@example.org',
firstname: 'assets_overview5',
lastname: 'assets_overview5',
email: 'assets_overview5@example.org',
password: 'some_pass',
active: true,
roles: roles,
)
ticket_state1 = Ticket::State.find_by(name: 'new')
ticket_state2 = Ticket::State.find_by(name: 'open')
overview_role = Role.find_by(name: 'Agent')
overview = Overview.create_or_update(
name: 'my asset test',
link: 'my_asset_test',
prio: 1000,
role_id: overview_role.id,
user_ids: [ user4.id, user5.id ],
condition: {
'ticket.state_id' => {
operator: 'is',
value: [ ticket_state1.id, ticket_state2.id ],
},
'ticket.owner_id' => {
operator: 'is',
pre_condition: 'specific',
value: user1.id,
value_completion: 'John Smith <john.smith@example.com>'
},
},
order: {
by: 'created_at',
direction: 'ASC',
},
view: {
d: %w(title customer group created_at),
s: %w(title customer group created_at),
m: %w(number title customer group created_at),
view_mode_default: 's',
},
)
assets = overview.assets({})
assert(assets[:User][user1.id], 'check assets')
assert_not(assets[:User][user2.id], 'check assets')
assert_not(assets[:User][user3.id], 'check assets')
assert(assets[:User][user4.id], 'check assets')
assert(assets[:User][user5.id], 'check assets')
assert(assets[:TicketState][ticket_state1.id], 'check assets')
assert(assets[:TicketState][ticket_state2.id], 'check assets')
overview = Overview.create_or_update(
name: 'my asset test',
link: 'my_asset_test',
prio: 1000,
role_id: overview_role.id,
user_ids: [ user4.id ],
condition: {
'ticket.state_id' => {
operator: 'is',
value: ticket_state1.id,
},
'ticket.owner_id' => {
operator: 'is',
pre_condition: 'specific',
value: [user1.id, user2.id],
},
},
order: {
by: 'created_at',
direction: 'ASC',
},
view: {
d: %w(title customer group created_at),
s: %w(title customer group created_at),
m: %w(number title customer group created_at),
view_mode_default: 's',
},
)
assets = overview.assets({})
assert(assets[:User][user1.id], 'check assets')
assert(assets[:User][user2.id], 'check assets')
assert_not(assets[:User][user3.id], 'check assets')
assert(assets[:User][user4.id], 'check assets')
assert_not(assets[:User][user5.id], 'check assets')
assert(assets[:TicketState][ticket_state1.id], 'check assets')
assert_not(assets[:TicketState][ticket_state2.id], 'check assets')
end
test 'sla' do
UserInfo.current_user_id = 1
roles = Role.where(name: %w(Customer))
user1 = User.create_or_update(
login: 'assets_sla1@example.org',
firstname: 'assets_sla1',
lastname: 'assets_sla1',
email: 'assets_sla1@example.org',
password: 'some_pass',
active: true,
roles: roles,
)
user2 = User.create_or_update(
login: 'assets_sla2@example.org',
firstname: 'assets_sla2',
lastname: 'assets_sla2',
email: 'assets_sla2@example.org',
password: 'some_pass',
active: true,
roles: roles,
)
calendar1 = Calendar.first
ticket_state1 = Ticket::State.find_by(name: 'new')
ticket_state2 = Ticket::State.find_by(name: 'open')
sla = Sla.create_or_update(
name: 'my asset test',
calendar_id: calendar1.id,
condition: {
'ticket.state_id' => {
operator: 'is',
value: [ ticket_state1.id, ticket_state2.id ],
},
'ticket.owner_id' => {
operator: 'is',
pre_condition: 'specific',
value: user1.id,
value_completion: 'John Smith <john.smith@example.com>'
},
},
)
assets = sla.assets({})
assert(assets[:User][user1.id], 'check assets')
assert_not(assets[:User][user2.id], 'check assets')
assert(assets[:TicketState][ticket_state1.id], 'check assets')
assert(assets[:TicketState][ticket_state2.id], 'check assets')
assert(assets[:Calendar][calendar1.id], 'check assets')
end
test 'job' do
UserInfo.current_user_id = 1
roles = Role.where(name: %w(Customer))
user1 = User.create_or_update(
login: 'assets_job1@example.org',
firstname: 'assets_job1',
lastname: 'assets_job1',
email: 'assets_job1@example.org',
password: 'some_pass',
active: true,
roles: roles,
)
user2 = User.create_or_update(
login: 'assets_job2@example.org',
firstname: 'assets_job2',
lastname: 'assets_job2',
email: 'assets_job2@example.org',
password: 'some_pass',
active: true,
roles: roles,
)
user3 = User.create_or_update(
login: 'assets_job3@example.org',
firstname: 'assets_job3',
lastname: 'assets_job3',
email: 'assets_job3@example.org',
password: 'some_pass',
active: true,
roles: roles,
)
ticket_state1 = Ticket::State.find_by(name: 'new')
ticket_state2 = Ticket::State.find_by(name: 'open')
ticket_priority2 = Ticket::Priority.find_by(name: '2 normal')
job = Job.create_or_update(
name: 'my job',
timeplan: {
mon: true,
},
condition: {
'ticket.state_id' => {
operator: 'is',
value: [ ticket_state1.id, ticket_state2.id ],
},
'ticket.owner_id' => {
operator: 'is',
pre_condition: 'specific',
value: user1.id,
value_completion: 'John Smith <john.smith@example.com>'
},
},
perform: {
'ticket.priority_id' => {
value: ticket_priority2.id,
},
'ticket.owner_id' => {
pre_condition: 'specific',
value: user2.id,
value_completion: 'metest123@znuny.com <metest123@znuny.com>'
},
},
disable_notification: true,
)
assets = job.assets({})
assert(assets[:User][user1.id], 'check assets')
assert(assets[:User][user2.id], 'check assets')
assert_not(assets[:User][user3.id], 'check assets')
assert(assets[:TicketState][ticket_state1.id], 'check assets')
assert(assets[:TicketState][ticket_state2.id], 'check assets')
assert(assets[:TicketPriority][ticket_priority2.id], 'check assets')
end
end end