Improved fetching activity stream, online notifications and recent viewed items. Improved REST API with full and expaned attributes.

This commit is contained in:
Martin Edenhofer 2018-03-20 13:16:17 +01:00
parent 2df0ddc248
commit 70847f2b41
26 changed files with 585 additions and 308 deletions

View file

@ -1171,7 +1171,7 @@ class App.CollectionController extends App.Controller
class App.ObserverController extends App.Controller class App.ObserverController extends App.Controller
model: 'Ticket' model: 'Ticket'
template: 'ticket_zoom/title' template: 'tba'
globalRerender: true globalRerender: true
### ###
@ -1251,3 +1251,24 @@ class App.ObserverController extends App.Controller
#console.trace() #console.trace()
@log 'debug', 'release', @object_id, @model, @subscribeId @log 'debug', 'release', @object_id, @model, @subscribeId
App[@model].unsubscribe(@subscribeId) App[@model].unsubscribe(@subscribeId)
class App.ObserverActionRow extends App.ObserverController
constructor: ->
super
render: (object) =>
return if _.isEmpty(object)
actions = @actions()
@html App.view('generic/actions')(
items: actions
type: @type
)
for item in actions
do (item) =>
@$("[data-type=\"#{item.name}\"]").on(
'click'
(e) ->
e.preventDefault()
item.callback(object)
)

View file

@ -27,7 +27,7 @@ class App.DashboardActivityStream extends App.CollectionController
@ajax( @ajax(
id: 'dashoard_activity_stream' id: 'dashoard_activity_stream'
type: 'GET' type: 'GET'
url: "#{@apiPath}/activity_stream" url: "#{@apiPath}/activity_stream?full=true"
data: data:
limit: @limit || 8 limit: @limit || 8
processData: true processData: true
@ -37,8 +37,9 @@ class App.DashboardActivityStream extends App.CollectionController
load: (data) => load: (data) =>
App.SessionStorage.set('activity_stream', data) App.SessionStorage.set('activity_stream', data)
@items = data.activity_stream App.ActivityStream.refresh([], clear: true)
App.Collection.loadAssets(data.assets) App.Collection.loadAssets(data.assets)
@items = App.ActivityStream.search(sortBy: 'created_at', order: 'DESC')
@collectionSync(@items) @collectionSync(@items)
itemGet: (key) => itemGet: (key) =>
@ -49,7 +50,7 @@ class App.DashboardActivityStream extends App.CollectionController
# nothing # nothing
itemsAll: => itemsAll: =>
@items @items || []
onRenderEnd: => onRenderEnd: =>
return if _.isEmpty(@items) return if _.isEmpty(@items)

View file

@ -448,10 +448,9 @@ class App.Navigation extends App.ControllerWidgetPermanent
@Config.set('NavBarRight', NavBarRight) @Config.set('NavBarRight', NavBarRight)
fetchRecentView: => fetchRecentView: =>
load = (data) => load = =>
App.RecentView.refresh(data.stream, clear: true)
@renderPersonal() @renderPersonal()
App.RecentView.fetchFull(load) App.RecentView.fetchFull(load, clear: true)
toggleNotifications: (e) -> toggleNotifications: (e) ->
e.stopPropagation() e.stopPropagation()

View file

@ -73,21 +73,18 @@ class App.OrganizationProfile extends App.Controller
currentPosition: => currentPosition: =>
@$('.profile').scrollTop() @$('.profile').scrollTop()
class ActionRow extends App.ObserverController class ActionRow extends App.ObserverActionRow
model: 'Organization' model: 'Organization'
observe: observe:
member_ids: true member_ids: true
render: (organization) => showHistory: (organization) =>
# start action controller
showHistory = =>
new App.OrganizationHistory( new App.OrganizationHistory(
organization_id: organization.id organization_id: organization.id
container: @el.closest('.content') container: @el.closest('.content')
) )
editOrganization = => editOrganization: (organization) =>
new App.ControllerGenericEdit( new App.ControllerGenericEdit(
id: organization.id id: organization.id
genericObject: 'Organization' genericObject: 'Organization'
@ -99,24 +96,20 @@ class ActionRow extends App.ObserverController
container: @el.closest('.content') container: @el.closest('.content')
) )
actions: =>
actions = [ actions = [
{ {
name: 'edit' name: 'edit'
title: 'Edit' title: 'Edit'
callback: editOrganization callback: @editOrganization
} }
{ {
name: 'history' name: 'history'
title: 'History' title: 'History'
callback: showHistory callback: @showHistory
} }
] ]
new App.ActionRow(
el: @el
items: actions
)
class Object extends App.ObserverController class Object extends App.ObserverController
model: 'Organization' model: 'Organization'
observeNot: observeNot:

View file

@ -574,11 +574,12 @@ class App.TicketOverview extends App.Controller
@activeFocus = 'nav' @activeFocus = 'nav'
) )
@bind 'overview:fetch', => @bind('overview:fetch', =>
return if !@view return if !@view
update = => update = =>
App.OverviewListCollection.fetch(@view) App.OverviewListCollection.fetch(@view)
@delay(update, 2800, 'overview:fetch') @delay(update, 2800, 'overview:fetch')
)
renderBatchOverlay: (elLocal) => renderBatchOverlay: (elLocal) =>
if elLocal if elLocal

View file

@ -80,21 +80,18 @@ class App.UserProfile extends App.Controller
currentPosition: => currentPosition: =>
@$('.profile').scrollTop() @$('.profile').scrollTop()
class ActionRow extends App.ObserverController class ActionRow extends App.ObserverActionRow
model: 'User' model: 'User'
observe: observe:
organization_id: true organization_id: true
render: (user) => showHistory: (user) =>
# start action controller
showHistory = =>
new App.UserHistory( new App.UserHistory(
user_id: user.id user_id: user.id
container: @el.closest('.content') container: @el.closest('.content')
) )
editUser = => editUser: (user) =>
new App.ControllerGenericEdit( new App.ControllerGenericEdit(
id: user.id id: user.id
genericObject: 'User' genericObject: 'User'
@ -106,32 +103,28 @@ class ActionRow extends App.ObserverController
container: @el.closest('.content') container: @el.closest('.content')
) )
newTicket = => newTicket: (user) =>
@navigate("ticket/create/customer/#{user.id}") @navigate("ticket/create/customer/#{user.id}")
actions = [ actions: =>
[
{ {
name: 'edit' name: 'edit'
title: 'Edit' title: 'Edit'
callback: editUser callback: @editUser
} }
{ {
name: 'history' name: 'history'
title: 'History' title: 'History'
callback: showHistory callback: @showHistory
} }
{ {
name: 'ticket' name: 'ticket'
title: 'New Ticket' title: 'New Ticket'
callback: newTicket callback: @newTicket
} }
] ]
new App.ActionRow(
el: @el
items: actions
)
class Object extends App.ObserverController class Object extends App.ObserverController
model: 'User' model: 'User'
observeNot: observeNot:

View file

@ -20,16 +20,17 @@ class App.OnlineNotificationWidget extends App.Controller
super super
# at runtime if a online notifiction has changed # at runtime if a online notifiction has changed
@bind 'OnlineNotification::changed', => @bind('OnlineNotification::changed', =>
@delay( @delay(
=> @fetch() => @fetch()
2200 2200
'online-notification-changed' 'online-notification-changed'
) )
)
# after new websocket connection has been established # after new websocket connection has been established
@ignoreInitLogin = false @ignoreInitLogin = false
@bind 'ws:login', => @bind('ws:login', =>
if @ignoreInitLogin if @ignoreInitLogin
@delay( @delay(
=> @fetch() => @fetch()
@ -37,15 +38,17 @@ class App.OnlineNotificationWidget extends App.Controller
'online-notification-changed' 'online-notification-changed'
) )
@ignoreInitLogin = true @ignoreInitLogin = true
)
# rebuild widget on auth # rebuild widget on auth
@bind 'auth', (user) => @bind('auth', (user) =>
if !user if !user
@counterUpdate(0) @counterUpdate(0)
return return
if !@access() if !@access()
@counterUpdate(0) @counterUpdate(0)
return return
)
$(window).on 'click.notifications', @hide $(window).on 'click.notifications', @hide
@ -150,10 +153,9 @@ class App.OnlineNotificationWidget extends App.Controller
) )
fetch: => fetch: =>
load = (data) => load = =>
@fetchedData = true @fetchedData = true
App.OnlineNotification.refresh(data.stream, clear: true) App.OnlineNotification.fetchFull(load, clear: true)
App.OnlineNotification.fetchFull(load)
toggle: => toggle: =>
if @shown if @shown

View file

@ -273,11 +273,11 @@ set new attributes of model (remove already available attributes)
# subscribe and reload data / fetch new data if triggered # subscribe and reload data / fetch new data if triggered
subscribeId = undefined subscribeId = undefined
if bind if bind
subscribeId = App[ @className ].subscribeItem(id, callback) subscribeId = App[@className].subscribeItem(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')
@ -312,17 +312,18 @@ set new attributes of model (remove already available attributes)
# 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 ]
error: (xhr, statusText, error) -> error: (xhr, statusText, error) =>
@FULL_FETCH[ data.id ] = false
App.Log.error('Model', statusText, error, url) App.Log.error('Model', statusText, error, url)
) )
subscribeId subscribeId
@ -455,8 +456,8 @@ set new attributes of model (remove already available attributes)
items = [items] items = [items]
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 ]
callback(App[ @className ]._fillUp(item), 'change') callback(App[@className]._fillUp(item), 'change')
) )
@bind( @bind(
'destroy' 'destroy'
@ -467,8 +468,8 @@ set new attributes of model (remove already available attributes)
items = [items] items = [items]
App.Log.debug('Model', "local destroy #{@className}", items) App.Log.debug('Model', "local destroy #{@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 ]
callback(App[ @className ]._fillUp(item), 'destroy') callback(App[@className]._fillUp(item), 'destroy')
) )
@changeTable = {} @changeTable = {}
@ -481,7 +482,7 @@ set new attributes of model (remove already available attributes)
items = [items] items = [items]
App.Log.debug('Model', "local refresh #{@className}", items) App.Log.debug('Model', "local refresh #{@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 ]
# only trigger callbacks if object has changed # only trigger callbacks if object has changed
if !@changeTable[key] || @changeTable[key] < item.updated_at if !@changeTable[key] || @changeTable[key] < item.updated_at
@ -498,8 +499,8 @@ set new attributes of model (remove already available attributes)
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 = =>
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)
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)
@ -512,8 +513,8 @@ set new attributes of model (remove already available attributes)
events events
(item) => (item) =>
return if !@SUBSCRIPTION_ITEM || !@SUBSCRIPTION_ITEM[ item.id ] return if !@SUBSCRIPTION_ITEM || !@SUBSCRIPTION_ITEM[ item.id ]
return if !App[ @className ].exists(item.id) return if !App[@className].exists(item.id)
genericObject = App[ @className ].find(item.id) genericObject = App[@className].find(item.id)
App.Log.debug('Model', "server delete on #{@className}.find(#{item.id}) #{item.updated_at}") App.Log.debug('Model', "server delete on #{@className}.find(#{item.id}) #{item.updated_at}")
callback = -> callback = ->
genericObject.trigger('destroy', genericObject) genericObject.trigger('destroy', genericObject)
@ -565,16 +566,30 @@ set new attributes of model (remove already available attributes)
@fetchFull: (callback, params = {}) -> @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)
# request already active, queue callback
queueManagerName = "#{@className}::fetchFull"
if params.force is false && App[@className].count() isnt 0 if params.force is false && App[@className].count() isnt 0
if callback if callback
callback(App[@className].all()) localCallback = =>
callback(App[@className].all(), 'full')
App.QueueManager.add(queueManagerName, localCallback)
App.QueueManager.run(queueManagerName)
return return
if callback
localCallback = =>
callback(App[@className].all())
App.QueueManager.add(queueManagerName, localCallback)
return if @fetchFullActive is true
@fetchFullActive = true
App.Ajax.request( App.Ajax.request(
type: 'GET' type: 'GET'
url: url url: url
processData: true, processData: true,
success: (data, status, xhr) => success: (data, status, xhr) =>
@fetchFullActive = false
App.Log.debug('Model', "got fetchFull collection #{@className}", data) App.Log.debug('Model', "got fetchFull collection #{@className}", data)
@ -594,10 +609,10 @@ set new attributes of model (remove already available attributes)
else else
App[@className].refresh(data) App[@className].refresh(data)
if callback App.QueueManager.run(queueManagerName)
callback(data)
error: (xhr, statusText, error) -> error: (xhr, statusText, error) =>
@fetchFullActive = false
App.Log.error('Model', statusText, error, url) App.Log.error('Model', statusText, error, url)
) )

View file

@ -0,0 +1,4 @@
class App.ActivityStream extends App.Model
@configure 'ActivityStream', 'name'
@extend Spine.Model.Ajax
@url: @apiPath + '/activity_steams'

View file

@ -5,10 +5,36 @@ class ActivityStreamController < ApplicationController
# GET /api/v1/activity_stream # GET /api/v1/activity_stream
def show def show
activity_stream = current_user.activity_stream(params[:limit], true) activity_stream = current_user.activity_stream(params[:limit])
# return result if response_expand?
render json: activity_stream list = []
activity_stream.each do |item|
list.push item.attributes_with_association_names
end
render json: list, status: :ok
return
end
if response_full?
assets = {}
item_ids = []
activity_stream.each do |item|
item_ids.push item.id
assets = item.assets(assets)
end
render json: {
record_ids: item_ids,
assets: assets,
}, status: :ok
return
end
all = []
activity_stream.each do |item|
all.push item.attributes_with_association_ids
end
render json: all, status: :ok
end end
end end

View file

@ -47,13 +47,36 @@ curl http://localhost/api/v1/online_notifications.json -v -u #{login}:#{password
=end =end
def index def index
if response_full? online_notifications = OnlineNotification.list(current_user, 200)
render json: OnlineNotification.list_full(current_user, 200)
if response_expand?
list = []
online_notifications.each do |item|
list.push item.attributes_with_association_names
end
render json: list, status: :ok
return return
end end
notifications = OnlineNotification.list(current_user, 200) if response_full?
model_index_render_result(notifications) assets = {}
item_ids = []
online_notifications.each do |item|
item_ids.push item.id
assets = item.assets(assets)
end
render json: {
record_ids: item_ids,
assets: assets,
}, status: :ok
return
end
all = []
online_notifications.each do |item|
all.push item.attributes_with_association_ids
end
render json: all, status: :ok
end end
=begin =begin

View file

@ -19,10 +19,36 @@ curl http://localhost/api/v1/recent_view -v -u #{login}:#{password} -H "Content-
=end =end
def index def index
recent_viewed = RecentView.list_full(current_user, 10) recent_viewed = RecentView.list(current_user, 10)
# return result if response_expand?
render json: recent_viewed list = []
recent_viewed.each do |item|
list.push item.attributes_with_association_names
end
render json: list, status: :ok
return
end
if response_full?
assets = {}
item_ids = []
recent_viewed.each do |item|
item_ids.push item.id
assets = item.assets(assets)
end
render json: {
record_ids: item_ids,
assets: assets,
}, status: :ok
return
end
all = []
recent_viewed.each do |item|
all.push item.attributes_with_association_ids
end
render json: all, status: :ok
end end
=begin =begin

View file

@ -11,11 +11,15 @@ module ExtraCollection
assets = item.assets(assets) assets = item.assets(assets)
end end
collections[ OnlineNotification.to_app_model ] = OnlineNotification.list(user, 200) collections[ OnlineNotification.to_app_model ] = []
assets = ApplicationModel.assets_of_object_list(collections[ OnlineNotification.to_app_model ], assets) OnlineNotification.list(user, 200).each do |item|
assets = item.assets(assets)
end
collections[ RecentView.to_app_model ] = RecentView.list(user, 10) collections[ RecentView.to_app_model ] = []
assets = RecentView.assets_of_object_list(collections[ RecentView.to_app_model ], assets) RecentView.list(user, 10).each do |item|
assets = item.assets(assets)
end
collections[ Permission.to_app_model ] = [] collections[ Permission.to_app_model ] = []
Permission.all.each do |item| Permission.all.each do |item|

View file

@ -335,12 +335,12 @@ class TicketsController < ApplicationController
end end
ticket_ids_recent_viewed = [] ticket_ids_recent_viewed = []
recent_views = RecentView.list(current_user, 8, 'Ticket').delete_if { |object| object['o_id'] == ticket.id } recent_views = RecentView.list(current_user, 8, 'Ticket')
recent_views.each do |recent_view| recent_views.each do |recent_view|
next if recent_view['object'] != 'Ticket' next if recent_view.object.name != 'Ticket'
ticket_ids_recent_viewed.push recent_view['o_id'] next if recent_view.o_id == ticket.id
recent_view_ticket = Ticket.find(recent_view['o_id']) ticket_ids_recent_viewed.push recent_view.o_id
next if recent_view_ticket.state.state_type.name == 'merged' recent_view_ticket = Ticket.find(recent_view.o_id)
assets = recent_view_ticket.assets(assets) assets = recent_view_ticket.assets(assets)
end end

View file

@ -1,9 +1,12 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/ # Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class ActivityStream < ApplicationModel class ActivityStream < ApplicationModel
load 'activity_stream/assets.rb'
include ActivityStream::Assets
self.table_name = 'activity_streams' self.table_name = 'activity_streams'
belongs_to :activity_stream_type, class_name: 'TypeLookup' belongs_to :object, class_name: 'ObjectLookup', foreign_key: 'activity_stream_object_id'
belongs_to :activity_stream_object, class_name: 'ObjectLookup' belongs_to :type, class_name: 'TypeLookup', foreign_key: 'activity_stream_type_id'
=begin =begin
@ -108,16 +111,7 @@ return all activity entries of an user
.order('created_at DESC, id DESC') .order('created_at DESC, id DESC')
.limit(limit) .limit(limit)
end end
list = [] stream
stream.each do |item|
data = item.attributes
data['object'] = ObjectLookup.by_id( data['activity_stream_object_id'] )
data['type'] = TypeLookup.by_id( data['activity_stream_type_id'] )
data.delete('activity_stream_object_id')
data.delete('activity_stream_type_id')
list.push data
end
list
end end
=begin =begin

View file

@ -0,0 +1,56 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class ActivityStream
module Assets
=begin
get all assets / related models for this activity stream item
activity_stream = ActivityStream.find(123)
result = activity_stream.assets(assets_if_exists)
returns
result = {
:ActivityStream => {
123 => activity_stream_model_123,
1234 => activity_stream_model_1234,
}
}
=end
def assets(data)
app_model = self.class.to_app_model
if !data[ app_model ]
data[ app_model ] = {}
end
if !data[ app_model ][ id ]
local_attributes = attributes_with_association_ids
local_attributes['object'] = ObjectLookup.by_id(local_attributes['activity_stream_object_id'])
local_attributes['type'] = TypeLookup.by_id(local_attributes['activity_stream_type_id'])
# set temp. current attributes to assets pool to prevent
# loops, will be updated with lookup attributes later
data[ app_model ][ id ] = local_attributes
ApplicationModel.assets_of_object_list([local_attributes], data)
end
return data if !self['created_by_id']
app_model_user = User.to_app_model
%w[created_by_id].each do |local_user_id|
next if !self[ local_user_id ]
next if data[ app_model_user ] && data[ app_model_user ][ self[ local_user_id ] ]
user = User.lookup(id: self[ local_user_id ])
next if !user
data = user.assets(data)
end
data
end
end
end

View file

@ -1,8 +1,11 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/ # Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class OnlineNotification < ApplicationModel class OnlineNotification < ApplicationModel
belongs_to :type_lookup, class_name: 'TypeLookup' load 'online_notification/assets.rb'
belongs_to :object_lookup, class_name: 'ObjectLookup' include OnlineNotification::Assets
belongs_to :type, class_name: 'TypeLookup', foreign_key: 'type_lookup_id'
belongs_to :object, class_name: 'ObjectLookup', foreign_key: 'object_lookup_id'
belongs_to :user belongs_to :user
after_create :notify_clients_after_change after_create :notify_clients_after_change
@ -49,7 +52,7 @@ add a new online notification for this user
updated_at: data[:updated_at] || Time.zone.now, updated_at: data[:updated_at] || Time.zone.now,
} }
OnlineNotification.create(record) OnlineNotification.create!(record)
end end
=begin =begin
@ -92,9 +95,9 @@ remove whole online notifications of an object by type
=end =end
def self.remove_by_type(object_name, o_id, type, user) def self.remove_by_type(object_name, o_id, type_name, user)
object_id = ObjectLookup.by_name(object_name) object_id = ObjectLookup.by_name(object_name)
type_id = TypeLookup.by_name(type) type_id = TypeLookup.by_name(type_name)
OnlineNotification.where( OnlineNotification.where(
object_lookup_id: object_id, object_lookup_id: object_id,
type_lookup_id: type_id, type_lookup_id: type_id,
@ -112,20 +115,9 @@ return all online notifications of an user
=end =end
def self.list(user, limit) def self.list(user, limit)
OnlineNotification.where(user_id: user.id)
notifications = OnlineNotification.where(user_id: user.id)
.order('created_at DESC, id DESC') .order('created_at DESC, id DESC')
.limit(limit) .limit(limit)
list = []
notifications.each do |item|
data = item.attributes
data['object'] = ObjectLookup.by_id(data['object_lookup_id'])
data['type'] = TypeLookup.by_id(data['type_lookup_id'])
data.delete('object_lookup_id')
data.delete('type_lookup_id')
list.push data
end
list
end end
=begin =begin
@ -169,31 +161,6 @@ mark online notification as seen by object
true true
end end
=begin
return all online notifications of an user with assets
OnlineNotification.list_full(user)
returns:
list = {
stream: notifications,
assets: assets,
}
=end
def self.list_full(user, limit)
notifications = OnlineNotification.list(user, limit)
assets = ApplicationModel.assets_of_object_list(notifications)
{
stream: notifications,
assets: assets
}
end
def notify_clients_after_change def notify_clients_after_change
Sessions.send_to( Sessions.send_to(
user_id, user_id,
@ -216,8 +183,8 @@ returns:
=end =end
def self.all_seen?(object, o_id) def self.all_seen?(object_name, o_id)
notifications = OnlineNotification.list_by_object(object, o_id) notifications = OnlineNotification.list_by_object(object_name, o_id)
notifications.each do |onine_notification| notifications.each do |onine_notification|
return false if !onine_notification['seen'] return false if !onine_notification['seen']
end end
@ -237,15 +204,17 @@ returns:
=end =end
# rubocop:disable Metrics/ParameterLists # rubocop:disable Metrics/ParameterLists
def self.exists?(user, object, o_id, type, created_by_user, seen) def self.exists?(user, object_name, o_id, type_name, created_by_user, seen)
# rubocop:enable Metrics/ParameterLists # rubocop:enable Metrics/ParameterLists
object_id = ObjectLookup.by_name(object_name)
type_id = TypeLookup.by_name(type_name)
notifications = OnlineNotification.list(user, 10) notifications = OnlineNotification.list(user, 10)
notifications.each do |notification| notifications.each do |notification|
next if notification['o_id'] != o_id next if notification.o_id != o_id
next if notification['object'] != object next if notification.object_lookup_id != object_id
next if notification['type'] != type next if notification.type_lookup_id != type_id
next if notification['created_by_id'] != created_by_user.id next if notification.created_by_id != created_by_user.id
next if notification['seen'] != seen next if notification.seen != seen
return true return true
end end
false false

View file

@ -0,0 +1,56 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class OnlineNotification
module Assets
=begin
get all assets / related models for this online notification item
online_notification = OnlineNotification.find(123)
result = online_notification.assets(assets_if_exists)
returns
result = {
:OnlineNotification => {
123 => online_notification_model_123,
1234 => online_notification_model_1234,
}
}
=end
def assets(data)
app_model = self.class.to_app_model
if !data[ app_model ]
data[ app_model ] = {}
end
if !data[ app_model ][ id ]
local_attributes = attributes_with_association_ids
local_attributes['object'] = ObjectLookup.by_id(local_attributes['object_lookup_id'])
local_attributes['type'] = TypeLookup.by_id(local_attributes['type_lookup_id'])
# set temp. current attributes to assets pool to prevent
# loops, will be updated with lookup attributes later
data[ app_model ][ id ] = local_attributes
ApplicationModel.assets_of_object_list([local_attributes], data)
end
return data if !self['created_by_id'] && !self['updated_by_id']
app_model_user = User.to_app_model
%w[created_by_id updated_by_id].each do |local_user_id|
next if !self[ local_user_id ]
next if data[ app_model_user ] && data[ app_model_user ][ self[ local_user_id ] ]
user = User.lookup(id: self[ local_user_id ])
next if !user
data = user.assets(data)
end
data
end
end
end

View file

@ -1,8 +1,10 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/ # Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class RecentView < ApplicationModel class RecentView < ApplicationModel
belongs_to :object_lookup, class_name: 'ObjectLookup' load 'recent_view/assets.rb'
belongs_to :ticket, class_name: 'Ticket', foreign_key: 'o_id' include RecentView::Assets
belongs_to :object, class_name: 'ObjectLookup', foreign_key: 'recent_view_object_id'
after_create :notify_clients after_create :notify_clients
after_update :notify_clients after_update :notify_clients
@ -36,53 +38,46 @@ class RecentView < ApplicationModel
RecentView.where(created_by_id: user.id).destroy_all RecentView.where(created_by_id: user.id).destroy_all
end end
def self.list(user, limit = 10, type = nil) def self.list(user, limit = 10, object_name = nil)
recent_views = if !type recent_views = if !object_name
RecentView.select('o_id, recent_view_object_id, MAX(created_at) as created_at, MAX(id) as id') RecentView.select('o_id, recent_view_object_id, MAX(created_at) as created_at, MAX(id) as id, created_by_id')
.group(:o_id, :recent_view_object_id) .group(:o_id, :recent_view_object_id, :created_by_id)
.where(created_by_id: user.id) .where(created_by_id: user.id)
.limit(limit) .limit(limit)
elsif type == 'Ticket' elsif object_name == 'Ticket'
state_ids = Ticket::State.by_category(:viewable_agent_new).pluck(:id) state_ids = Ticket::State.by_category(:viewable_agent_new).pluck(:id)
RecentView.joins(:ticket) local_recent_views = RecentView.select('o_id, recent_view_object_id, MAX(created_at) as created_at, MAX(id) as id, created_by_id')
.select('recent_views.o_id as o_id, recent_views.recent_view_object_id as recent_view_object_id, MAX(recent_views.created_at) as created_at, MAX(recent_views.id) as id') .group(:o_id, :recent_view_object_id, :created_by_id)
.group(:o_id, :recent_view_object_id) .where(created_by_id: user.id, recent_view_object_id: ObjectLookup.by_name(object_name))
.where('recent_views.created_by_id = ? AND recent_views.recent_view_object_id = ? AND tickets.state_id IN (?)', user.id, ObjectLookup.by_name('Ticket'), state_ids ) .limit(limit + 10)
.limit(limit) clear_list = []
local_recent_views.each do |item|
ticket = Ticket.find_by(id: item.o_id)
next if !ticket
next if !state_ids.include?(ticket.state_id)
clear_list.push item
break if clear_list.count == limit
end
clear_list
else else
RecentView.select('o_id, recent_view_object_id, MAX(created_at) as created_at, MAX(id) as id') RecentView.select('o_id, recent_view_object_id, MAX(created_at) as created_at, MAX(id) as id, created_by_id')
.group(:o_id, :recent_view_object_id) .group(:o_id, :recent_view_object_id, :created_by_id)
.where(created_by_id: user.id, recent_view_object_id: ObjectLookup.by_name(type)) .where(created_by_id: user.id, recent_view_object_id: ObjectLookup.by_name(object_name))
.limit(limit) .limit(limit)
end end
list = [] list = []
recent_views.each do |item| recent_views.each do |item|
data = item.attributes
data['object'] = ObjectLookup.by_id(data['recent_view_object_id'])
data.delete('recent_view_object_id')
# access check # access check
next if !access(data['object'], data['o_id'], user) next if !access(ObjectLookup.by_id(item['recent_view_object_id']), item['o_id'], user)
# add to result list # add to result list
list.push data list.push item
end end
list list
end end
def self.list_full(user, limit = 10)
recent_viewed = list(user, limit)
# get related object
assets = ApplicationModel.assets_of_object_list(recent_viewed)
{
stream: recent_viewed,
assets: assets,
}
end
def notify_clients def notify_clients
Sessions.send_to( Sessions.send_to(
created_by_id, created_by_id,
@ -117,11 +112,11 @@ cleanup old entries
optional you can put the max oldest entries as argument optional you can put the max oldest entries as argument
RecentView.cleanup(1.month) RecentView.cleanup(3.month)
=end =end
def self.cleanup(diff = 1.month) def self.cleanup(diff = 3.months)
RecentView.where('created_at < ?', Time.zone.now - diff).delete_all RecentView.where('created_at < ?', Time.zone.now - diff).delete_all
true true
end end

View file

@ -0,0 +1,55 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class RecentView
module Assets
=begin
get all assets / related models for this recend view item
recent_view = RecentView.find(123)
result = recent_view.assets(assets_if_exists)
returns
result = {
:RecentView => {
123 => recent_view_model_123,
1234 => recent_view_model_1234,
}
}
=end
def assets(data)
app_model = self.class.to_app_model
if !data[ app_model ]
data[ app_model ] = {}
end
if !data[ app_model ][ id ]
local_attributes = attributes_with_association_ids
local_attributes['object'] = ObjectLookup.by_id(local_attributes['recent_view_object_id'])
# set temp. current attributes to assets pool to prevent
# loops, will be updated with lookup attributes later
data[ app_model ][ id ] = local_attributes
ApplicationModel.assets_of_object_list([local_attributes], data)
end
return data if !self['created_by_id']
app_model_user = User.to_app_model
%w[created_by_id].each do |local_user_id|
next if !self[ local_user_id ]
next if data[ app_model_user ] && data[ app_model_user ][ self[ local_user_id ] ]
user = User.lookup(id: self[ local_user_id ])
next if !user
data = user.assets(data)
end
data
end
end
end

View file

@ -44,7 +44,7 @@ class User < ApplicationModel
before_update :check_preferences_default, :validate_ooo, :reset_login_failed, :validate_agent_limit_by_attributes, :last_admin_check_by_attribute before_update :check_preferences_default, :validate_ooo, :reset_login_failed, :validate_agent_limit_by_attributes, :last_admin_check_by_attribute
after_create :avatar_for_email_check after_create :avatar_for_email_check
after_update :avatar_for_email_check after_update :avatar_for_email_check
after_destroy :avatar_destroy, :user_device_destroy before_destroy :avatar_destroy, :user_device_destroy, :cit_caller_id_destroy, :task_destroy
has_and_belongs_to_many :roles, after_add: %i[cache_update check_notifications], after_remove: :cache_update, before_add: %i[validate_agent_limit_by_role validate_roles], before_remove: :last_admin_check_by_role, class_name: 'Role' has_and_belongs_to_many :roles, after_add: %i[cache_update check_notifications], after_remove: :cache_update, before_add: %i[validate_agent_limit_by_role validate_roles], before_remove: :last_admin_check_by_role, class_name: 'Role'
has_and_belongs_to_many :organizations, after_add: :cache_update, after_remove: :cache_update, class_name: 'Organization' has_and_belongs_to_many :organizations, after_add: :cache_update, after_remove: :cache_update, class_name: 'Organization'
@ -257,14 +257,17 @@ returns
=end =end
def activity_stream(limit, fulldata = false) def activity_stream(limit, fulldata = false)
activity_stream = ActivityStream.list(self, limit) stream = ActivityStream.list(self, limit)
return activity_stream if !fulldata return stream if !fulldata
# get related objects # get related objects
assets = ApplicationModel.assets_of_object_list(activity_stream) assets = {}
stream.each do |item|
assets = item.assets(assets)
end
{ {
activity_stream: activity_stream, stream: stream,
assets: assets, assets: assets,
} }
end end
@ -1132,6 +1135,14 @@ raise 'Minimum one user need to have admin permissions'
UserDevice.remove(id) UserDevice.remove(id)
end end
def cit_caller_id_destroy
Cti::CallerId.where(user_id: id).destroy_all
end
def task_destroy
Taskbar.where(user_id: id).destroy_all
end
def ensure_password def ensure_password
return true if password_empty? return true if password_empty?
return true if PasswordHash.crypted?(password) return true if PasswordHash.crypted?(password)

View file

@ -26,7 +26,17 @@ class Sessions::Backend::ActivityStream
@last_change = activity_stream.first['created_at'] @last_change = activity_stream.first['created_at']
end end
@user.activity_stream(25, true) assets = {}
item_ids = []
activity_stream.each do |item|
item_ids.push item.id
assets = item.assets(assets)
end
{
record_ids: item_ids,
assets: assets,
}
end end
def client_key def client_key

View file

@ -235,18 +235,18 @@ test( "model search tests", function() {
}, },
] ) ] )
priorities = App.TicketPriority.search({sortBy:'created_at', order: 'ASC'}) priorities = App.TicketPriority.search({sortBy:'created_at', order: 'ASC'})
equal( '2 normal', priorities[0].name, 'check 1 entry') equal('2 normal', priorities[0].name, 'check 1 entry')
equal( '3 high', priorities[1].name, 'check 2 entry') equal('3 high', priorities[1].name, 'check 2 entry')
equal( '4 very high', priorities[2].name, 'check 3 entry') equal('4 very high', priorities[2].name, 'check 3 entry')
equal( '1 low', priorities[3].name, 'check 4 entry') equal('1 low', priorities[3].name, 'check 4 entry')
equal( undefined, priorities[4], 'check 5 entry') equal(undefined, priorities[4], 'check 5 entry')
priorities = App.TicketPriority.search({sortBy:'created_at', order: 'DESC'}) priorities = App.TicketPriority.search({sortBy:'created_at', order: 'DESC'})
equal( '1 low', priorities[0].name, 'check 4 entry') equal('1 low', priorities[0].name, 'check 4 entry')
equal( '4 very high', priorities[1].name, 'check 3 entry') equal('4 very high', priorities[1].name, 'check 3 entry')
equal( '3 high', priorities[2].name, 'check 2 entry') equal('3 high', priorities[2].name, 'check 2 entry')
equal( '2 normal', priorities[3].name, 'check 1 entry') equal('2 normal', priorities[3].name, 'check 1 entry')
equal( undefined, priorities[4], 'check 5 entry') equal(undefined, priorities[4], 'check 5 entry')
}); });
@ -255,12 +255,12 @@ test( "model loadAssets tests - 1", function() {
window.refreshCounter1 = 0 window.refreshCounter1 = 0
var callback1 = function(state, triggerType) { var callback1 = function(state, triggerType) {
window.refreshCounter1 = window.refreshCounter1 + 1 window.refreshCounter1 = window.refreshCounter1 + 1
equal( state.id, 9999, 'id check') equal(state.id, 9999, 'id check')
if (window.refreshCounter1 == 1) { if (window.refreshCounter1 == 1) {
equal( 'full', triggerType, 'trigger type check') equal('full', triggerType, 'trigger type check')
} }
else { else {
equal( 'refresh', triggerType, 'trigger type check') equal('refresh', triggerType, 'trigger type check')
} }
if ( window.refreshCounter1 == 1 ) { if ( window.refreshCounter1 == 1 ) {
@ -298,7 +298,7 @@ test( "model loadAssets tests - 1", function() {
App.Delay.set( function() { App.Delay.set( function() {
test( "model loadAssets tests - 1 / check refresh counter", function() { test( "model loadAssets tests - 1 / check refresh counter", function() {
equal( window.refreshCounter1, 2, 'check refresh counter') equal(window.refreshCounter1, 2, 'check refresh counter')
}); });
}, },
1000 1000
@ -308,12 +308,12 @@ test( "model loadAssets tests - 2", function() {
window.refreshCounter2 = 0 window.refreshCounter2 = 0
var callback2 = function(state, triggerType) { var callback2 = function(state, triggerType) {
window.refreshCounter2 = window.refreshCounter2 + 1 window.refreshCounter2 = window.refreshCounter2 + 1
equal( state.id, 10000, 'id check') equal(state.id, 10000, 'id check')
if (window.refreshCounter2 == 1) { if (window.refreshCounter2 == 1) {
equal( 'full', triggerType, 'trigger type check') equal('full', triggerType, 'trigger type check')
} }
else { else {
equal( 'refresh', triggerType, 'trigger type check') equal('refresh', triggerType, 'trigger type check')
} }
if ( window.refreshCounter2 == 1 ) { if ( window.refreshCounter2 == 1 ) {
App.Collection.loadAssets({ App.Collection.loadAssets({
@ -349,7 +349,7 @@ test( "model loadAssets tests - 2", function() {
App.Delay.set( function() { App.Delay.set( function() {
test( "model loadAssets tests - 2 / check refresh counter", function() { test( "model loadAssets tests - 2 / check refresh counter", function() {
equal( window.refreshCounter2, 2, 'check refresh counter') equal(window.refreshCounter2, 2, 'check refresh counter')
}); });
}, },
1200 1200
@ -359,12 +359,12 @@ test( "model loadAssets tests - 3", function() {
window.refreshCounter3 = 0 window.refreshCounter3 = 0
var callback3 = function(state, triggerType) { var callback3 = function(state, triggerType) {
window.refreshCounter3 = window.refreshCounter3 + 1 window.refreshCounter3 = window.refreshCounter3 + 1
equal( state.id, 10001, 'id check') equal(state.id, 10001, 'id check')
if (window.refreshCounter3 == 1) { if (window.refreshCounter3 == 1) {
equal( 'full', triggerType, 'trigger type check') equal('full', triggerType, 'trigger type check')
} }
else { else {
equal( 'refresh', triggerType, 'trigger type check') equal('refresh', triggerType, 'trigger type check')
} }
if ( window.refreshCounter3 == 1 ) { if ( window.refreshCounter3 == 1 ) {
@ -401,7 +401,7 @@ test( "model loadAssets tests - 3", function() {
App.Delay.set( function() { App.Delay.set( function() {
test( "model loadAssets tests - 3 / check refresh counter", function() { test( "model loadAssets tests - 3 / check refresh counter", function() {
equal( window.refreshCounter3, 3, 'check refresh counter') equal(window.refreshCounter3, 3, 'check refresh counter')
}); });
}, },
1400 1400

View file

@ -91,15 +91,38 @@ class ApiAuthControllerTest < ActionDispatch::IntegrationTest
assert_equal(Hash, result_ticket_create.class) assert_equal(Hash, result_ticket_create.class)
assert_equal(result_ticket_create['created_by_id'], @customer.id) assert_equal(result_ticket_create['created_by_id'], @customer.id)
get '/api/v1/activity_stream', params: {}, headers: admin_headers get '/api/v1/activity_stream?full=true', params: {}, headers: admin_headers
assert_response(200) assert_response(200)
result_activity_stream = JSON.parse(@response.body) result_activity_stream = JSON.parse(@response.body)
assert_equal(Hash, result_activity_stream.class) assert_equal(Hash, result_activity_stream.class)
ticket_created = result_activity_stream['activity_stream'].find { |activity| activity['object'] == 'Ticket' && activity['o_id'] == result_ticket_create['id'] } ticket_created = nil
result_activity_stream['record_ids'].each do |record_id|
activity_stream = ActivityStream.find(record_id)
next if activity_stream.object.name != 'Ticket'
next if activity_stream.o_id != result_ticket_create['id']
ticket_created = activity_stream
end
assert(ticket_created)
assert_equal(ticket_created.created_by_id, @customer.id)
get '/api/v1/activity_stream', params: {}, headers: admin_headers
assert_response(200)
result_activity_stream = JSON.parse(@response.body)
assert_equal(Array, result_activity_stream.class)
ticket_created = nil
result_activity_stream.each do |record|
activity_stream = ActivityStream.find(record['id'])
next if activity_stream.object.name != 'Ticket'
next if activity_stream.o_id != result_ticket_create['id']
ticket_created = activity_stream
end
assert(ticket_created)
assert_equal(ticket_created.created_by_id, @customer.id)
assert_equal(Hash, ticket_created.class)
assert_equal(ticket_created['created_by_id'], @customer.id)
end end
test 'X-On-Behalf-Of auth - ticket create admin for customer by email' do test 'X-On-Behalf-Of auth - ticket create admin for customer by email' do

View file

@ -62,24 +62,24 @@ class ActivityStreamTest < ActiveSupport::TestCase
# check activity_stream # check activity_stream
stream = @admin_user.activity_stream(4) stream = @admin_user.activity_stream(4)
assert_equal(stream[0]['group_id'], ticket.group_id) assert_equal(stream[0].group_id, ticket.group_id)
assert_equal(stream[0]['o_id'], ticket.id) assert_equal(stream[0].o_id, ticket.id)
assert_equal(stream[0]['created_by_id'], @current_user.id) assert_equal(stream[0].created_by_id, @current_user.id)
assert_equal(stream[0]['created_at'].to_s, updated_at.to_s) assert_equal(stream[0].created_at.to_s, updated_at.to_s)
assert_equal(stream[0]['object'], 'Ticket') assert_equal(stream[0].object.name, 'Ticket')
assert_equal(stream[0]['type'], 'update') assert_equal(stream[0].type.name, 'update')
assert_equal(stream[1]['group_id'], ticket.group_id) assert_equal(stream[1].group_id, ticket.group_id)
assert_equal(stream[1]['o_id'], article.id) assert_equal(stream[1].o_id, article.id)
assert_equal(stream[1]['created_by_id'], @current_user.id) assert_equal(stream[1].created_by_id, @current_user.id)
assert_equal(stream[1]['created_at'].to_s, article.created_at.to_s) assert_equal(stream[1].created_at.to_s, article.created_at.to_s)
assert_equal(stream[1]['object'], 'Ticket::Article') assert_equal(stream[1].object.name, 'Ticket::Article')
assert_equal(stream[1]['type'], 'create') assert_equal(stream[1].type.name, 'create')
assert_equal(stream[2]['group_id'], ticket.group_id) assert_equal(stream[2].group_id, ticket.group_id)
assert_equal(stream[2]['o_id'], ticket.id) assert_equal(stream[2].o_id, ticket.id)
assert_equal(stream[2]['created_by_id'], @current_user.id) assert_equal(stream[2].created_by_id, @current_user.id)
assert_equal(stream[2]['created_at'].to_s, ticket.created_at.to_s) assert_equal(stream[2].created_at.to_s, ticket.created_at.to_s)
assert_equal(stream[2]['object'], 'Ticket') assert_equal(stream[2].object.name, 'Ticket')
assert_equal(stream[2]['type'], 'create') assert_equal(stream[2].type.name, 'create')
assert_not(stream[3]) assert_not(stream[3])
stream = @current_user.activity_stream(4) stream = @current_user.activity_stream(4)
@ -90,18 +90,18 @@ class ActivityStreamTest < ActiveSupport::TestCase
# check activity_stream # check activity_stream
stream = @admin_user.activity_stream(4) stream = @admin_user.activity_stream(4)
assert_equal(stream[0]['group_id'], ticket.group_id) assert_equal(stream[0].group_id, ticket.group_id)
assert_equal(stream[0]['o_id'], ticket.id) assert_equal(stream[0].o_id, ticket.id)
assert_equal(stream[0]['created_by_id'], @current_user.id) assert_equal(stream[0].created_by_id, @current_user.id)
assert_equal(stream[0]['created_at'].to_s, updated_at.to_s) assert_equal(stream[0].created_at.to_s, updated_at.to_s)
assert_equal(stream[0]['object'], 'Ticket') assert_equal(stream[0].object.name, 'Ticket')
assert_equal(stream[0]['type'], 'update') assert_equal(stream[0].type.name, 'update')
assert_equal(stream[1]['group_id'], ticket.group_id) assert_equal(stream[1].group_id, ticket.group_id)
assert_equal(stream[1]['o_id'], ticket.id) assert_equal(stream[1].o_id, ticket.id)
assert_equal(stream[1]['created_by_id'], @current_user.id) assert_equal(stream[1].created_by_id, @current_user.id)
assert_equal(stream[1]['created_at'].to_s, ticket.created_at.to_s) assert_equal(stream[1].created_at.to_s, ticket.created_at.to_s)
assert_equal(stream[1]['object'], 'Ticket') assert_equal(stream[1].object.name, 'Ticket')
assert_equal(stream[1]['type'], 'create') assert_equal(stream[1].type.name, 'create')
assert_not(stream[2]) assert_not(stream[2])
stream = @current_user.activity_stream(4) stream = @current_user.activity_stream(4)
@ -129,18 +129,18 @@ class ActivityStreamTest < ActiveSupport::TestCase
# check activity_stream # check activity_stream
stream = @admin_user.activity_stream(3) stream = @admin_user.activity_stream(3)
assert_not(stream[0]['group_id']) assert_not(stream[0].group_id)
assert_equal(stream[0]['o_id'], organization.id) assert_equal(stream[0].o_id, organization.id)
assert_equal(stream[0]['created_by_id'], @current_user.id) assert_equal(stream[0].created_by_id, @current_user.id)
assert_equal(stream[0]['created_at'].to_s, updated_at.to_s) assert_equal(stream[0].created_at.to_s, updated_at.to_s)
assert_equal(stream[0]['object'], 'Organization') assert_equal(stream[0].object.name, 'Organization')
assert_equal(stream[0]['type'], 'update') assert_equal(stream[0].type.name, 'update')
assert_not(stream[1]['group_id']) assert_not(stream[1].group_id)
assert_equal(stream[1]['o_id'], organization.id) assert_equal(stream[1].o_id, organization.id)
assert_equal(stream[1]['created_by_id'], @current_user.id) assert_equal(stream[1].created_by_id, @current_user.id)
assert_equal(stream[1]['created_at'].to_s, organization.created_at.to_s) assert_equal(stream[1].created_at.to_s, organization.created_at.to_s)
assert_equal(stream[1]['object'], 'Organization') assert_equal(stream[1].object.name, 'Organization')
assert_equal(stream[1]['type'], 'create') assert_equal(stream[1].type.name, 'create')
assert_not(stream[2]) assert_not(stream[2])
stream = @current_user.activity_stream(4) stream = @current_user.activity_stream(4)
@ -167,12 +167,12 @@ class ActivityStreamTest < ActiveSupport::TestCase
# check activity_stream # check activity_stream
stream = @admin_user.activity_stream(3) stream = @admin_user.activity_stream(3)
assert_not(stream[0]['group_id']) assert_not(stream[0].group_id)
assert_equal(stream[0]['o_id'], user.id) assert_equal(stream[0].o_id, user.id)
assert_equal(stream[0]['created_by_id'], @current_user.id) assert_equal(stream[0].created_by_id, @current_user.id)
assert_equal(stream[0]['created_at'].to_s, user.created_at.to_s) assert_equal(stream[0].created_at.to_s, user.created_at.to_s)
assert_equal(stream[0]['object'], 'User') assert_equal(stream[0].object.name, 'User')
assert_equal(stream[0]['type'], 'create') assert_equal(stream[0].type.name, 'create')
assert_not(stream[1]) assert_not(stream[1])
stream = @current_user.activity_stream(4) stream = @current_user.activity_stream(4)
@ -208,18 +208,18 @@ class ActivityStreamTest < ActiveSupport::TestCase
# check activity_stream # check activity_stream
stream = @admin_user.activity_stream(3) stream = @admin_user.activity_stream(3)
assert_not(stream[0]['group_id']) assert_not(stream[0].group_id)
assert_equal(stream[0]['o_id'], user.id) assert_equal(stream[0].o_id, user.id)
assert_equal(stream[0]['created_by_id'], @current_user.id) assert_equal(stream[0].created_by_id, @current_user.id)
assert_equal(stream[0]['created_at'].to_s, updated_at.to_s) assert_equal(stream[0].created_at.to_s, updated_at.to_s)
assert_equal(stream[0]['object'], 'User') assert_equal(stream[0].object.name, 'User')
assert_equal(stream[0]['type'], 'update') assert_equal(stream[0].type.name, 'update')
assert_not(stream[1]['group_id']) assert_not(stream[1].group_id)
assert_equal(stream[1]['o_id'], user.id) assert_equal(stream[1].o_id, user.id)
assert_equal(stream[1]['created_by_id'], @current_user.id) assert_equal(stream[1].created_by_id, @current_user.id)
assert_equal(stream[1]['created_at'].to_s, user.created_at.to_s) assert_equal(stream[1].created_at.to_s, user.created_at.to_s)
assert_equal(stream[1]['object'], 'User') assert_equal(stream[1].object.name, 'User')
assert_equal(stream[1]['type'], 'create') assert_equal(stream[1].type.name, 'create')
assert_not(stream[2]) assert_not(stream[2])
stream = @current_user.activity_stream(4) stream = @current_user.activity_stream(4)

View file

@ -37,11 +37,11 @@ class RecentViewTest < ActiveSupport::TestCase
RecentView.log(ticket1.class.to_s, ticket1.id, user1) RecentView.log(ticket1.class.to_s, ticket1.id, user1)
list = RecentView.list(user1) list = RecentView.list(user1)
assert(list[0]['o_id'], ticket1.id) assert(list[0].o_id, ticket1.id)
assert(list[0]['object'], 'Ticket') assert(list[0].object.name, 'Ticket')
assert(list[1]['o_id'], ticket2.id) assert(list[1].o_id, ticket2.id)
assert(list[1]['object'], 'Ticket') assert(list[1].object.name, 'Ticket')
assert_equal(2, list.count) assert_equal(2, list.count)
ticket1.destroy ticket1.destroy
@ -156,8 +156,8 @@ class RecentViewTest < ActiveSupport::TestCase
# check if list is empty # check if list is empty
list = RecentView.list(customer) list = RecentView.list(customer)
assert(list[0]['o_id'], ticket1.id) assert(list[0].o_id, ticket1.id)
assert(list[0]['object'], 'Ticket') assert(list[0].object.name, 'Ticket')
assert_not(list[1], 'check if recent view list is empty') assert_not(list[1], 'check if recent view list is empty')
# log entry # log entry
@ -178,8 +178,8 @@ class RecentViewTest < ActiveSupport::TestCase
# check if list is empty # check if list is empty
list = RecentView.list(agent) list = RecentView.list(agent)
assert(list[0]['o_id'], organization1.id) assert(list[0].o_id, organization1.id)
assert(list[0]['object'], 'Organization') assert(list[0].object.name, 'Organization')
assert_not(list[1], 'check if recent view list is empty') assert_not(list[1], 'check if recent view list is empty')
organization2.destroy organization2.destroy