diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/article_actions.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/article_actions.coffee
index 86526cc86..083402a39 100644
--- a/app/assets/javascripts/app/controllers/ticket_zoom/article_actions.coffee
+++ b/app/assets/javascripts/app/controllers/ticket_zoom/article_actions.coffee
@@ -1,9 +1,11 @@
class App.TicketZoomArticleActions extends App.Controller
events:
- 'click [data-type=public]': 'publicInternal'
- 'click [data-type=internal]': 'publicInternal'
- 'click [data-type=reply]': 'reply'
- 'click [data-type=replyAll]': 'replyAll'
+ 'click [data-type=public]': 'publicInternal'
+ 'click [data-type=internal]': 'publicInternal'
+ 'click [data-type=emailReply]': 'emailReply'
+ 'click [data-type=emailReplyAll]': 'emailReplyAll'
+ 'click [data-type=twitterStatusReply]': 'twitterStatusReply'
+ 'click [data-type=twitterDirectMessageReply]': 'twitterDirectMessageReply'
constructor: ->
super
@@ -68,7 +70,7 @@ class App.TicketZoomArticleActions extends App.Controller
if article.type.name is 'email' || article.type.name is 'phone' || article.type.name is 'web'
actions.push {
name: 'reply'
- type: 'reply'
+ type: 'emailReply'
icon: 'reply'
href: '#'
}
@@ -90,10 +92,18 @@ class App.TicketZoomArticleActions extends App.Controller
if recipients.length > 1
actions.push {
name: 'reply all'
- type: 'replyAll'
+ type: 'emailReplyAll'
icon: 'reply-all'
href: '#'
}
+ if article.type.name is 'twitter status'
+ actions.push {
+ name: 'reply'
+ type: 'twitterStatusReply'
+ icon: 'reply'
+ href: '#'
+ }
+
actions.push {
name: 'split'
type: 'split'
@@ -102,19 +112,83 @@ class App.TicketZoomArticleActions extends App.Controller
}
actions
- replyAll: (e) =>
- @reply(e, true)
-
- reply: (e, all = false) =>
+ twitterStatusReply: (e) =>
e.preventDefault()
# get reference article
article_id = $(e.target).parents('[data-id]').data('id')
- article = App.TicketArticle.fullLocal( article_id )
- type = App.TicketArticleType.find( article.type_id )
- customer = App.User.find( article.created_by_id )
+ article = App.TicketArticle.fullLocal(article_id)
+ type = App.TicketArticleType.find(article.type_id)
+ customer = App.User.find(article.created_by_id)
- @el.closest('.article-add').ScrollTo()
+ @scrollToCompose()
+
+ # empty form
+ articleNew = {
+ to: ''
+ cc: ''
+ body: ''
+ in_reply_to: ''
+ }
+
+ if article.message_id
+ articleNew.in_reply_to = article.message_id
+
+ # get current body
+ body = @el.closest('.ticketZoom').find('.article-add [data-name="body"]').html() || ''
+ articleNew.body = body
+
+ to = customer.accounts['twitter'].username || customer.accounts['twitter'].uid
+ recipient = "@#{to} "
+
+ if !body
+ articleNew.body = recipient
+
+ if body && !body.match("@#{to}")
+ articleNew.body = "#{recipient}#{articleNew.body}"
+
+
+ App.Event.trigger('ui::ticket::setArticleType', { ticket: @ticket, type: type, article: articleNew } )
+
+ twitterDirectMessageReply: (e) =>
+ e.preventDefault()
+
+ # get reference article
+ article_id = $(e.target).parents('[data-id]').data('id')
+ article = App.TicketArticle.fullLocal(article_id)
+ type = App.TicketArticleType.find(article.type_id)
+ customer = App.User.find(article.created_by_id)
+
+ @scrollToCompose()
+
+ # empty form
+ articleNew = {
+ to: ''
+ cc: ''
+ body: ''
+ in_reply_to: ''
+ }
+
+ if article.message_id
+ articleNew.in_reply_to = article.message_id
+
+ articleNew.to = customer.accounts['twitter'].username || customer.accounts['twitter'].uid
+
+ App.Event.trigger('ui::ticket::setArticleType', { ticket: @ticket, type: type, article: articleNew } )
+
+ emailReplyAll: (e) =>
+ @emailReply(e, true)
+
+ emailReply: (e, all = false) =>
+ e.preventDefault()
+
+ # get reference article
+ article_id = $(e.target).parents('[data-id]').data('id')
+ article = App.TicketArticle.fullLocal(article_id)
+ type = App.TicketArticleType.find(article.type_id)
+ customer = App.User.find(article.created_by_id)
+
+ @scrollToCompose()
# empty form
articleNew = {
@@ -129,19 +203,7 @@ class App.TicketZoomArticleActions extends App.Controller
if article.message_id
articleNew.in_reply_to = article.message_id
- if type.name is 'twitter status'
-
- # set to in body
- to = customer.accounts['twitter'].username || customer.accounts['twitter'].uid
- articleNew.body = '@' + to
-
- else if type.name is 'twitter direct-message'
-
- # show to
- to = customer.accounts['twitter'].username || customer.accounts['twitter'].uid
- articleNew.to = to
-
- else if type.name is 'email' || type.name is 'phone' || type.name is 'web'
+ if type.name is 'email' || type.name is 'phone' || type.name is 'web'
if article.sender.name is 'Agent'
articleNew.to = article.to
@@ -198,10 +260,10 @@ class App.TicketZoomArticleActions extends App.Controller
if selectedText
# clean selection
- selectedText = App.Utils.textCleanup( selectedText )
+ selectedText = App.Utils.textCleanup(selectedText)
# convert to html
- selectedText = App.Utils.text2html( selectedText )
+ selectedText = App.Utils.text2html(selectedText)
if selectedText
selectedText = "
"
@@ -210,4 +272,10 @@ class App.TicketZoomArticleActions extends App.Controller
articleNew.body = body
+ type = App.TicketArticleType.findByAttribute(name:'email')
+
App.Event.trigger('ui::ticket::setArticleType', { ticket: @ticket, type: type, article: articleNew } )
+
+ scrollToCompose: =>
+ @el.closest('.content').find('.article-add').ScrollTo()
+
diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee
index 9ccba0fd3..92a05b5ff 100644
--- a/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee
+++ b/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee
@@ -84,7 +84,6 @@ class App.TicketZoomArticleNew extends App.Controller
# set article type and expand text area
@bind('ui::ticket::setArticleType', (data) =>
return if data.ticket.id isnt @ticket_id
- #@setArticleType(data.type.name)
@openTextarea(null, true)
for key, value of data.article
@@ -94,7 +93,7 @@ class App.TicketZoomArticleNew extends App.Controller
@$('[name="' + key + '"]').val(value)
# preselect article type
- @setArticleType('email')
+ @setArticleType(data.type.name)
)
# reset new article screen
diff --git a/app/models/avatar.rb b/app/models/avatar.rb
index 42630c8e0..c4e6a8af6 100644
--- a/app/models/avatar.rb
+++ b/app/models/avatar.rb
@@ -8,12 +8,11 @@ class Avatar < ApplicationModel
add an avatar based on auto detection (email address)
Avatar.auto_detection(
- :object => 'User',
- :o_id => user.id,
- :url => 'somebody@example.com',
- :source => 'web',
- :updated_by_id => 1,
- :created_by_id => 1,
+ object: 'User',
+ o_id: user.id,
+ url: 'somebody@example.com',
+ updated_by_id: 1,
+ created_by_id: 1,
)
=end
@@ -41,20 +40,20 @@ add an avatar based on auto detection (email address)
add a avatar
Avatar.add(
- :object => 'User',
- :o_id => user.id,
- :default => true,
- :full => {
- :content => '...',
- :mime_type => 'image/png',
+ object: 'User',
+ o_id: user.id,
+ default: true,
+ full: {
+ content: '...',
+ mime_type: 'image/png',
},
- :resize => {
- :content => '...',
- :mime_type => 'image/png',
+ resize: {
+ content: '...',
+ mime_type: 'image/png',
},
- :source => 'web',
- :updated_by_id => 1,
- :created_by_id => 1,
+ source: 'web',
+ updated_by_id: 1,
+ created_by_id: 1,
)
=end
@@ -214,7 +213,7 @@ add a avatar
set avatars as default
- Avatar.set_default( 'User', 123, avatar_id )
+ Avatar.set_default('User', 123, avatar_id)
=end
@@ -238,12 +237,12 @@ set avatars as default
remove all avatars of an object
- Avatar.remove( 'User', 123 )
+ Avatar.remove('User', 123)
=end
- def self.remove( object_name, o_id )
- object_id = ObjectLookup.by_name( object_name )
+ def self.remove(object_name, o_id)
+ object_id = ObjectLookup.by_name(object_name)
Avatar.where(
object_lookup_id: object_id,
o_id: o_id,
@@ -264,12 +263,12 @@ remove all avatars of an object
remove one avatars of an object
- Avatar.remove_one( 'User', 123, avatar_id )
+ Avatar.remove_one('User', 123, avatar_id)
=end
- def self.remove_one( object_name, o_id, avatar_id )
- object_id = ObjectLookup.by_name( object_name )
+ def self.remove_one(object_name, o_id, avatar_id)
+ object_id = ObjectLookup.by_name(object_name)
Avatar.where(
object_lookup_id: object_id,
o_id: o_id,
@@ -281,16 +280,16 @@ remove one avatars of an object
return all avatars of an user
- avatars = Avatar.list( 'User', 123 )
+ avatars = Avatar.list('User', 123)
=end
def self.list(object_name, o_id)
- object_id = ObjectLookup.by_name( object_name )
+ object_id = ObjectLookup.by_name(object_name)
avatars = Avatar.where(
object_lookup_id: object_id,
o_id: o_id,
- ).order( 'initial DESC, deletable ASC, created_at ASC, id DESC' )
+ ).order('initial DESC, deletable ASC, created_at ASC, id DESC')
# add initial avatar
add_init_avatar(object_id, o_id)
@@ -300,7 +299,7 @@ return all avatars of an user
data = avatar.attributes
if avatar.store_resize_id
file = Store.find(avatar.store_resize_id)
- data['content'] = "data:#{file.preferences['Mime-Type']};base64,#{Base64.strict_encode64( file.content )}"
+ data['content'] = "data:#{file.preferences['Mime-Type']};base64,#{Base64.strict_encode64(file.content)}"
end
avatar_list.push data
end
@@ -311,7 +310,7 @@ return all avatars of an user
get default avatar image of user by hash
- store = Avatar.get_by_hash( hash )
+ store = Avatar.get_by_hash(hash)
returns:
@@ -331,7 +330,7 @@ returns:
get default avatar of user by user id
- avatar = Avatar.get_default( 'User', user_id )
+ avatar = Avatar.get_default('User', user_id)
returns:
@@ -340,7 +339,7 @@ returns:
=end
def self.get_default(object_name, o_id)
- object_id = ObjectLookup.by_name( object_name )
+ object_id = ObjectLookup.by_name(object_name)
Avatar.find_by(
object_lookup_id: object_id,
o_id: o_id,
@@ -352,7 +351,7 @@ returns:
avatars = Avatar.where(
object_lookup_id: object_id,
o_id: o_id,
- ).order( 'created_at ASC, id DESC' )
+ ).order('created_at ASC, id DESC')
avatars.each do |avatar|
next if avatar.id == avatar_id
avatar.default = false
diff --git a/app/models/observer/ticket/article/communicate_twitter.rb b/app/models/observer/ticket/article/communicate_twitter.rb
index 68eba6067..1c2e7b29a 100644
--- a/app/models/observer/ticket/article/communicate_twitter.rb
+++ b/app/models/observer/ticket/article/communicate_twitter.rb
@@ -1,8 +1,5 @@
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
-# http://stem.ps/rails/2015/01/25/ruby-gotcha-toplevel-constant-referenced-by.html
-require 'channel/driver/twitter'
-
class Observer::Ticket::Article::CommunicateTwitter < ActiveRecord::Observer
observe 'ticket::_article'
@@ -28,9 +25,26 @@ class Observer::Ticket::Article::CommunicateTwitter < ActiveRecord::Observer
tweet = channel.deliver(
type: type['name'],
to: record.to,
- body: record.body,
+ body: record.body.html2text,
in_reply_to: record.in_reply_to
)
+
+ # fill article with tweet info
+ record.from = tweet.user.screen_name
+ if tweet.user_mentions
+ to = ''
+ twitter_mention_ids = []
+ tweet.user_mentions.each {|user|
+ if to != ''
+ to += ' '
+ end
+ to += "@#{user.screen_name}"
+ twitter_mention_ids.push user.id
+ }
+ record.to = to
+ record.preferences[:twitter_mention_ids] = twitter_mention_ids
+ end
+
record.message_id = tweet.id
record.save
end
diff --git a/lib/tweet.rb b/lib/tweet.rb
index 289546091..8b8c91293 100644
--- a/lib/tweet.rb
+++ b/lib/tweet.rb
@@ -68,6 +68,24 @@ class Tweet
user = User.create(user_data)
end
+ if user_data[:image_source]
+ avatar = Avatar.add(
+ object: 'User',
+ o_id: user.id,
+ url: user_data[:image_source],
+ source: 'twitter',
+ deletable: true,
+ updated_by_id: user.id,
+ created_by_id: user.id,
+ )
+
+ # update user link
+ if avatar && user.image != avatar.store_hash
+ user.image = avatar.store_hash
+ user.save
+ end
+ end
+
# create or update authorization
auth_data = {
uid: tweet_user.id,
@@ -81,8 +99,6 @@ class Tweet
Authorization.create(auth_data)
end
- UserInfo.current_user_id = user.id
-
user
end
@@ -112,6 +128,8 @@ class Tweet
end
end
+ UserInfo.current_user_id = user.id
+
Ticket.create(
customer_id: user.id,
title: "#{tweet.text[0, 37]}...",
@@ -148,12 +166,14 @@ class Tweet
from = tweet.sender.screen_name
elsif tweet.class == Twitter::Tweet
article_type = 'twitter status'
- from = tweet.in_reply_to_screen_name
+ from = tweet.user.screen_name
in_reply_to = tweet.in_reply_to_status_id
else
fail "Unknown tweet type '#{tweet.class}'"
end
+ UserInfo.current_user_id = user.id
+
Ticket::Article.create(
from: from,
to: to,
diff --git a/test/browser/agent_ticket_actions_level5_test.rb b/test/browser/agent_ticket_actions_level5_test.rb
index 06a852e3e..c8a1109c6 100644
--- a/test/browser/agent_ticket_actions_level5_test.rb
+++ b/test/browser/agent_ticket_actions_level5_test.rb
@@ -243,7 +243,7 @@ class AgentTicketActionLevel5Test < TestCase
# execute reply
click(
- css: '.active [data-type="reply"]',
+ css: '.active [data-type="emailReply"]',
)
# check if signature exists
@@ -267,7 +267,7 @@ class AgentTicketActionLevel5Test < TestCase
# execute reply
sleep 5 # time to recognice form changes
click(
- css: '.active [data-type="reply"]',
+ css: '.active [data-type="emailReply"]',
)
# check if signature exists
diff --git a/test/browser/agent_ticket_actions_level7_test.rb b/test/browser/agent_ticket_actions_level7_test.rb
index 905206131..d41d9625f 100644
--- a/test/browser/agent_ticket_actions_level7_test.rb
+++ b/test/browser/agent_ticket_actions_level7_test.rb
@@ -35,11 +35,11 @@ class AgentTicketActionLevel7Test < TestCase
# scroll to reply - needed for chrome
scroll_to(
position: 'botton',
- css: '.content.active [data-type="reply"]',
+ css: '.content.active [data-type="emailReply"]',
)
# click reply
- click( css: '.content.active [data-type="reply"]' )
+ click( css: '.content.active [data-type="emailReply"]' )
# check body
watch_for(
@@ -58,11 +58,11 @@ class AgentTicketActionLevel7Test < TestCase
# scroll to reply - needed for chrome
scroll_to(
position: 'botton',
- css: '.content.active [data-type="reply"]',
+ css: '.content.active [data-type="emailReply"]',
)
# click reply
- click( css: '.content.active [data-type="reply"]' )
+ click( css: '.content.active [data-type="emailReply"]' )
# check body
watch_for(