Init version of highlighter.
This commit is contained in:
parent
8576909975
commit
6570ead1d3
9 changed files with 168 additions and 85 deletions
|
@ -91,7 +91,11 @@ class App.TicketZoom extends App.Controller
|
||||||
return if @activeState
|
return if @activeState
|
||||||
@activeState = true
|
@activeState = true
|
||||||
|
|
||||||
App.Event.trigger('ui::ticket::shown', { ticket_id: @ticket.id } )
|
App.Event.trigger('ui::ticket::shown', { ticket_id: @ticket_id } )
|
||||||
|
|
||||||
|
if !@highlighed
|
||||||
|
@highlighed = true
|
||||||
|
@highligher.loadHighlights()
|
||||||
|
|
||||||
App.OnlineNotification.seen( 'Ticket', @ticket_id )
|
App.OnlineNotification.seen( 'Ticket', @ticket_id )
|
||||||
@navupdate '#'
|
@navupdate '#'
|
||||||
|
@ -292,10 +296,15 @@ class App.TicketZoom extends App.Controller
|
||||||
ui: @
|
ui: @
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@highligher = new App.TicketZoomHighlighter(
|
||||||
|
el: @$('.highlighter')
|
||||||
|
ticket_id: @ticket.id
|
||||||
|
)
|
||||||
|
|
||||||
# rerender whole sidebar if customer or organization has changed
|
# rerender whole sidebar if customer or organization has changed
|
||||||
if @ticketLastAttributes.customer_id isnt @ticket.customer_id || @ticketLastAttributes.organization_id isnt @ticket.organization_id
|
if @ticketLastAttributes.customer_id isnt @ticket.customer_id || @ticketLastAttributes.organization_id isnt @ticket.organization_id
|
||||||
new App.WidgetAvatar(
|
new App.WidgetAvatar(
|
||||||
el: @$('.page-header .js-avatar')
|
el: @$('.ticketZoom-header .js-avatar')
|
||||||
user_id: @ticket.customer_id
|
user_id: @ticket.customer_id
|
||||||
size: 50
|
size: 50
|
||||||
)
|
)
|
||||||
|
@ -316,6 +325,7 @@ class App.TicketZoom extends App.Controller
|
||||||
ticket: @ticket
|
ticket: @ticket
|
||||||
el: @el.find('.ticket-article')
|
el: @el.find('.ticket-article')
|
||||||
ui: @
|
ui: @
|
||||||
|
highlighter: @highlighter
|
||||||
)
|
)
|
||||||
|
|
||||||
@article_view.execute(
|
@article_view.execute(
|
||||||
|
|
|
@ -5,6 +5,7 @@ class App.TicketZoomArticleView extends App.Controller
|
||||||
@article_controller = {}
|
@article_controller = {}
|
||||||
|
|
||||||
execute: (params) ->
|
execute: (params) ->
|
||||||
|
all = []
|
||||||
for ticket_article_id in params.ticket_article_ids
|
for ticket_article_id in params.ticket_article_ids
|
||||||
if !@article_controller[ticket_article_id]
|
if !@article_controller[ticket_article_id]
|
||||||
el = $('<div></div>')
|
el = $('<div></div>')
|
||||||
|
@ -14,9 +15,16 @@ class App.TicketZoomArticleView extends App.Controller
|
||||||
el: el
|
el: el
|
||||||
ui: @ui
|
ui: @ui
|
||||||
)
|
)
|
||||||
@el.append( el )
|
all.push el
|
||||||
|
@el.append( all )
|
||||||
|
|
||||||
class ArticleViewItem extends App.Controller
|
class ArticleViewItem extends App.Controller
|
||||||
|
hasChangedAttributes: ['from', 'to', 'cc', 'subject', 'body', 'internal']
|
||||||
|
|
||||||
|
elements:
|
||||||
|
'.textBubble-content': 'textBubbleContent'
|
||||||
|
'.textBubble-overflowContainer': 'textBubbleOverflowContainer'
|
||||||
|
|
||||||
events:
|
events:
|
||||||
'click .show_toogle': 'show_toogle'
|
'click .show_toogle': 'show_toogle'
|
||||||
'click .textBubble': 'toggle_meta_with_delay'
|
'click .textBubble': 'toggle_meta_with_delay'
|
||||||
|
@ -34,21 +42,43 @@ class ArticleViewItem extends App.Controller
|
||||||
@bind(
|
@bind(
|
||||||
'ui::ticket::shown'
|
'ui::ticket::shown'
|
||||||
(data) =>
|
(data) =>
|
||||||
if data.ticket_id is @ticket.id
|
if data.ticket_id.toString() is @ticket.id.toString()
|
||||||
@setSeeMore()
|
@setSeeMore()
|
||||||
)
|
)
|
||||||
|
|
||||||
# subscribe to changes
|
# subscribe to changes
|
||||||
@subscribeId = App.TicketArticle.full( @ticket_article_id, @render, false, true )
|
@subscribeId = App.TicketArticle.full(@ticket_article_id, @render, false, true)
|
||||||
|
|
||||||
release: =>
|
release: =>
|
||||||
App.User.TicketArticle(@subscribeId)
|
App.TicketArticle.unsubscribe(@subscribeId)
|
||||||
|
|
||||||
|
hasChanged: (article) =>
|
||||||
|
|
||||||
|
# if no last article exists, remember it and return true
|
||||||
|
if !@article_last_updated
|
||||||
|
@article_last_updated = {}
|
||||||
|
for item in @hasChangedAttributes
|
||||||
|
@article_last_updated[item] = article[item]
|
||||||
|
return true
|
||||||
|
|
||||||
|
# compare last and current article attributes
|
||||||
|
article_last_updated_check = {}
|
||||||
|
for item in @hasChangedAttributes
|
||||||
|
article_last_updated_check[item] = article[item]
|
||||||
|
diff = difference(@article_last_updated, article_last_updated_check)
|
||||||
|
return false if !diff || _.isEmpty( diff )
|
||||||
|
@article_last_updated = article_last_updated_check
|
||||||
|
true
|
||||||
|
|
||||||
render: (article) =>
|
render: (article) =>
|
||||||
|
|
||||||
# get articles
|
# get articles
|
||||||
@article = App.TicketArticle.fullLocal( @ticket_article_id )
|
@article = App.TicketArticle.fullLocal( @ticket_article_id )
|
||||||
|
|
||||||
|
# check if rerender is needed
|
||||||
|
return if !@hasChanged(@article)
|
||||||
|
|
||||||
|
console.log('RERENDER', @ticket_article_id)
|
||||||
# prepare html body
|
# prepare html body
|
||||||
if @article.content_type is 'text/html'
|
if @article.content_type is 'text/html'
|
||||||
@article['html'] = @article.body
|
@article['html'] = @article.body
|
||||||
|
@ -83,33 +113,34 @@ class ArticleViewItem extends App.Controller
|
||||||
# set see more options
|
# set see more options
|
||||||
setSeeMore: =>
|
setSeeMore: =>
|
||||||
maxHeight = 560
|
maxHeight = 560
|
||||||
bubble = @$('.textBubble-content')
|
bubbleContent = @textBubbleContent
|
||||||
|
bubbleOvervlowContainer = @textBubbleOverflowContainer
|
||||||
|
|
||||||
# expand if see more is already clicked
|
# expand if see more is already clicked
|
||||||
if @seeMore
|
if @seeMore
|
||||||
bubble.css('height', 'auto')
|
bubbleContent.css('height', 'auto')
|
||||||
bubble.parent().find('.textBubble-overflowContainer').addClass('hide')
|
bubbleOvervlowContainer.addClass('hide')
|
||||||
return
|
return
|
||||||
|
|
||||||
# reset bubble heigth and "see more" opacity
|
# reset bubble heigth and "see more" opacity
|
||||||
bubble.css('height', '')
|
bubbleContent.css('height', '')
|
||||||
bubble.parent().find('.textBubble-overflowContainer').css('opacity', '')
|
bubbleOvervlowContainer.css('opacity', '')
|
||||||
|
|
||||||
# remember offset of "see more"
|
# remember offset of "see more"
|
||||||
offsetTop = bubble.find('.js-signatureMarker').position()
|
offsetTop = bubbleContent.find('.js-signatureMarker').position()
|
||||||
|
|
||||||
# remember bubble heigth
|
# remember bubble heigth
|
||||||
heigth = bubble.height()
|
heigth = bubbleContent.height()
|
||||||
if offsetTop
|
if offsetTop && heigth
|
||||||
bubble.attr('data-height', heigth)
|
bubbleContent.attr('data-height', heigth)
|
||||||
bubble.css('height', "#{offsetTop.top + 30}px")
|
bubbleContent.css('height', "#{offsetTop.top + 30}px")
|
||||||
bubble.parent().find('.textBubble-overflowContainer').removeClass('hide')
|
bubbleOvervlowContainer.removeClass('hide')
|
||||||
else if heigth > maxHeight
|
else if heigth > maxHeight
|
||||||
bubble.attr('data-height', heigth)
|
bubbleContent.attr('data-height', heigth)
|
||||||
bubble.css('height', "#{maxHeight}px")
|
bubbleContent.css('height', "#{maxHeight}px")
|
||||||
bubble.parent().find('.textBubble-overflowContainer').removeClass('hide')
|
bubbleOvervlowContainer.removeClass('hide')
|
||||||
else
|
else
|
||||||
bubble.parent().find('.textBubble-overflowContainer').addClass('hide')
|
bubbleOvervlowContainer.addClass('hide')
|
||||||
|
|
||||||
show_toogle: (e) ->
|
show_toogle: (e) ->
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
|
@ -218,21 +249,21 @@ class ArticleViewItem extends App.Controller
|
||||||
|
|
||||||
@seeMore = true
|
@seeMore = true
|
||||||
|
|
||||||
container = $(e.currentTarget).parents('.textBubble-content')
|
bubbleContent = @textBubbleContent
|
||||||
overflowContainer = container.find('.textBubble-overflowContainer')
|
bubbleOvervlowContainer = @textBubbleOverflowContainer
|
||||||
|
|
||||||
overflowContainer.velocity
|
bubbleOvervlowContainer.velocity
|
||||||
properties:
|
properties:
|
||||||
opacity: 0
|
opacity: 0
|
||||||
options:
|
options:
|
||||||
duration: 300
|
duration: 300
|
||||||
|
|
||||||
container.velocity
|
bubbleContent.velocity
|
||||||
properties:
|
properties:
|
||||||
height: container.attr('data-height')
|
height: bubbleContent.attr('data-height')
|
||||||
options:
|
options:
|
||||||
duration: 300
|
duration: 300
|
||||||
complete: -> overflowContainer.addClass('hide');
|
complete: -> bubbleOvervlowContainer.addClass('hide');
|
||||||
|
|
||||||
isOrContains: (node, container) ->
|
isOrContains: (node, container) ->
|
||||||
while node
|
while node
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
class App.TicketZoomHighlighter extends App.Controller
|
class App.TicketZoomHighlighter extends App.Controller
|
||||||
elements:
|
elements:
|
||||||
'.textBubble-content': 'articles'
|
'.textBubble-content': 'articles'
|
||||||
'.js-highlight .marker-icon': 'highlighterControl'
|
'.js-highlight-icon': 'highlighterControl'
|
||||||
|
|
||||||
events:
|
events:
|
||||||
'click .js-highlight': 'toggleHighlight'
|
'click .js-highlight': 'toggleHighlight'
|
||||||
|
@ -10,23 +10,23 @@ class App.TicketZoomHighlighter extends App.Controller
|
||||||
colors: [
|
colors: [
|
||||||
{
|
{
|
||||||
name: 'Yellow'
|
name: 'Yellow'
|
||||||
color: "#f7e7b2"
|
color: '#f7e7b2'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Green'
|
name: 'Green'
|
||||||
color: "#bce7b6"
|
color: '#bce7b6'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Blue'
|
name: 'Blue'
|
||||||
color: "#b3ddf9"
|
color: '#b3ddf9'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Pink'
|
name: 'Pink'
|
||||||
color: "#fea9c5"
|
color: '#fea9c5'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Purple'
|
name: 'Purple'
|
||||||
color: "#eac5ee"
|
color: '#eac5ee'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -41,7 +41,6 @@ class App.TicketZoomHighlighter extends App.Controller
|
||||||
rangy.init()
|
rangy.init()
|
||||||
|
|
||||||
@highlighter = rangy.createHighlighter(document, 'TextRange')
|
@highlighter = rangy.createHighlighter(document, 'TextRange')
|
||||||
|
|
||||||
@addClassApplier entry for entry in @colors
|
@addClassApplier entry for entry in @colors
|
||||||
|
|
||||||
@setColor()
|
@setColor()
|
||||||
|
@ -50,13 +49,19 @@ class App.TicketZoomHighlighter extends App.Controller
|
||||||
# store original highlight css data
|
# store original highlight css data
|
||||||
@storeOriginalHighlight()
|
@storeOriginalHighlight()
|
||||||
|
|
||||||
|
update = =>
|
||||||
@loadHighlights()
|
@loadHighlights()
|
||||||
|
@refreshObserver()
|
||||||
|
App.Delay.set( update, 800 )
|
||||||
|
|
||||||
render: ->
|
render: ->
|
||||||
@html App.view('ticket_zoom/highlighter')
|
@html App.view('ticket_zoom/highlighter')
|
||||||
colors: @colors
|
colors: @colors
|
||||||
activeColorIndex: @activeColorIndex
|
activeColorIndex: @activeColorIndex
|
||||||
|
|
||||||
|
highlighterInstance: =>
|
||||||
|
@highlighter
|
||||||
|
|
||||||
storeOriginalHighlight: =>
|
storeOriginalHighlight: =>
|
||||||
@originalHighlight =
|
@originalHighlight =
|
||||||
fill: @highlighterControl.css('fill')
|
fill: @highlighterControl.css('fill')
|
||||||
|
@ -70,19 +75,33 @@ class App.TicketZoomHighlighter extends App.Controller
|
||||||
highlightEnable: =>
|
highlightEnable: =>
|
||||||
@isActive = true
|
@isActive = true
|
||||||
@highlighterControl.css('opacity', 1)
|
@highlighterControl.css('opacity', 1)
|
||||||
|
@highlighterControl.css('fill', @activeColor)
|
||||||
|
|
||||||
|
@refreshObserver()
|
||||||
|
|
||||||
highlightDisable: =>
|
highlightDisable: =>
|
||||||
@isActive = false
|
@isActive = false
|
||||||
@restoreOriginalHighlight()
|
@restoreOriginalHighlight()
|
||||||
#@highlighterControl.css('opacity', @originalHighlight.opacity)
|
|
||||||
|
|
||||||
active: =>
|
articles = @el.closest('.content').find('.textBubble')
|
||||||
@isActive
|
articles.removeAttr('data-highlightcolor')
|
||||||
|
@refreshObserver()
|
||||||
|
|
||||||
|
refreshObserver: =>
|
||||||
|
articles = @el.closest('.content').find('.textBubble-content')
|
||||||
|
console.log('refreshObserver', articles)
|
||||||
|
articles.off('mouseup', @onMouseUp)
|
||||||
|
articles.on('mouseup', @onMouseUp) #future: touchend
|
||||||
|
|
||||||
# for testing purposes the highlights get stored in localStorage
|
# for testing purposes the highlights get stored in localStorage
|
||||||
loadHighlights: ->
|
loadHighlights: ->
|
||||||
if highlights = localStorage['highlights']
|
@el.closest('.content').find('.textBubble-content').each( (index, element) =>
|
||||||
@highlighter.deserialize localStorage['highlights']
|
article_id = $(element).data('id')
|
||||||
|
article = App.TicketArticle.find(article_id)
|
||||||
|
if article.preferences && article.preferences['highlight']
|
||||||
|
console.log('highlight', article.preferences['highlight'])
|
||||||
|
@highlighter.deserialize(article.preferences['highlight'])
|
||||||
|
)
|
||||||
|
|
||||||
# the serialization creates one string for the entiery ticket
|
# the serialization creates one string for the entiery ticket
|
||||||
# containing the offsets and the highlight classes
|
# containing the offsets and the highlight classes
|
||||||
|
@ -91,8 +110,12 @@ class App.TicketZoomHighlighter extends App.Controller
|
||||||
#
|
#
|
||||||
# if classes can be changed in the admin interface
|
# if classes can be changed in the admin interface
|
||||||
# we have to watch out to not end up with empty highlight classes
|
# we have to watch out to not end up with empty highlight classes
|
||||||
storeHighlights: ->
|
storeHighlights: (article_id) ->
|
||||||
localStorage['highlights'] = @highlighter.serialize()
|
article = App.TicketArticle.find(article_id)
|
||||||
|
data = @highlighter.serialize()
|
||||||
|
console.log('HI', article_id, data)
|
||||||
|
article.preferences['highlight'] = data
|
||||||
|
article.save()
|
||||||
|
|
||||||
# the colors is set via css classes (can't do it inline with rangy)
|
# the colors is set via css classes (can't do it inline with rangy)
|
||||||
# thus we have to create a stylesheet if the colors
|
# thus we have to create a stylesheet if the colors
|
||||||
|
@ -102,54 +125,60 @@ class App.TicketZoomHighlighter extends App.Controller
|
||||||
|
|
||||||
setColor: ->
|
setColor: ->
|
||||||
@highlightClass = @highlightClassPrefix + @colors[@activeColorIndex].name
|
@highlightClass = @highlightClassPrefix + @colors[@activeColorIndex].name
|
||||||
|
@activeColor = @colors[@activeColorIndex].color
|
||||||
|
|
||||||
if @isActive
|
if @isActive
|
||||||
@articles.attr('data-highlightcolor', @colors[@activeColorIndex].name)
|
articles = @el.closest('.content').find('.textBubble')
|
||||||
|
articles.attr('data-highlightcolor', @colors[@activeColorIndex].name)
|
||||||
|
|
||||||
toggleHighlight: (e) =>
|
toggleHighlight: (e) =>
|
||||||
if @isActive
|
console.log('toggleHighlight', @isActive)
|
||||||
@restoreOriginalHighlight()
|
|
||||||
else
|
|
||||||
@highlightEnable()
|
|
||||||
return
|
|
||||||
|
|
||||||
console.log('toggleHighlight', @isActive, @articles)
|
|
||||||
if @isActive
|
if @isActive
|
||||||
$(e.currentTarget).removeClass('active')
|
$(e.currentTarget).removeClass('active')
|
||||||
@isActive = false
|
|
||||||
@articles.off('mouseup', @onMouseUp)
|
@highlightDisable()
|
||||||
@articles.removeAttr('data-highlightcolor')
|
|
||||||
else
|
else
|
||||||
|
@highlightEnable()
|
||||||
selection = rangy.getSelection()
|
selection = rangy.getSelection()
|
||||||
# if there's already something selected,
|
# if there's already something selected,
|
||||||
# don't go into highlight mode
|
# don't go into highlight mode
|
||||||
# just toggle the selected
|
# just toggle the selected
|
||||||
if !selection.isCollapsed
|
if !selection.isCollapsed
|
||||||
@toggleHighlightAtSelection $(selection.anchorNode).closest @articles.selector
|
@toggleHighlightAtSelection(@content, @article_id)
|
||||||
else
|
#else
|
||||||
# toggle ui
|
# toggle ui
|
||||||
$(e.currentTarget).addClass('active')
|
#$(e.currentTarget).addClass('active')
|
||||||
|
|
||||||
# activate selection background
|
# activate selection background
|
||||||
@articles.attr('data-highlightcolor', @colors[@activeColorIndex].name)
|
#@articles.attr('data-highlightcolor', @colors[@activeColorIndex].name)
|
||||||
|
|
||||||
@isActive = true
|
|
||||||
@articles.on('mouseup', @onMouseUp) #future: touchend
|
|
||||||
|
|
||||||
pickColor: (e) =>
|
pickColor: (e) =>
|
||||||
@$('.js-highlightColor .visibility-change.active').removeClass('active')
|
# TODO: @mrflix - still needed?
|
||||||
$(e.currentTarget).find('.visibility-change').addClass('active')
|
#@$('.js-highlightColor .visibility-change.active').removeClass('active')
|
||||||
|
#$(e.currentTarget).find('.visibility-change').addClass('active')
|
||||||
|
|
||||||
@activeColorIndex = $(e.currentTarget).attr('data-key')
|
@activeColorIndex = $(e.currentTarget).attr('data-key')
|
||||||
|
|
||||||
|
|
||||||
@isActive = true
|
|
||||||
console.log('ooo', @activeColorIndex, @colors[@activeColorIndex].color, @colors[@activeColorIndex])
|
|
||||||
@highlighterControl.css('fill', @colors[@activeColorIndex].color)
|
|
||||||
@highlighterControl.css('opacity', 1)
|
|
||||||
@setColor()
|
@setColor()
|
||||||
|
|
||||||
|
@highlightEnable()
|
||||||
|
|
||||||
|
# check if selection exists - highlight it or remove highlight
|
||||||
|
@toggleHighlightAtSelection(@content, @article_id)
|
||||||
|
|
||||||
onMouseUp: (e) =>
|
onMouseUp: (e) =>
|
||||||
#@toggleHighlightAtSelection $(e.currentTarget).closest('.textBubble-content')# @articles.selector
|
@updateSelectedArticle(e)
|
||||||
|
|
||||||
|
console.log('onMouseUp', @isActive, @content, @article_id)
|
||||||
|
if @isActive
|
||||||
|
@toggleHighlightAtSelection(@content, @article_id) # @articles.selector
|
||||||
|
|
||||||
|
updateSelectedArticle: (e) =>
|
||||||
|
@content = $(e.currentTarget).closest('.textBubble-content')
|
||||||
|
@article_id = @content.data('id')
|
||||||
|
if !@article_id
|
||||||
|
@content = $(e.currentTarget)
|
||||||
|
@article_id = @content.data('id')
|
||||||
|
|
||||||
#
|
#
|
||||||
# toggle Highlight
|
# toggle Highlight
|
||||||
|
@ -160,12 +189,17 @@ class App.TicketZoomHighlighter extends App.Controller
|
||||||
# - or highlights the selection
|
# - or highlights the selection
|
||||||
# - clears the selection
|
# - clears the selection
|
||||||
|
|
||||||
toggleHighlightAtSelection: (article) =>
|
toggleHighlightAtSelection: (article, article_id) =>
|
||||||
selection = rangy.getSelection()
|
selection = rangy.getSelection()
|
||||||
|
|
||||||
|
# activate selection background
|
||||||
|
article.attr('data-highlightcolor', @colors[@activeColorIndex].name)
|
||||||
|
|
||||||
if @highlighter.selectionOverlapsHighlight selection
|
if @highlighter.selectionOverlapsHighlight selection
|
||||||
|
console.log('SELECTION EXISTS, REMOVED IT')
|
||||||
@highlighter.unhighlightSelection()
|
@highlighter.unhighlightSelection()
|
||||||
else
|
else
|
||||||
|
console.log('NEW SELECTION')
|
||||||
@highlighter.highlightSelection @highlightClass,
|
@highlighter.highlightSelection @highlightClass,
|
||||||
selection: selection
|
selection: selection
|
||||||
containerElementId: article.get(0).id
|
containerElementId: article.get(0).id
|
||||||
|
@ -175,5 +209,5 @@ class App.TicketZoomHighlighter extends App.Controller
|
||||||
|
|
||||||
@highlightDisable()
|
@highlightDisable()
|
||||||
|
|
||||||
|
# save new selections
|
||||||
#@storeHighlights()
|
@storeHighlights(article_id)
|
|
@ -1,5 +1,5 @@
|
||||||
class App.TicketArticle extends App.Model
|
class App.TicketArticle extends App.Model
|
||||||
@configure 'TicketArticle', 'from', 'to', 'cc', 'subject', 'body', 'content_type', 'ticket_id', 'type_id', 'sender_id', 'internal', 'in_reply_to', 'form_id', 'updated_at'
|
@configure 'TicketArticle', 'from', 'to', 'cc', 'subject', 'body', 'content_type', 'ticket_id', 'type_id', 'sender_id', 'internal', 'in_reply_to', 'form_id', 'preferences', 'updated_at'
|
||||||
@extend Spine.Model.Ajax
|
@extend Spine.Model.Ajax
|
||||||
@url: @apiPath + '/ticket_articles'
|
@url: @apiPath + '/ticket_articles'
|
||||||
@configure_attributes = [
|
@configure_attributes = [
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
<span class="dropdown-iconSpacer">
|
<span class="dropdown-iconSpacer">
|
||||||
<span class="color-swatch icon" style="background: <%= entry.color %>"></span>
|
<span class="color-swatch icon" style="background: <%= entry.color %>"></span>
|
||||||
</span>
|
</span>
|
||||||
<%= entry.name %>
|
<%- @Ti(entry.name) %>
|
||||||
<span class="dropdown-activeSpacer visibility-change<%= ' is-active' if i is @activeColorIndex %>">
|
<span class="dropdown-activeSpacer visibility-change<%= ' is-active' if i is @activeColorIndex %>">
|
||||||
<svg class="icon-checkmark" data-visible="active"><use xlink:href="#icon-checkmark" fill="white" /></svg>
|
<svg class="icon-checkmark" data-visible="active"><use xlink:href="#icon-checkmark" fill="white" /></svg>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
<div class="internal-border">
|
<div class="internal-border">
|
||||||
<div class="textBubble">
|
<div class="textBubble">
|
||||||
<div class="bubble-arrow"></div>
|
<div class="bubble-arrow"></div>
|
||||||
<div class="textBubble-content">
|
<div class="textBubble-content" id="article-content-<%= @article.id %>" data-id="<%= @article.id %>">
|
||||||
<%- App.Utils.signatureIdentify( @article.html ) %>
|
<%- App.Utils.signatureIdentify( @article.html ) %>
|
||||||
<div class="textBubble-overflowContainer">
|
<div class="textBubble-overflowContainer">
|
||||||
<div class="btn btn--text js-unfold"><%- @T('See more') %></div>
|
<div class="btn btn--text js-unfold"><%- @T('See more') %></div>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<div class="btn btn--action btn--split--first js-highlight centered">
|
<div class="btn btn--action btn--split--first js-highlight centered">
|
||||||
<svg class="marker-icon"><use xlink:href="#icon-marker" /></svg>
|
<svg class="icon icon-marker js-highlight-icon"><use xlink:href="#icon-marker" /></svg>
|
||||||
</div>
|
</div>
|
||||||
<div class="dropdown dropdown--actions">
|
<div class="dropdown dropdown--actions">
|
||||||
<div class="btn btn--action btn--split--last btn--slim centered" data-toggle="dropdown" aria-expanded="true">
|
<div class="btn btn--action btn--split--last btn--slim centered" data-toggle="dropdown" aria-expanded="true">
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
<span class="dropdown-iconSpacer">
|
<span class="dropdown-iconSpacer">
|
||||||
<span class="color-swatch icon" style="background: <%= entry.color %>"></span>
|
<span class="color-swatch icon" style="background: <%= entry.color %>"></span>
|
||||||
</span>
|
</span>
|
||||||
<%= entry.name %>
|
<%- @Ti(entry.name) %>
|
||||||
<span class="dropdown-activeSpacer visibility-change<%= ' active' if i is @activeColorIndex %>">
|
<span class="dropdown-activeSpacer visibility-change<%= ' active' if i is @activeColorIndex %>">
|
||||||
<span class="white checkmark icon" data-visible="active"></span>
|
<span class="white checkmark icon" data-visible="active"></span>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -13,6 +13,7 @@ class Ticket::Article < ApplicationModel
|
||||||
belongs_to :sender, class_name: 'Ticket::Article::Sender'
|
belongs_to :sender, class_name: 'Ticket::Article::Sender'
|
||||||
belongs_to :created_by, class_name: 'User'
|
belongs_to :created_by, class_name: 'User'
|
||||||
belongs_to :updated_by, class_name: 'User'
|
belongs_to :updated_by, class_name: 'User'
|
||||||
|
store :preferences
|
||||||
before_create :check_subject
|
before_create :check_subject
|
||||||
before_update :check_subject
|
before_update :check_subject
|
||||||
notify_clients_support
|
notify_clients_support
|
||||||
|
@ -20,11 +21,13 @@ class Ticket::Article < ApplicationModel
|
||||||
activity_stream_support ignore_attributes: {
|
activity_stream_support ignore_attributes: {
|
||||||
type_id: true,
|
type_id: true,
|
||||||
sender_id: true,
|
sender_id: true,
|
||||||
|
preferences: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
history_support ignore_attributes: {
|
history_support ignore_attributes: {
|
||||||
type_id: true,
|
type_id: true,
|
||||||
sender_id: true,
|
sender_id: true,
|
||||||
|
preferences: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
class AddPreferencesToTicketArticles < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_column :ticket_articles, :preferences, :text, limit: 500.kilobytes + 1, null: true
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue