Added generic activity stream support.
This commit is contained in:
parent
9aa5afbd65
commit
4e2288e9a4
21 changed files with 611 additions and 90 deletions
|
@ -40,21 +40,26 @@ class App.DashboardActivityStream extends App.Controller
|
|||
render: (items) ->
|
||||
|
||||
for item in items
|
||||
if item.history_object is 'Ticket'
|
||||
if item.object is 'Ticket'
|
||||
ticket = App.Ticket.find( item.o_id )
|
||||
item.link = '#ticket/zoom/' + ticket.id
|
||||
item.title = ticket.title
|
||||
item.type = 'Ticket'
|
||||
item.updated_by_id = ticket.updated_by_id
|
||||
item.updated_by = App.User.find( ticket.updated_by_id )
|
||||
else if item.history_object is 'Ticket::Article'
|
||||
item.object = 'Ticket'
|
||||
|
||||
else if item.object is 'Ticket::Article'
|
||||
article = App.TicketArticle.find( item.o_id )
|
||||
ticket = App.Ticket.find( article.ticket_id )
|
||||
item.link = '#ticket/zoom/' + ticket.id + '/' + article.id
|
||||
item.title = article.subject || ticket.title
|
||||
item.type = 'Article'
|
||||
item.updated_by_id = article.updated_by_id
|
||||
item.updated_by = App.User.find( article.updated_by_id )
|
||||
item.object = 'Article'
|
||||
|
||||
else if item.object is 'User'
|
||||
user = App.User.find( item.o_id )
|
||||
item.link = '#user/zoom/' + item.o_id
|
||||
item.title = user.displayName()
|
||||
item.object = 'User'
|
||||
|
||||
item.created_by = App.User.find( item.created_by_id )
|
||||
|
||||
html = App.view('dashboard/activity_stream')(
|
||||
head: 'Activity Stream',
|
||||
|
@ -67,3 +72,5 @@ class App.DashboardActivityStream extends App.Controller
|
|||
# start user popups
|
||||
@userPopups('right')
|
||||
|
||||
# update time
|
||||
@frontendTimeUpdate()
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
<h2 class="can-move"><%- @T( @head ) %></h2>
|
||||
<dl>
|
||||
<% for item in @items: %>
|
||||
<dt><span class="user-popover" data-id="<%= item.updated_by_id %>">"<%= item.updated_by.displayName() %>"</span></dt>
|
||||
<dd><%- @T( item.history_type ) %> <a href="<%- item.link %>"><%= item.type %><% if item.title: %> (<%= item.title %>)<% end %></a>.</dd>
|
||||
<dt><span class="user-popover" data-id="<%= item.created_by_id %>">"<%= item.created_by.displayName() %>"</span></dt>
|
||||
<dd><%- @T( item.type ) %> <a href="<%- item.link %>"><%= item.object %><% if item.title: %> (<%= item.title %>)<% end %></a> <span class="humanTimeFromNow" data-time="<%- item.created_at %>">?</span> <%- @T('ago') %>.</dd>
|
||||
<% end %>
|
||||
</dl>
|
||||
</div>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
# Copyright (C) 2012-2013 Zammad Foundation, http://zammad-foundation.org/
|
||||
|
||||
class ActivityController < ApplicationController
|
||||
class ActivityStreamController < ApplicationController
|
||||
before_filter :authentication_check
|
||||
|
||||
# GET /api/v1/activity_stream
|
||||
def activity_stream
|
||||
activity_stream = History.activity_stream_fulldata( current_user, params[:limit] )
|
||||
def show
|
||||
activity_stream = current_user.activity_stream( params[:limit], true )
|
||||
|
||||
# return result
|
||||
render :json => activity_stream
|
|
@ -14,6 +14,8 @@ class SessionsController < ApplicationController
|
|||
return
|
||||
end
|
||||
|
||||
user.activity_stream_log( 'session started', user.id )
|
||||
|
||||
# auto population of default collections
|
||||
default_collection = SessionHelper::default_collections(user)
|
||||
|
||||
|
|
179
app/models/activity_stream.rb
Normal file
179
app/models/activity_stream.rb
Normal file
|
@ -0,0 +1,179 @@
|
|||
# Copyright (C) 2012-2013 Zammad Foundation, http://zammad-foundation.org/
|
||||
|
||||
class ActivityStream < ApplicationModel
|
||||
self.table_name = 'activity_streams'
|
||||
belongs_to :activity_stream_type, :class_name => 'ActivityStream::Type'
|
||||
belongs_to :activity_stream_object, :class_name => 'ActivityStream::Object'
|
||||
|
||||
@@cache_type = {}
|
||||
@@cache_object = {}
|
||||
|
||||
=begin
|
||||
|
||||
add a new activity entry for an object
|
||||
|
||||
ActivityStream.add(
|
||||
:type => 'updated',
|
||||
:object => 'Ticket',
|
||||
:role => 'Admin',
|
||||
:o_id => ticket.id,
|
||||
:created_by_id => 1,
|
||||
:created_at => '2013-06-04 10:00:00',
|
||||
)
|
||||
|
||||
=end
|
||||
|
||||
def self.add(data)
|
||||
|
||||
# lookups
|
||||
if data[:type]
|
||||
type = self.type_lookup( data[:type] )
|
||||
end
|
||||
if data[:object]
|
||||
object = self.object_lookup( data[:object] )
|
||||
end
|
||||
|
||||
role_id = nil
|
||||
if data[:role]
|
||||
role_id = Role.lookup( :name => data[:role] )
|
||||
if !role_id
|
||||
raise "No such Role #{data[:role]}"
|
||||
end
|
||||
end
|
||||
|
||||
# check if entry is needed
|
||||
result = ActivityStream.where(
|
||||
:o_id => data[:o_id],
|
||||
# :activity_stream_type_id => type.id,
|
||||
:role_id => role_id,
|
||||
:activity_stream_object_id => object.id,
|
||||
:created_by_id => data[:created_by_id]
|
||||
).last
|
||||
|
||||
# resturn if old entry is really freash
|
||||
return result if result && result.created_at >= (data[:created_at] - 10.seconds)
|
||||
puts "AS: #{data[:type]} #{data[:object]} #{data[:o_id]}"
|
||||
|
||||
# create history
|
||||
record = {
|
||||
:o_id => data[:o_id],
|
||||
:activity_stream_type_id => type.id,
|
||||
:activity_stream_object_id => object.id,
|
||||
:created_at => data[:created_at],
|
||||
:created_by_id => data[:created_by_id]
|
||||
}
|
||||
ActivityStream.create(record)
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
remove whole activity entries of an object
|
||||
|
||||
ActivityStream.remove( 'Ticket', 123 )
|
||||
|
||||
=end
|
||||
|
||||
def self.remove( object_name, o_id )
|
||||
object = self.object_lookup( object_name )
|
||||
ActivityStream.where(
|
||||
:activity_stream_object_id => object.id,
|
||||
:o_id => o_id,
|
||||
).destroy_all
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
return all activity entries of an user
|
||||
|
||||
activity_stream = ActivityStream.list( user )
|
||||
|
||||
=end
|
||||
|
||||
def self.list(user,limit)
|
||||
# stream = ActivityStream.where( :role_id => user.roles, :group_id => user.groups )
|
||||
stream = ActivityStream.where('1=1').
|
||||
order( 'created_at DESC, id DESC' ).
|
||||
limit( limit )
|
||||
list = []
|
||||
stream.each do |item|
|
||||
data = item.attributes
|
||||
data['object'] = self.object_lookup_id( data['activity_stream_object_id'] ).name
|
||||
data['type'] = self.type_lookup_id( data['activity_stream_type_id'] ).name
|
||||
data.delete('activity_stream_object_id')
|
||||
data.delete('activity_stream_type_id')
|
||||
list.push data
|
||||
end
|
||||
list
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.type_lookup_id( id )
|
||||
|
||||
# use cache
|
||||
return @@cache_type[ id ] if @@cache_type[ id ]
|
||||
|
||||
# lookup
|
||||
type = ActivityStream::Type.find(id)
|
||||
@@cache_type[ id ] = type
|
||||
type
|
||||
end
|
||||
|
||||
def self.type_lookup( name )
|
||||
|
||||
# use cache
|
||||
return @@cache_type[ name ] if @@cache_type[ name ]
|
||||
|
||||
# lookup
|
||||
type = ActivityStream::Type.where( :name => name ).first
|
||||
if type
|
||||
@@cache_type[ name ] = type
|
||||
return type
|
||||
end
|
||||
|
||||
# create
|
||||
type = ActivityStream::Type.create(
|
||||
:name => name
|
||||
)
|
||||
@@cache_type[ name ] = type
|
||||
type
|
||||
end
|
||||
|
||||
def self.object_lookup_id( id )
|
||||
|
||||
# use cache
|
||||
return @@cache_object[ id ] if @@cache_object[ id ]
|
||||
|
||||
# lookup
|
||||
object = ActivityStream::Object.find(id)
|
||||
@@cache_object[ id ] = object
|
||||
object
|
||||
end
|
||||
|
||||
def self.object_lookup( name )
|
||||
|
||||
# use cache
|
||||
return @@cache_object[ name ] if @@cache_object[ name ]
|
||||
|
||||
# lookup
|
||||
object = ActivityStream::Object.where( :name => name ).first
|
||||
if object
|
||||
@@cache_object[ name ] = object
|
||||
return object
|
||||
end
|
||||
|
||||
# create
|
||||
object = ActivityStream::Object.create(
|
||||
:name => name
|
||||
)
|
||||
@@cache_object[ name ] = object
|
||||
object
|
||||
end
|
||||
|
||||
class Object < ApplicationModel
|
||||
end
|
||||
|
||||
class Type < ApplicationModel
|
||||
end
|
||||
|
||||
end
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
class ApplicationModel < ActiveRecord::Base
|
||||
include ApplicationModel::HistoryLogBase
|
||||
include ApplicationModel::ActivityStreamBase
|
||||
|
||||
self.abstract_class = true
|
||||
|
||||
|
@ -14,6 +15,13 @@ class ApplicationModel < ActiveRecord::Base
|
|||
after_update :cache_delete
|
||||
after_destroy :cache_delete
|
||||
|
||||
after_create :activity_stream_create
|
||||
after_update :activity_stream_update
|
||||
after_destroy :activity_stream_destroy
|
||||
|
||||
# create instance accessor
|
||||
class << self; attr_accessor :activity_stream_support_config end
|
||||
|
||||
@@import_class_list = ['Ticket', 'Ticket::Article', 'History', 'Ticket::State', 'Ticket::Priority', 'Group', 'User' ]
|
||||
|
||||
def check_attributes_protected
|
||||
|
@ -410,6 +418,59 @@ class OwnModel < ApplicationModel
|
|||
|
||||
=begin
|
||||
|
||||
serve methode to configure activity stream support for this model
|
||||
|
||||
class Model < ApplicationModel
|
||||
activity_stream_support :role => 'Admin'
|
||||
end
|
||||
|
||||
=end
|
||||
|
||||
def self.activity_stream_support(data = {})
|
||||
@activity_stream_support_config = data
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
log object create activity stream
|
||||
|
||||
model = Model.find(123)
|
||||
model.activity_stream_create
|
||||
|
||||
=end
|
||||
|
||||
def activity_stream_create
|
||||
activity_stream_log( 'created', self['created_by_id'] )
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
log object update activity stream
|
||||
|
||||
model = Model.find(123)
|
||||
model.activity_stream_update
|
||||
|
||||
=end
|
||||
|
||||
def activity_stream_update
|
||||
activity_stream_log( 'updated', self['updated_by_id'] )
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
delete object activity stream
|
||||
|
||||
model = Model.find(123)
|
||||
model.activity_stream_destroy
|
||||
|
||||
=end
|
||||
|
||||
def activity_stream_destroy
|
||||
ActivityStream.remove( self.class.to_s, self.id )
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
destory object dependencies, will be executed automatically
|
||||
|
||||
=end
|
||||
|
@ -418,6 +479,7 @@ destory object dependencies, will be executed automatically
|
|||
|
||||
# delete history
|
||||
History.remove( self.class.to_s, self.id )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
30
app/models/application_model/activity_stream_base.rb
Normal file
30
app/models/application_model/activity_stream_base.rb
Normal file
|
@ -0,0 +1,30 @@
|
|||
# Copyright (C) 2012-2013 Zammad Foundation, http://zammad-foundation.org/
|
||||
|
||||
module ApplicationModel::ActivityStreamBase
|
||||
|
||||
=begin
|
||||
|
||||
log activity for this object
|
||||
|
||||
article = Ticket::Article.find(123)
|
||||
result = article.activity_stream_log( 'created', user_id )
|
||||
|
||||
returns
|
||||
|
||||
result = true # false
|
||||
|
||||
=end
|
||||
|
||||
def activity_stream_log (type, user_id)
|
||||
return if !self.class.activity_stream_support_config
|
||||
ActivityStream.add(
|
||||
:o_id => self['id'],
|
||||
:type => type,
|
||||
:object => self.class.name,
|
||||
# :role => self.activity_stream_role,
|
||||
:created_at => self.updated_at,
|
||||
:created_by_id => user_id,
|
||||
)
|
||||
end
|
||||
|
||||
end
|
|
@ -1,8 +1,9 @@
|
|||
# Copyright (C) 2012-2013 Zammad Foundation, http://zammad-foundation.org/
|
||||
|
||||
class Group < ApplicationModel
|
||||
has_and_belongs_to_many :users, :after_add => :cache_update, :after_remove => :cache_update
|
||||
belongs_to :email_address
|
||||
belongs_to :signature
|
||||
validates :name, :presence => true
|
||||
end
|
||||
has_and_belongs_to_many :users, :after_add => :cache_update, :after_remove => :cache_update
|
||||
belongs_to :email_address
|
||||
belongs_to :signature
|
||||
validates :name, :presence => true
|
||||
activity_stream_support :role => 'Admin'
|
||||
end
|
|
@ -95,6 +95,7 @@ remove whole history entries of an object
|
|||
|
||||
def self.remove( requested_object, requested_object_id )
|
||||
history_object = History::Object.where( :name => requested_object ).first
|
||||
return if !history_object
|
||||
History.where(
|
||||
:history_object_id => history_object.id,
|
||||
:o_id => requested_object_id,
|
||||
|
@ -103,7 +104,7 @@ remove whole history entries of an object
|
|||
|
||||
=begin
|
||||
|
||||
return all histoy entries of an object
|
||||
return all history entries of an object
|
||||
|
||||
history_list = History.list( 'Ticket', 123 )
|
||||
|
||||
|
@ -133,56 +134,6 @@ return all histoy entries of an object
|
|||
return history
|
||||
end
|
||||
|
||||
def self.activity_stream( user, limit = 10 )
|
||||
# g = Group.where( :active => true ).joins(:users).where( 'users.id' => user.id )
|
||||
# stream = History.select("distinct(histories.o_id), created_by_id, history_attribute_id, history_type_id, history_object_id, value_from, value_to").
|
||||
# where( :history_type_id => History::Type.where( :name => ['created', 'updated']) ).
|
||||
stream = History.select("distinct(histories.o_id), created_by_id, history_type_id, history_object_id").
|
||||
where( :history_object_id => History::Object.where( :name => [ 'Ticket', 'Ticket::Article' ] ) ).
|
||||
where( :history_type_id => History::Type.where( :name => [ 'created', 'updated' ]) ).
|
||||
order('created_at DESC, id DESC').
|
||||
limit(limit)
|
||||
datas = []
|
||||
stream.each do |item|
|
||||
data = item.attributes
|
||||
data['history_object'] = self.object_lookup_id( data['history_object_id'] ).name
|
||||
data['history_type'] = self.type_lookup_id( data['history_type_id'] ).name
|
||||
data.delete('history_object_id')
|
||||
data.delete('history_type_id')
|
||||
datas.push data
|
||||
# item['history_attribute'] = item.history_attribute
|
||||
end
|
||||
return datas
|
||||
end
|
||||
|
||||
def self.activity_stream_fulldata( user, limit = 10 )
|
||||
activity_stream = History.activity_stream( user, limit )
|
||||
|
||||
# get related users
|
||||
assets = {}
|
||||
activity_stream.each {|item|
|
||||
|
||||
# load article ids
|
||||
if item['history_object'] == 'Ticket'
|
||||
ticket = Ticket.find( item['o_id'] )
|
||||
assets = ticket.assets(assets)
|
||||
end
|
||||
if item['history_object'] == 'Ticket::Article'
|
||||
article = Ticket::Article.find( item['o_id'] )
|
||||
assets = article.assets(assets)
|
||||
end
|
||||
if item['history_object'] == 'User'
|
||||
user = User.find( item['o_id'] )
|
||||
assets = user.assets(assets)
|
||||
end
|
||||
}
|
||||
|
||||
return {
|
||||
:activity_stream => activity_stream,
|
||||
:assets => assets,
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.type_lookup_id( id )
|
||||
|
|
|
@ -20,10 +20,6 @@ class Observer::History < ActiveRecord::Observer
|
|||
record.history_create( 'created', user_id )
|
||||
end
|
||||
|
||||
# log activity stream
|
||||
if record.respond_to?('activity_stream')
|
||||
record.activity_stream( 'created', user_id )
|
||||
end
|
||||
end
|
||||
|
||||
def before_update(record)
|
||||
|
@ -149,12 +145,6 @@ class Observer::History < ActiveRecord::Observer
|
|||
end
|
||||
end
|
||||
|
||||
# log activity stream
|
||||
if history_logged
|
||||
if record.respond_to?('activity_stream')
|
||||
record.activity_stream( 'updated', user_id )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def differences_from?(one, other)
|
||||
|
|
|
@ -4,7 +4,8 @@ class Organization < ApplicationModel
|
|||
include Organization::Assets
|
||||
extend Organization::Search
|
||||
|
||||
has_and_belongs_to_many :users
|
||||
validates :name, :presence => true
|
||||
has_and_belongs_to_many :users
|
||||
validates :name, :presence => true
|
||||
activity_stream_support :role => 'Admin'
|
||||
|
||||
end
|
|
@ -1,6 +1,7 @@
|
|||
# Copyright (C) 2012-2013 Zammad Foundation, http://zammad-foundation.org/
|
||||
|
||||
class Role < ApplicationModel
|
||||
has_and_belongs_to_many :users, :after_add => :cache_update, :after_remove => :cache_update
|
||||
validates :name, :presence => true
|
||||
has_and_belongs_to_many :users, :after_add => :cache_update, :after_remove => :cache_update
|
||||
validates :name, :presence => true
|
||||
activity_stream_support :role => 'Admin'
|
||||
end
|
||||
|
|
|
@ -7,6 +7,7 @@ class Ticket < ApplicationModel
|
|||
after_create :notify_clients_after_create
|
||||
after_update :notify_clients_after_update
|
||||
after_destroy :notify_clients_after_destroy
|
||||
activity_stream_support :role => 'User'
|
||||
|
||||
belongs_to :group
|
||||
has_many :articles, :class_name => 'Ticket::Article', :after_add => :cache_update, :after_remove => :cache_update
|
||||
|
|
|
@ -4,15 +4,17 @@ class Ticket::Article < ApplicationModel
|
|||
include Ticket::Article::Assets
|
||||
include Ticket::Article::HistoryLog
|
||||
|
||||
after_create :attachment_check
|
||||
belongs_to :ticket
|
||||
belongs_to :ticket_article_type, :class_name => 'Ticket::Article::Type'
|
||||
belongs_to :ticket_article_sender, :class_name => 'Ticket::Article::Sender'
|
||||
belongs_to :created_by, :class_name => 'User'
|
||||
after_create :attachment_check
|
||||
after_create :notify_clients_after_create
|
||||
after_update :notify_clients_after_update
|
||||
after_destroy :notify_clients_after_destroy
|
||||
|
||||
activity_stream_support
|
||||
|
||||
attr_accessor :attachments
|
||||
|
||||
private
|
||||
|
|
|
@ -19,6 +19,8 @@ class User < ApplicationModel
|
|||
|
||||
store :preferences
|
||||
|
||||
activity_stream_support :role => 'Admin'
|
||||
|
||||
=begin
|
||||
|
||||
fullname of user
|
||||
|
@ -43,7 +45,7 @@ returns
|
|||
end
|
||||
fullname = fullname + self.lastname
|
||||
end
|
||||
return fullname
|
||||
fullname
|
||||
end
|
||||
|
||||
=begin
|
||||
|
@ -68,6 +70,52 @@ returns
|
|||
|
||||
=begin
|
||||
|
||||
get users activity stream
|
||||
|
||||
user = User.find(123)
|
||||
result = user.activity_stream( 20 )
|
||||
|
||||
returns
|
||||
|
||||
result = [
|
||||
{
|
||||
:id =>2,
|
||||
:o_id =>2,
|
||||
:created_by_id => 3,
|
||||
:created_at => '2013-09-28 00:57:21',
|
||||
:object => "User",
|
||||
:type => "created",
|
||||
},
|
||||
{
|
||||
:id =>2,
|
||||
:o_id =>2,
|
||||
:created_by_id => 3,
|
||||
:created_at => '2013-09-28 00:59:21',
|
||||
:object => "User",
|
||||
:type => "updated",
|
||||
},
|
||||
]
|
||||
|
||||
=end
|
||||
|
||||
def activity_stream( limit, fulldata = false )
|
||||
activity_stream = ActivityStream.list( self, limit )
|
||||
return activity_stream if !fulldata
|
||||
|
||||
# get related objects
|
||||
assets = {}
|
||||
activity_stream.each {|item|
|
||||
record = Kernel.const_get( item['object'] ).find( item['o_id'] )
|
||||
assets = record.assets(assets)
|
||||
}
|
||||
return {
|
||||
:activity_stream => activity_stream,
|
||||
:assets => assets,
|
||||
}
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
authenticate user
|
||||
|
||||
result = User.authenticate(username, password)
|
||||
|
|
|
@ -28,6 +28,12 @@ returns
|
|||
if !data[ User.to_app_model ][ self.id ]
|
||||
data[ User.to_app_model ][ self.id ] = User.user_data_full( self.id )
|
||||
end
|
||||
if !data[ User.to_app_model ][ self['created_by_id'] ]
|
||||
data[ User.to_app_model ][ self['created_by_id'] ] = User.user_data_full( self['created_by_id'] )
|
||||
end
|
||||
if !data[ User.to_app_model ][ self['updated_by_id'] ]
|
||||
data[ User.to_app_model ][ self['updated_by_id'] ] = User.user_data_full( self['updated_by_id'] )
|
||||
end
|
||||
data
|
||||
end
|
||||
|
||||
|
|
|
@ -16,8 +16,8 @@ module Zammad
|
|||
# -- all .rb files in that directory are automatically loaded.
|
||||
|
||||
# Custom directories with classes and modules you want to be autoloadable.
|
||||
config.autoload_paths += Dir["#{config.root}/lib/*", "#{config.root}/lib/**/"]
|
||||
# config.autoload_paths += %W(#{config.root}/lib)
|
||||
# config.autoload_paths += Dir["#{config.root}/lib/*", "#{config.root}/lib/**/"]
|
||||
config.autoload_paths += %W(#{config.root}/lib)
|
||||
|
||||
# Only load the plugins named here, in the order given (default is alphabetical).
|
||||
# :all can be used as a placeholder for all plugins not explicitly named.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Zammad::Application.routes.draw do
|
||||
api_path = Rails.configuration.api_path
|
||||
|
||||
match api_path + '/activity_stream', :to => 'activity#activity_stream', :via => :get
|
||||
match api_path + '/activity_stream', :to => 'activity_stream#show', :via => :get
|
||||
|
||||
end
|
41
db/migrate/20130925000001_create_activity_stream.rb
Normal file
41
db/migrate/20130925000001_create_activity_stream.rb
Normal file
|
@ -0,0 +1,41 @@
|
|||
class CreateActivityStream < ActiveRecord::Migration
|
||||
def up
|
||||
|
||||
create_table :activity_streams do |t|
|
||||
t.references :activity_stream_type, :null => false
|
||||
t.references :activity_stream_object, :null => false
|
||||
t.references :role, :null => true
|
||||
t.references :group, :null => true
|
||||
t.column :o_id, :integer, :null => false
|
||||
t.column :created_by_id, :integer, :null => false
|
||||
t.timestamps
|
||||
end
|
||||
add_index :activity_streams, [:o_id]
|
||||
add_index :activity_streams, [:created_by_id]
|
||||
add_index :activity_streams, [:role_id]
|
||||
add_index :activity_streams, [:group_id]
|
||||
add_index :activity_streams, [:created_at]
|
||||
add_index :activity_streams, [:activity_stream_object_id]
|
||||
add_index :activity_streams, [:activity_stream_type_id]
|
||||
|
||||
create_table :activity_stream_types do |t|
|
||||
t.column :name, :string, :limit => 250, :null => false
|
||||
t.timestamps
|
||||
end
|
||||
add_index :activity_stream_types, [:name], :unique => true
|
||||
|
||||
create_table :activity_stream_objects do |t|
|
||||
t.column :name, :string, :limit => 250, :null => false
|
||||
t.column :note, :string, :limit => 250, :null => true
|
||||
t.timestamps
|
||||
end
|
||||
add_index :activity_stream_objects, [:name], :unique => true
|
||||
|
||||
end
|
||||
|
||||
def down
|
||||
drop_table :activity_streams
|
||||
drop_table :activity_stream_objects
|
||||
drop_table :activity_stream_types
|
||||
end
|
||||
end
|
|
@ -4,13 +4,13 @@ module Sessions::Backend::ActivityStream
|
|||
def self.worker( user, worker )
|
||||
cache_key = 'user_' + user.id.to_s + '_activity_stream'
|
||||
if Sessions::CacheIn.expired(cache_key)
|
||||
activity_stream = History.activity_stream( user, 20 )
|
||||
activity_stream = user.activity_stream( 20 )
|
||||
activity_stream_cache = Sessions::CacheIn.get( cache_key, { :re_expire => true } )
|
||||
worker.log 'notice', 'fetch activity_stream - ' + cache_key
|
||||
if activity_stream != activity_stream_cache
|
||||
worker.log 'notify', 'fetch activity_stream changed - ' + cache_key
|
||||
|
||||
activity_stream_full = History.activity_stream_fulldata( user, 20 )
|
||||
activity_stream_full = user.activity_stream( 20, true )
|
||||
Sessions::CacheIn.set( cache_key, activity_stream, { :expires_in => 0.75.minutes } )
|
||||
Sessions::CacheIn.set( cache_key + '_push', activity_stream_full )
|
||||
end
|
||||
|
|
199
test/unit/activity_stream_test.rb
Normal file
199
test/unit/activity_stream_test.rb
Normal file
|
@ -0,0 +1,199 @@
|
|||
# encoding: utf-8
|
||||
require 'test_helper'
|
||||
|
||||
class ActivityStreamTest < ActiveSupport::TestCase
|
||||
test 'ticket+user' do
|
||||
tests = [
|
||||
|
||||
# test 1
|
||||
{
|
||||
:create => {
|
||||
:ticket => {
|
||||
:group_id => Group.lookup( :name => 'Users' ).id,
|
||||
:customer_id => User.lookup( :login => 'nicole.braun@zammad.org' ).id,
|
||||
:owner_id => User.lookup( :login => '-' ).id,
|
||||
:title => 'Unit Test 1 (äöüß)!',
|
||||
:ticket_state_id => Ticket::State.lookup( :name => 'new' ).id,
|
||||
:ticket_priority_id => Ticket::Priority.lookup( :name => '2 normal' ).id,
|
||||
:updated_by_id => User.lookup( :login => 'nicole.braun@zammad.org' ).id,
|
||||
:created_by_id => User.lookup( :login => 'nicole.braun@zammad.org' ).id,
|
||||
},
|
||||
:article => {
|
||||
:updated_by_id => User.lookup( :login => 'nicole.braun@zammad.org' ).id,
|
||||
:created_by_id => User.lookup( :login => 'nicole.braun@zammad.org' ).id,
|
||||
:ticket_article_type_id => Ticket::Article::Type.lookup( :name => 'phone' ).id,
|
||||
:ticket_article_sender_id => Ticket::Article::Sender.lookup( :name => 'Customer' ).id,
|
||||
:from => 'Unit Test <unittest@example.com>',
|
||||
:body => 'Unit Test 123',
|
||||
:internal => false
|
||||
},
|
||||
},
|
||||
:update => {
|
||||
:ticket => {
|
||||
:title => 'Unit Test 1 (äöüß) - update!',
|
||||
:ticket_state_id => Ticket::State.lookup( :name => 'open' ).id,
|
||||
:ticket_priority_id => Ticket::Priority.lookup( :name => '1 low' ).id,
|
||||
},
|
||||
},
|
||||
:check => [
|
||||
{
|
||||
:object => 'Ticket',
|
||||
:type => 'created',
|
||||
},
|
||||
{
|
||||
:object => 'Ticket::Article',
|
||||
:type => 'created',
|
||||
},
|
||||
{
|
||||
:object => 'User',
|
||||
:type => 'updated',
|
||||
:o_id => User.lookup( :login => 'nicole.braun@zammad.org' ).id,
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
tickets = []
|
||||
tests.each { |test|
|
||||
|
||||
ticket = nil
|
||||
article = nil
|
||||
|
||||
# use transaction
|
||||
ActiveRecord::Base.transaction do
|
||||
ticket = Ticket.create( test[:create][:ticket] )
|
||||
test[:check][0][:o_id] = ticket.id
|
||||
test[:check][0][:created_at] = ticket.created_at
|
||||
test[:check][0][:created_by_id] = User.lookup( :login => 'nicole.braun@zammad.org' ).id
|
||||
sleep 2
|
||||
|
||||
test[:create][:article][:ticket_id] = ticket.id
|
||||
article = Ticket::Article.create( test[:create][:article] )
|
||||
test[:check][1][:o_id] = article.id
|
||||
test[:check][1][:created_at] = article.created_at
|
||||
test[:check][1][:created_by_id] = User.lookup( :login => 'nicole.braun@zammad.org' ).id
|
||||
|
||||
assert_equal( ticket.class.to_s, 'Ticket' )
|
||||
assert_equal( article.class.to_s, 'Ticket::Article' )
|
||||
|
||||
# update ticket
|
||||
if test[:update][:ticket]
|
||||
ticket.update_attributes( test[:update][:ticket] )
|
||||
test[:check][2][:o_id] = ticket.id
|
||||
test[:check][2][:created_at] = ticket.created_at
|
||||
test[:check][2][:created_by_id] = User.lookup( :login => 'nicole.braun@zammad.org' ).id
|
||||
end
|
||||
if test[:update][:article]
|
||||
article.update_attributes( test[:update][:article] )
|
||||
end
|
||||
end
|
||||
|
||||
# remember ticket
|
||||
tickets.push ticket
|
||||
|
||||
# check activity_stream
|
||||
activity_stream_check( User.find(1).activity_stream(3), test[:check] )
|
||||
}
|
||||
|
||||
# delete tickets
|
||||
tickets.each { |ticket|
|
||||
ticket_id = ticket.id
|
||||
ticket.destroy
|
||||
found = Ticket.where( :id => ticket_id ).first
|
||||
assert( !found, "Ticket destroyed")
|
||||
}
|
||||
end
|
||||
|
||||
test 'organization' do
|
||||
tests = [
|
||||
|
||||
# test 1
|
||||
{
|
||||
:create => {
|
||||
:organization => {
|
||||
:name => 'some name',
|
||||
:updated_by_id => User.lookup( :login => 'nicole.braun@zammad.org' ).id,
|
||||
:created_by_id => User.lookup( :login => 'nicole.braun@zammad.org' ).id,
|
||||
},
|
||||
},
|
||||
:update1 => {
|
||||
:organization => {
|
||||
:name => 'some name (äöüß)',
|
||||
},
|
||||
},
|
||||
:update2 => {
|
||||
:organization => {
|
||||
:name => 'some name 2 (äöüß)',
|
||||
},
|
||||
},
|
||||
:check => [
|
||||
{
|
||||
:object => 'Organization',
|
||||
:type => 'created',
|
||||
},
|
||||
{
|
||||
:object => 'Organization',
|
||||
:type => 'updated',
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
organizations = []
|
||||
tests.each { |test|
|
||||
|
||||
organization = Organization.create( test[:create][:organization] )
|
||||
test[:check][0][:o_id] = organization.id
|
||||
test[:check][0][:created_at] = organization.created_at
|
||||
test[:check][0][:created_by_id] = User.lookup( :login => 'nicole.braun@zammad.org' ).id
|
||||
sleep 11
|
||||
|
||||
assert_equal( organization.class.to_s, 'Organization' )
|
||||
|
||||
if test[:update1][:organization]
|
||||
organization.update_attributes( test[:update1][:organization] )
|
||||
test[:check][1][:o_id] = organization.id
|
||||
test[:check][1][:updated_at] = organization.updated_at
|
||||
test[:check][1][:created_by_id] = User.lookup( :login => 'nicole.braun@zammad.org' ).id
|
||||
sleep 2
|
||||
end
|
||||
|
||||
if test[:update2][:organization]
|
||||
organization.update_attributes( test[:update2][:organization] )
|
||||
end
|
||||
|
||||
# remember organization
|
||||
organizations.push organization
|
||||
|
||||
# check activity_stream
|
||||
activity_stream_check( User.find(1).activity_stream(2), test[:check] )
|
||||
}
|
||||
|
||||
# delete tickets
|
||||
organizations.each { |organization|
|
||||
organization_id = organization.id
|
||||
organization.destroy
|
||||
found = Organization.where( :id => organization_id ).first
|
||||
assert( !found, "Organization destroyed")
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
def activity_stream_check( activity_stream_list, checks )
|
||||
checks.each { |check_item|
|
||||
# puts '+++++++++++'
|
||||
# puts check_item.inspect
|
||||
match = false
|
||||
activity_stream_list.each { |item|
|
||||
next if match
|
||||
# puts '--------'
|
||||
# puts item.inspect
|
||||
# puts item.object
|
||||
next if item['object'] != check_item[:object]
|
||||
next if item['type'] != check_item[:type]
|
||||
next if item['o_id'] != check_item[:o_id]
|
||||
match = true
|
||||
}
|
||||
assert( match, "activity stream check not matched! #{check_item.inspect}")
|
||||
}
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in a new issue