Merge branch 'develop' into private-rl_2278_email_display_name
This commit is contained in:
commit
9fc841d7a1
20 changed files with 244 additions and 88 deletions
|
@ -1,7 +1,7 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
## [2.7.0](https://github.com/zammad/zammad/tree/2.7.0) (2018-xx-xx)
|
## [2.8.0](https://github.com/zammad/zammad/tree/2.8.0) (2018-xx-xx)
|
||||||
[Full Changelog](https://github.com/zammad/zammad/compare/2.6.0...2.7.0)
|
[Full Changelog](https://github.com/zammad/zammad/compare/2.7.0...2.8.0)
|
||||||
|
|
||||||
**Implemented enhancements:**
|
**Implemented enhancements:**
|
||||||
|
|
||||||
|
@ -13,4 +13,3 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
2.7.x
|
2.8.x
|
||||||
|
|
|
@ -364,6 +364,11 @@ class App.UiElement.ticket_perform_action
|
||||||
object: 'Ticket'
|
object: 'Ticket'
|
||||||
display: 'Ticket'
|
display: 'Ticket'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
prefix: 'article'
|
||||||
|
object: 'TicketArticle'
|
||||||
|
display: 'Article'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
prefix: 'user'
|
prefix: 'user'
|
||||||
object: 'User'
|
object: 'User'
|
||||||
|
|
|
@ -193,7 +193,7 @@ class Graph extends App.ControllerContent
|
||||||
else if @params.timeRange is 'week'
|
else if @params.timeRange is 'week'
|
||||||
xaxis = [[0, 'Mon'], [1, 'Tue'], [2, 'Wed'], [3, 'Thr'], [4, 'Fri'], [5, 'Sat'], [6, 'Sun'] ]
|
xaxis = [[0, 'Mon'], [1, 'Tue'], [2, 'Wed'], [3, 'Thr'], [4, 'Fri'], [5, 'Sat'], [6, 'Sun'] ]
|
||||||
else
|
else
|
||||||
xaxis = [[0, 'Jan'], [1, 'Feb'], [2, 'Mar'], [3, 'Apr'], [4, 'Mai'], [5, 'Jun'], [6, 'Jul'], [7, 'Aug'], [8, 'Sep'], [9, 'Oct'], [10, 'Nov'], [11, 'Dec']]
|
xaxis = [[0, 'Jan'], [1, 'Feb'], [2, 'Mar'], [3, 'Apr'], [4, 'May'], [5, 'Jun'], [6, 'Jul'], [7, 'Aug'], [8, 'Sep'], [9, 'Oct'], [10, 'Nov'], [11, 'Dec']]
|
||||||
|
|
||||||
dataPlot = []
|
dataPlot = []
|
||||||
for key, value of data
|
for key, value of data
|
||||||
|
@ -489,7 +489,7 @@ class TimePicker extends App.Controller
|
||||||
value: 4,
|
value: 4,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
display: 'Mai'
|
display: 'May'
|
||||||
value: 5,
|
value: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -61,7 +61,7 @@ class Index extends App.ControllerSubContent
|
||||||
value: 4,
|
value: 4,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
display: 'Mai'
|
display: 'May'
|
||||||
value: 5,
|
value: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -1028,7 +1028,7 @@ class App.Utils
|
||||||
|
|
||||||
# the article we are replying to is an incoming call
|
# the article we are replying to is an incoming call
|
||||||
else if article.from?.match(/@/)
|
else if article.from?.match(/@/)
|
||||||
articleNew.to = article.from
|
articleNew.to = App.Utils.parseAddressListLocal(article.from).join(', ')
|
||||||
|
|
||||||
# if sender is customer but in article.from is no email, try to get
|
# if sender is customer but in article.from is no email, try to get
|
||||||
# customers email via customer user
|
# customers email via customer user
|
||||||
|
@ -1146,7 +1146,7 @@ class App.Utils
|
||||||
|
|
||||||
html.find('img').each( (index) ->
|
html.find('img').each( (index) ->
|
||||||
src = $(@).attr('src')
|
src = $(@).attr('src')
|
||||||
if !src.match(/^data:/i)
|
if !src.match(/^(data|cid):/i) # <img src="cid: ..."> may mean broken emails (see issue #2305)
|
||||||
base64 = App.Utils._htmlImage2DataUrl(@)
|
base64 = App.Utils._htmlImage2DataUrl(@)
|
||||||
$(@).attr('src', base64)
|
$(@).attr('src', base64)
|
||||||
)
|
)
|
||||||
|
|
|
@ -105,6 +105,7 @@ class App.User extends App.Model
|
||||||
placement: placement
|
placement: placement
|
||||||
vip: vip
|
vip: vip
|
||||||
url: @imageUrl()
|
url: @imageUrl()
|
||||||
|
initials: @initials()
|
||||||
|
|
||||||
isOutOfOffice: ->
|
isOutOfOffice: ->
|
||||||
return false if @out_of_office isnt true
|
return false if @out_of_office isnt true
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
<span class="avatar <%- @cssClass %>" style="background-image: url(<%- @url %>)"<%- @placement %><%- @data %>>
|
<span class="avatar <%- @cssClass %>" style="background-image: url(<%- @url %>)"<%- @placement %><%- @data %> data-initials="<%- @initials %>">
|
||||||
<%- @Icon('crown') if @vip %>
|
<%- @Icon('crown') if @vip %>
|
||||||
</span>
|
</span>
|
|
@ -201,6 +201,35 @@ th.js-tableHead:not([data-column-key="icon"]) {
|
||||||
|
|
||||||
.avatar {
|
.avatar {
|
||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
|
|
||||||
|
&:not(.avatar--unique) {
|
||||||
|
&:before {
|
||||||
|
content: attr(data-initials);
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.size-30:before {
|
||||||
|
font-size: 10px;
|
||||||
|
line-height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.size-50:before {
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 52px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.size-80:before {
|
||||||
|
font-size: 26px;
|
||||||
|
line-height: 84px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ class Observer::Ticket::Article::CommunicateSms::BackgroundJob
|
||||||
def perform
|
def perform
|
||||||
article = Ticket::Article.find(@article_id)
|
article = Ticket::Article.find(@article_id)
|
||||||
|
|
||||||
|
# set retry count
|
||||||
article.preferences['delivery_retry'] ||= 0
|
article.preferences['delivery_retry'] ||= 0
|
||||||
article.preferences['delivery_retry'] += 1
|
article.preferences['delivery_retry'] += 1
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,8 @@ class Observer::Ticket::Article::CommunicateTelegram::BackgroundJob
|
||||||
article = Ticket::Article.find(@article_id)
|
article = Ticket::Article.find(@article_id)
|
||||||
|
|
||||||
# set retry count
|
# set retry count
|
||||||
record.preferences['delivery_retry'] ||= 0
|
article.preferences['delivery_retry'] ||= 0
|
||||||
record.preferences['delivery_retry'] += 1
|
article.preferences['delivery_retry'] += 1
|
||||||
|
|
||||||
ticket = Ticket.lookup(id: article.ticket_id)
|
ticket = Ticket.lookup(id: article.ticket_id)
|
||||||
log_error(article, "Can't find ticket.preferences for Ticket.find(#{article.ticket_id})") if !ticket.preferences
|
log_error(article, "Can't find ticket.preferences for Ticket.find(#{article.ticket_id})") if !ticket.preferences
|
||||||
|
|
|
@ -7,8 +7,8 @@ class Observer::Ticket::Article::CommunicateTwitter::BackgroundJob
|
||||||
article = Ticket::Article.find(@article_id)
|
article = Ticket::Article.find(@article_id)
|
||||||
|
|
||||||
# set retry count
|
# set retry count
|
||||||
record.preferences['delivery_retry'] ||= 0
|
article.preferences['delivery_retry'] ||= 0
|
||||||
record.preferences['delivery_retry'] += 1
|
article.preferences['delivery_retry'] += 1
|
||||||
|
|
||||||
ticket = Ticket.lookup(id: article.ticket_id)
|
ticket = Ticket.lookup(id: article.ticket_id)
|
||||||
log_error(article, "Can't find ticket.preferences for Ticket.find(#{article.ticket_id})") if !ticket.preferences
|
log_error(article, "Can't find ticket.preferences for Ticket.find(#{article.ticket_id})") if !ticket.preferences
|
||||||
|
@ -62,7 +62,7 @@ class Observer::Ticket::Article::CommunicateTwitter::BackgroundJob
|
||||||
mention_ids.push user.id
|
mention_ids.push user.id
|
||||||
end
|
end
|
||||||
article.to = to
|
article.to = to
|
||||||
article.preferences['twitter'] = {
|
article.preferences['twitter'] = TweetBase.preferences_cleanup(
|
||||||
mention_ids: mention_ids,
|
mention_ids: mention_ids,
|
||||||
geo: tweet.geo,
|
geo: tweet.geo,
|
||||||
retweeted: tweet.retweeted?,
|
retweeted: tweet.retweeted?,
|
||||||
|
@ -74,7 +74,7 @@ class Observer::Ticket::Article::CommunicateTwitter::BackgroundJob
|
||||||
favorited: tweet.favorited?,
|
favorited: tweet.favorited?,
|
||||||
truncated: tweet.truncated?,
|
truncated: tweet.truncated?,
|
||||||
created_at: tweet.created_at,
|
created_at: tweet.created_at,
|
||||||
}
|
)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
raise "Unknown tweet type '#{tweet.class}'"
|
raise "Unknown tweet type '#{tweet.class}'"
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
class FixedTwitterTicketArticlePreferences4 < ActiveRecord::Migration[5.0]
|
|
||||||
def up
|
|
||||||
|
|
||||||
# return if it's a new setup
|
|
||||||
return if !Setting.find_by(name: 'system_init_done')
|
|
||||||
|
|
||||||
# find article preferences with Twitter::NullObject and replace it with nill to prevent elasticsearch index issue
|
|
||||||
article_type_ids = Ticket::Article::Type.where(name: ['twitter status', 'twitter direct-message']).pluck(:id)
|
|
||||||
article_ids = Ticket::Article.where(type_id: article_type_ids).pluck(:id)
|
|
||||||
article_ids.each do |article_id|
|
|
||||||
article = Ticket::Article.find(article_id)
|
|
||||||
next if !article.preferences
|
|
||||||
|
|
||||||
changed = false
|
|
||||||
article.preferences.each_value do |value|
|
|
||||||
next if value.class != ActiveSupport::HashWithIndifferentAccess
|
|
||||||
|
|
||||||
value.each do |sub_key, sub_level|
|
|
||||||
if sub_level.class == NilClass
|
|
||||||
value[sub_key] = nil
|
|
||||||
next
|
|
||||||
end
|
|
||||||
if sub_level.class == Twitter::Place
|
|
||||||
value[sub_key] = sub_level.attrs
|
|
||||||
changed = true
|
|
||||||
next
|
|
||||||
end
|
|
||||||
next if sub_level.class != Twitter::NullObject
|
|
||||||
|
|
||||||
value[sub_key] = nil
|
|
||||||
changed = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
next if !changed
|
|
||||||
|
|
||||||
article.save!
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,4 +1,4 @@
|
||||||
class FixedTwitterTicketArticlePreferences5 < ActiveRecord::Migration[5.0]
|
class FixedTwitterTicketArticlePreferences7 < ActiveRecord::Migration[5.0]
|
||||||
def up
|
def up
|
||||||
|
|
||||||
# return if it's a new setup
|
# return if it's a new setup
|
||||||
|
@ -21,7 +21,7 @@ class FixedTwitterTicketArticlePreferences5 < ActiveRecord::Migration[5.0]
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
if sub_level.class == Twitter::Place || sub_level.class == Twitter::Geo
|
if sub_level.class == Twitter::Place || sub_level.class == Twitter::Geo
|
||||||
value[sub_key] = sub_level.attrs
|
value[sub_key] = sub_level.to_h
|
||||||
changed = true
|
changed = true
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
|
@ -31,6 +31,17 @@ class FixedTwitterTicketArticlePreferences5 < ActiveRecord::Migration[5.0]
|
||||||
changed = true
|
changed = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if article.preferences[:twitter]&.key?(:geo) && article.preferences[:twitter][:geo].nil?
|
||||||
|
article.preferences[:twitter][:geo] = {}
|
||||||
|
changed = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if article.preferences[:twitter]&.key?(:place) && article.preferences[:twitter][:place].nil?
|
||||||
|
article.preferences[:twitter][:place] = {}
|
||||||
|
changed = true
|
||||||
|
end
|
||||||
|
|
||||||
next if !changed
|
next if !changed
|
||||||
|
|
||||||
article.save!
|
article.save!
|
|
@ -6,7 +6,14 @@ class CtiGenericApi2 < ActiveRecord::Migration[5.1]
|
||||||
return if !column_exists?(:cti_logs, :initialized_at)
|
return if !column_exists?(:cti_logs, :initialized_at)
|
||||||
return if column_exists?(:cti_logs, :initialized_at_cleanup)
|
return if column_exists?(:cti_logs, :initialized_at_cleanup)
|
||||||
|
|
||||||
add_column :cti_logs, :initialized_at_cleanup, :timestamp, limit: 3, null: true
|
if ActiveRecord::Base.connection_config[:adapter] == 'mysql2'
|
||||||
|
# disable the MySQL strict_mode for the current connection
|
||||||
|
execute("SET sql_mode = ''")
|
||||||
|
add_column :cti_logs, :initialized_at_cleanup, :timestamp, limit: 3, null: true, default: '0000-00-00 00:00:00'
|
||||||
|
else
|
||||||
|
add_column :cti_logs, :initialized_at_cleanup, :timestamp, limit: 3, null: true
|
||||||
|
end
|
||||||
|
|
||||||
Cti::Log.connection.schema_cache.clear!
|
Cti::Log.connection.schema_cache.clear!
|
||||||
Cti::Log.reset_column_information
|
Cti::Log.reset_column_information
|
||||||
|
|
||||||
|
|
|
@ -208,7 +208,7 @@ class TweetBase
|
||||||
end
|
end
|
||||||
|
|
||||||
article_preferences = {
|
article_preferences = {
|
||||||
twitter: twitter_preferences,
|
twitter: self.class.preferences_cleanup(twitter_preferences),
|
||||||
links: [
|
links: [
|
||||||
{
|
{
|
||||||
url: "https://twitter.com/statuses/#{tweet.id}",
|
url: "https://twitter.com/statuses/#{tweet.id}",
|
||||||
|
@ -228,7 +228,7 @@ class TweetBase
|
||||||
type_id: Ticket::Article::Type.find_by(name: article_type).id,
|
type_id: Ticket::Article::Type.find_by(name: article_type).id,
|
||||||
sender_id: Ticket::Article::Sender.find_by(name: 'Customer').id,
|
sender_id: Ticket::Article::Sender.find_by(name: 'Customer').id,
|
||||||
internal: false,
|
internal: false,
|
||||||
preferences: preferences_cleanup(article_preferences),
|
preferences: article_preferences,
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -366,10 +366,50 @@ class TweetBase
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
def preferences_cleanup(preferences)
|
=begin
|
||||||
|
|
||||||
|
replace Twitter::Place and Twitter::Geo as hash and replace Twitter::NullObject with nil
|
||||||
|
|
||||||
|
preferences = TweetBase.preferences_cleanup(
|
||||||
|
twitter: twitter_preferences,
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
url: 'https://twitter.com/statuses/123',
|
||||||
|
target: '_blank',
|
||||||
|
name: 'on Twitter',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
preferences = {
|
||||||
|
twitter: TweetBase.preferences_cleanup(twitter_preferences),
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
url: 'https://twitter.com/statuses/123',
|
||||||
|
target: '_blank',
|
||||||
|
name: 'on Twitter',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def self.preferences_cleanup(preferences)
|
||||||
|
|
||||||
# replace Twitter::NullObject with nill to prevent elasticsearch index issue
|
# replace Twitter::NullObject with nill to prevent elasticsearch index issue
|
||||||
preferences.each_value do |value|
|
preferences.each do |key, value|
|
||||||
|
|
||||||
|
if value.class == Twitter::Place || value.class == Twitter::Geo
|
||||||
|
preferences[key] = value.to_h
|
||||||
|
next
|
||||||
|
end
|
||||||
|
if value.class == Twitter::NullObject
|
||||||
|
preferences[key] = nil
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
next if !value.is_a?(Hash)
|
next if !value.is_a?(Hash)
|
||||||
|
|
||||||
value.each do |sub_key, sub_level|
|
value.each do |sub_key, sub_level|
|
||||||
|
@ -378,7 +418,7 @@ class TweetBase
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
if sub_level.class == Twitter::Place || sub_level.class == Twitter::Geo
|
if sub_level.class == Twitter::Place || sub_level.class == Twitter::Geo
|
||||||
value[sub_key] = sub_level.attrs
|
value[sub_key] = sub_level.to_h
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
next if sub_level.class != Twitter::NullObject
|
next if sub_level.class != Twitter::NullObject
|
||||||
|
@ -386,6 +426,23 @@ class TweetBase
|
||||||
value[sub_key] = nil
|
value[sub_key] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if preferences[:twitter]
|
||||||
|
if preferences[:twitter][:geo].blank?
|
||||||
|
preferences[:twitter][:geo] = {}
|
||||||
|
end
|
||||||
|
if preferences[:twitter][:place].blank?
|
||||||
|
preferences[:twitter][:place] = {}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if preferences[:geo].blank?
|
||||||
|
preferences[:geo] = {}
|
||||||
|
end
|
||||||
|
if preferences[:place].blank?
|
||||||
|
preferences[:place] = {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
preferences
|
preferences
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2944,7 +2944,7 @@ test('check getRecipientArticle format', function() {
|
||||||
sender: {
|
sender: {
|
||||||
name: 'Customer',
|
name: 'Customer',
|
||||||
},
|
},
|
||||||
from: article_customer.email,
|
from: 'article lastname <article_customer@example.com>',
|
||||||
to: 'some group',
|
to: 'some group',
|
||||||
message_id: 'message_id22',
|
message_id: 'message_id22',
|
||||||
created_by: {
|
created_by: {
|
||||||
|
@ -3079,6 +3079,11 @@ test("htmlImage2DataUrl", function() {
|
||||||
result = App.Utils.htmlImage2DataUrl(source)
|
result = App.Utils.htmlImage2DataUrl(source)
|
||||||
equal(result, should, source)
|
equal(result, should, source)
|
||||||
|
|
||||||
|
source = '<img src="cid:1234">some test'
|
||||||
|
should = '<img src="cid:1234">some test'
|
||||||
|
result = App.Utils.htmlImage2DataUrl(source)
|
||||||
|
equal(result, should, source)
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
source = '<img src="/assets/images/avatar-bg.png">some test'
|
source = '<img src="/assets/images/avatar-bg.png">some test'
|
||||||
|
|
|
@ -13,7 +13,7 @@ class AdminCalendarSlaTest < TestCase
|
||||||
calendar_name = "ZZZ some calendar #{rand(99_999_999)}"
|
calendar_name = "ZZZ some calendar #{rand(99_999_999)}"
|
||||||
sla_name = "ZZZ some sla #{rand(99_999_999)}"
|
sla_name = "ZZZ some sla #{rand(99_999_999)}"
|
||||||
timezone = 'Europe/Berlin'
|
timezone = 'Europe/Berlin'
|
||||||
timezone_verify = 'Europe/Berlin (GMT+2)'
|
timezone_verify = "Europe/Berlin\s\\(GMT\\+(2|1)\\)"
|
||||||
calendar_create(
|
calendar_create(
|
||||||
data: {
|
data: {
|
||||||
name: calendar_name,
|
name: calendar_name,
|
||||||
|
@ -66,7 +66,7 @@ class AdminCalendarSlaTest < TestCase
|
||||||
)
|
)
|
||||||
watch_for(
|
watch_for(
|
||||||
css: '.content.active .modal input.js-input',
|
css: '.content.active .modal input.js-input',
|
||||||
value: Regexp.quote(timezone_verify),
|
value: timezone_verify,
|
||||||
timeout: 4,
|
timeout: 4,
|
||||||
)
|
)
|
||||||
modal_close()
|
modal_close()
|
||||||
|
|
|
@ -991,7 +991,7 @@ html.html2html_strict
|
||||||
html = '<img style="width: 181px; height: 125px" src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/...">'
|
html = '<img style="width: 181px; height: 125px" src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/...">'
|
||||||
(body, attachments_inline) = HtmlSanitizer.replace_inline_images(html)
|
(body, attachments_inline) = HtmlSanitizer.replace_inline_images(html)
|
||||||
assert_match(/<img style="width: 181px; height: 125px" src="cid:.+?">/, body)
|
assert_match(/<img style="width: 181px; height: 125px" src="cid:.+?">/, body)
|
||||||
assert(1, attachments_inline.count)
|
assert_equal(1, attachments_inline.count)
|
||||||
assert_equal('image1.jpeg', attachments_inline[0][:filename])
|
assert_equal('image1.jpeg', attachments_inline[0][:filename])
|
||||||
assert_equal('image/jpeg', attachments_inline[0][:preferences]['Content-Type'])
|
assert_equal('image/jpeg', attachments_inline[0][:preferences]['Content-Type'])
|
||||||
assert_match(/@#{Setting.get('fqdn')}/, attachments_inline[0][:preferences]['Content-ID'])
|
assert_match(/@#{Setting.get('fqdn')}/, attachments_inline[0][:preferences]['Content-ID'])
|
||||||
|
@ -1000,7 +1000,7 @@ html.html2html_strict
|
||||||
html = '<img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/..." style="width: 181px; height: 125px" alt="abc">'
|
html = '<img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/..." style="width: 181px; height: 125px" alt="abc">'
|
||||||
(body, attachments_inline) = HtmlSanitizer.replace_inline_images(html)
|
(body, attachments_inline) = HtmlSanitizer.replace_inline_images(html)
|
||||||
assert_match(/<img src="cid:.+?" style="width: 181px; height: 125px" alt="abc">/, body)
|
assert_match(/<img src="cid:.+?" style="width: 181px; height: 125px" alt="abc">/, body)
|
||||||
assert(1, attachments_inline.count)
|
assert_equal(1, attachments_inline.count)
|
||||||
assert_equal('image1.jpeg', attachments_inline[0][:filename])
|
assert_equal('image1.jpeg', attachments_inline[0][:filename])
|
||||||
assert_equal('image/jpeg', attachments_inline[0][:preferences]['Content-Type'])
|
assert_equal('image/jpeg', attachments_inline[0][:preferences]['Content-Type'])
|
||||||
assert_match(/@#{Setting.get('fqdn')}/, attachments_inline[0][:preferences]['Content-ID'])
|
assert_match(/@#{Setting.get('fqdn')}/, attachments_inline[0][:preferences]['Content-ID'])
|
||||||
|
@ -1009,7 +1009,7 @@ html.html2html_strict
|
||||||
html = '<img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/..." style="width: 181px; height: 125px" alt="abc"><invalid what ever'
|
html = '<img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/..." style="width: 181px; height: 125px" alt="abc"><invalid what ever'
|
||||||
(body, attachments_inline) = HtmlSanitizer.replace_inline_images(html)
|
(body, attachments_inline) = HtmlSanitizer.replace_inline_images(html)
|
||||||
assert_match(/<img src="cid:.+?" style="width: 181px; height: 125px" alt="abc">/, body)
|
assert_match(/<img src="cid:.+?" style="width: 181px; height: 125px" alt="abc">/, body)
|
||||||
assert(1, attachments_inline.count)
|
assert_equal(1, attachments_inline.count)
|
||||||
assert_equal('image1.jpeg', attachments_inline[0][:filename])
|
assert_equal('image1.jpeg', attachments_inline[0][:filename])
|
||||||
assert_equal('image/jpeg', attachments_inline[0][:preferences]['Content-Type'])
|
assert_equal('image/jpeg', attachments_inline[0][:preferences]['Content-Type'])
|
||||||
assert_match(/@#{Setting.get('fqdn')}/, attachments_inline[0][:preferences]['Content-ID'])
|
assert_match(/@#{Setting.get('fqdn')}/, attachments_inline[0][:preferences]['Content-ID'])
|
||||||
|
@ -1018,12 +1018,12 @@ html.html2html_strict
|
||||||
html = '<img src="/some_one.png" style="width: 181px; height: 125px" alt="abc">'
|
html = '<img src="/some_one.png" style="width: 181px; height: 125px" alt="abc">'
|
||||||
(body, attachments_inline) = HtmlSanitizer.replace_inline_images(html)
|
(body, attachments_inline) = HtmlSanitizer.replace_inline_images(html)
|
||||||
assert_match(/<img src="\/some_one.png" style="width: 181px; height: 125px" alt="abc">/, body)
|
assert_match(/<img src="\/some_one.png" style="width: 181px; height: 125px" alt="abc">/, body)
|
||||||
assert(0, attachments_inline.count)
|
assert_equal(0, attachments_inline.count)
|
||||||
|
|
||||||
html = '<div><img style="width: 181px; height: 125px" src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/..."><p>123</p><img style="width: 181px; height: 125px" src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/..."></div>'
|
html = '<div><img style="width: 181px; height: 125px" src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/..."><p>123</p><img style="width: 181px; height: 125px" src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/..."></div>'
|
||||||
(body, attachments_inline) = HtmlSanitizer.replace_inline_images(html)
|
(body, attachments_inline) = HtmlSanitizer.replace_inline_images(html)
|
||||||
assert_match(/<div>\s+<img style="width: 181px; height: 125px" src="cid:.+?"><p>123<\/p>\s+<img style="width: 181px; height: 125px" src="cid:.+?">\s+<\/div>/, body)
|
assert_match(/<div>\s+<img style="width: 181px; height: 125px" src="cid:.+?"><p>123<\/p>\s+<img style="width: 181px; height: 125px" src="cid:.+?">\s+<\/div>/, body)
|
||||||
assert(2, attachments_inline.count)
|
assert_equal(2, attachments_inline.count)
|
||||||
assert_equal('image1.jpeg', attachments_inline[0][:filename])
|
assert_equal('image1.jpeg', attachments_inline[0][:filename])
|
||||||
assert_equal('image/jpeg', attachments_inline[0][:preferences]['Content-Type'])
|
assert_equal('image/jpeg', attachments_inline[0][:preferences]['Content-Type'])
|
||||||
assert_match(/@#{Setting.get('fqdn')}/, attachments_inline[0][:preferences]['Content-ID'])
|
assert_match(/@#{Setting.get('fqdn')}/, attachments_inline[0][:preferences]['Content-ID'])
|
||||||
|
|
|
@ -40,7 +40,7 @@ class TicketArticleTwitter < ActiveSupport::TestCase
|
||||||
truncated: false
|
truncated: false
|
||||||
}
|
}
|
||||||
preferences = {
|
preferences = {
|
||||||
twitter: twitter_preferences,
|
twitter: TweetBase.preferences_cleanup(twitter_preferences),
|
||||||
links: [
|
links: [
|
||||||
{
|
{
|
||||||
url: 'https://twitter.com/statuses/123',
|
url: 'https://twitter.com/statuses/123',
|
||||||
|
@ -56,18 +56,58 @@ class TicketArticleTwitter < ActiveSupport::TestCase
|
||||||
from: '@example',
|
from: '@example',
|
||||||
body: 'some tweet',
|
body: 'some tweet',
|
||||||
internal: false,
|
internal: false,
|
||||||
preferences: TweetBase.new.preferences_cleanup(preferences),
|
preferences: preferences,
|
||||||
updated_by_id: 1,
|
updated_by_id: 1,
|
||||||
created_by_id: 1,
|
created_by_id: 1,
|
||||||
)
|
)
|
||||||
assert(article1.preferences[:twitter])
|
assert(article1.preferences[:twitter])
|
||||||
assert_equal(1_234_567_890, article1.preferences[:twitter][:mention_ids][0])
|
assert_equal(1_234_567_890, article1.preferences[:twitter][:mention_ids][0])
|
||||||
assert_nil(article1.preferences[:twitter][:geo])
|
assert_equal(ActiveSupport::HashWithIndifferentAccess, article1.preferences[:twitter][:geo].class)
|
||||||
assert_equal(NilClass, article1.preferences[:twitter][:geo].class)
|
assert(article1.preferences[:twitter][:geo].blank?)
|
||||||
assert_nil(article1.preferences[:twitter][:place])
|
assert_equal(ActiveSupport::HashWithIndifferentAccess, article1.preferences[:twitter][:place].class)
|
||||||
assert_equal(NilClass, article1.preferences[:twitter][:place].class)
|
assert(article1.preferences[:twitter][:place].blank?)
|
||||||
|
|
||||||
twitter_preferences = {
|
twitter_preferences = {
|
||||||
|
mention_ids: [1_234_567_890],
|
||||||
|
geo: Twitter::NullObject.new,
|
||||||
|
retweeted: false,
|
||||||
|
possibly_sensitive: false,
|
||||||
|
in_reply_to_user_id: 1_234_567_890,
|
||||||
|
place: Twitter::NullObject.new,
|
||||||
|
retweet_count: 0,
|
||||||
|
source: '<a href="http://example.com/software/tweetbot/mac" rel="nofollow">Tweetbot for Mac</a>',
|
||||||
|
favorited: false,
|
||||||
|
truncated: false
|
||||||
|
}
|
||||||
|
preferences = TweetBase.preferences_cleanup(
|
||||||
|
twitter: twitter_preferences,
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
url: 'https://twitter.com/statuses/123',
|
||||||
|
target: '_blank',
|
||||||
|
name: 'on Twitter',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
article2 = Ticket::Article.create!(
|
||||||
|
ticket_id: ticket1.id,
|
||||||
|
type_id: Ticket::Article::Type.find_by(name: 'twitter status').id,
|
||||||
|
sender_id: Ticket::Article::Sender.find_by(name: 'Customer').id,
|
||||||
|
from: '@example',
|
||||||
|
body: 'some tweet',
|
||||||
|
internal: false,
|
||||||
|
preferences: preferences,
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
assert(article2.preferences[:twitter])
|
||||||
|
assert_equal(1_234_567_890, article2.preferences[:twitter][:mention_ids][0])
|
||||||
|
assert_equal(ActiveSupport::HashWithIndifferentAccess, article2.preferences[:twitter][:geo].class)
|
||||||
|
assert(article2.preferences[:twitter][:geo].blank?)
|
||||||
|
assert_equal(ActiveSupport::HashWithIndifferentAccess, article2.preferences[:twitter][:place].class)
|
||||||
|
assert(article2.preferences[:twitter][:place].blank?)
|
||||||
|
|
||||||
|
twitter_preferences = {
|
||||||
mention_ids: [1_234_567_890],
|
mention_ids: [1_234_567_890],
|
||||||
geo: Twitter::Geo.new(coordinates: [1, 1]),
|
geo: Twitter::Geo.new(coordinates: [1, 1]),
|
||||||
retweeted: false,
|
retweeted: false,
|
||||||
|
@ -80,7 +120,7 @@ class TicketArticleTwitter < ActiveSupport::TestCase
|
||||||
truncated: false
|
truncated: false
|
||||||
}
|
}
|
||||||
preferences = {
|
preferences = {
|
||||||
twitter: twitter_preferences,
|
twitter: TweetBase.preferences_cleanup(twitter_preferences),
|
||||||
links: [
|
links: [
|
||||||
{
|
{
|
||||||
url: 'https://twitter.com/statuses/123',
|
url: 'https://twitter.com/statuses/123',
|
||||||
|
@ -90,23 +130,64 @@ class TicketArticleTwitter < ActiveSupport::TestCase
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
article2 = Ticket::Article.create!(
|
article3 = Ticket::Article.create!(
|
||||||
ticket_id: ticket1.id,
|
ticket_id: ticket1.id,
|
||||||
type_id: Ticket::Article::Type.find_by(name: 'twitter status').id,
|
type_id: Ticket::Article::Type.find_by(name: 'twitter status').id,
|
||||||
sender_id: Ticket::Article::Sender.find_by(name: 'Customer').id,
|
sender_id: Ticket::Article::Sender.find_by(name: 'Customer').id,
|
||||||
from: '@example',
|
from: '@example',
|
||||||
body: 'some tweet',
|
body: 'some tweet',
|
||||||
internal: false,
|
internal: false,
|
||||||
preferences: TweetBase.new.preferences_cleanup(preferences),
|
preferences: preferences,
|
||||||
updated_by_id: 1,
|
updated_by_id: 1,
|
||||||
created_by_id: 1,
|
created_by_id: 1,
|
||||||
)
|
)
|
||||||
assert(article2.preferences[:twitter])
|
assert(article3.preferences[:twitter])
|
||||||
assert_equal(1_234_567_890, article2.preferences[:twitter][:mention_ids][0])
|
assert_equal(1_234_567_890, article3.preferences[:twitter][:mention_ids][0])
|
||||||
assert_equal(ActiveSupport::HashWithIndifferentAccess, article2.preferences[:twitter][:geo].class)
|
assert_equal(ActiveSupport::HashWithIndifferentAccess, article3.preferences[:twitter][:geo].class)
|
||||||
assert_equal({ 'coordinates' => [1, 1] }, article2.preferences[:twitter][:geo])
|
assert_equal({ 'coordinates' => [1, 1] }, article3.preferences[:twitter][:geo])
|
||||||
assert_equal(ActiveSupport::HashWithIndifferentAccess, article2.preferences[:twitter][:place].class)
|
assert_equal(ActiveSupport::HashWithIndifferentAccess, article3.preferences[:twitter][:place].class)
|
||||||
assert_equal({ 'country' => 'da', 'name' => 'do', 'woeid' => 1, 'id' => 1 }, article2.preferences[:twitter][:place])
|
assert_equal({ 'country' => 'da', 'name' => 'do', 'woeid' => 1, 'id' => 1 }, article3.preferences[:twitter][:place])
|
||||||
|
|
||||||
|
twitter_preferences = {
|
||||||
|
mention_ids: [1_234_567_890],
|
||||||
|
geo: Twitter::Geo.new(coordinates: [1, 1]),
|
||||||
|
retweeted: false,
|
||||||
|
possibly_sensitive: false,
|
||||||
|
in_reply_to_user_id: 1_234_567_890,
|
||||||
|
place: Twitter::Place.new(country: 'da', name: 'do', woeid: 1, id: 1),
|
||||||
|
retweet_count: 0,
|
||||||
|
source: '<a href="http://example.com/software/tweetbot/mac" rel="nofollow">Tweetbot for Mac</a>',
|
||||||
|
favorited: false,
|
||||||
|
truncated: false
|
||||||
|
}
|
||||||
|
preferences = TweetBase.preferences_cleanup(
|
||||||
|
twitter: twitter_preferences,
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
url: 'https://twitter.com/statuses/123',
|
||||||
|
target: '_blank',
|
||||||
|
name: 'on Twitter',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
article4 = Ticket::Article.create!(
|
||||||
|
ticket_id: ticket1.id,
|
||||||
|
type_id: Ticket::Article::Type.find_by(name: 'twitter status').id,
|
||||||
|
sender_id: Ticket::Article::Sender.find_by(name: 'Customer').id,
|
||||||
|
from: '@example',
|
||||||
|
body: 'some tweet',
|
||||||
|
internal: false,
|
||||||
|
preferences: preferences,
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
assert(article4.preferences[:twitter])
|
||||||
|
assert_equal(1_234_567_890, article4.preferences[:twitter][:mention_ids][0])
|
||||||
|
assert_equal(ActiveSupport::HashWithIndifferentAccess, article4.preferences[:twitter][:geo].class)
|
||||||
|
assert_equal({ 'coordinates' => [1, 1] }, article4.preferences[:twitter][:geo])
|
||||||
|
assert_equal(ActiveSupport::HashWithIndifferentAccess, article4.preferences[:twitter][:place].class)
|
||||||
|
assert_equal({ 'country' => 'da', 'name' => 'do', 'woeid' => 1, 'id' => 1 }, article4.preferences[:twitter][:place])
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue