Rewrite of ticket zoom, split in to different controllers.

This commit is contained in:
Martin Edenhofer 2013-06-18 11:38:08 +02:00
parent a408b1aef9
commit ba5b006aea
8 changed files with 438 additions and 318 deletions

View file

@ -1,14 +1,4 @@
class App.TicketZoom extends App.Controller class App.TicketZoom extends App.Controller
events:
'click .submit': 'update'
'click [data-type=reply]': 'reply'
# 'click [data-type=reply-all]': 'replyall'
'click [data-type=public]': 'public_internal'
'click [data-type=internal]': 'public_internal'
'change [name="ticket_article_type_id"]': 'form_update'
'click .show_toogle': 'show_toogle'
'blur .title_update': 'title_update'
constructor: (params) -> constructor: (params) ->
super super
# console.log 'zoom', params # console.log 'zoom', params
@ -18,12 +8,10 @@ class App.TicketZoom extends App.Controller
@navupdate '#' @navupdate '#'
@form_id = App.ControllerForm.formId()
@edit_form = undefined @edit_form = undefined
@ticket_id = params.ticket_id @ticket_id = params.ticket_id
@article_id = params.article_id @article_id = params.article_id
@signature = undefined @signature = undefined
@signature_used = undefined
@doNotLog = params['doNotLog'] || 0 @doNotLog = params['doNotLog'] || 0
@key = 'ticket::' + @ticket_id @key = 'ticket::' + @ticket_id
@ -88,8 +76,8 @@ class App.TicketZoom extends App.Controller
success: (data, status, xhr) => success: (data, status, xhr) =>
if @dataLastCall && !force if @dataLastCall && !force
# return if ticket hasnt changed # # return if ticket hasnt changed
return if _.isEqual( @dataLastCall.ticket, data.ticket ) # return if _.isEqual( @dataLastCall.ticket, data.ticket )
# return if ticket changed by my self # return if ticket changed by my self
return if data.ticket.updated_by_id is @Session.all().id return if data.ticket.updated_by_id is @Session.all().id
@ -97,17 +85,18 @@ class App.TicketZoom extends App.Controller
# trigger task notify # trigger task notify
diff = difference( @dataLastCall.ticket, data.ticket ) diff = difference( @dataLastCall.ticket, data.ticket )
console.log('diff', diff) console.log('diff', diff)
if !_.isEmpty(diff)
App.TaskManager.notify( @task_key ) App.TaskManager.notify( @task_key )
if $('[name="body"]').val() # if $('[name="body"]').val()
# App.Event.trigger 'notify', { # App.Event.trigger 'notify', {
# type: 'success' # type: 'success'
# msg: App.i18n.translateInline('Ticket has changed!') # msg: App.i18n.translateInline('Ticket has changed!')
# timeout: 30000 # timeout: 30000
# } # }
return # return
@dataLastCall = data @dataLastCall = data
@load(data) @load(data, force)
App.Store.write( @key, data ) App.Store.write( @key, data )
# start auto save # start auto save
@ -115,14 +104,19 @@ class App.TicketZoom extends App.Controller
error: (xhr, status, error) => error: (xhr, status, error) =>
# do not close window if request is abort or network error exists # do not close window if request is aborted
return if status is 'abort' return if status is 'abort'
return if status is 'error'
# do not close window on network error but if object is not found
return if status is 'error' && error isnt 'Not Found'
# remove task
App.TaskManager.remove( @task_key ) App.TaskManager.remove( @task_key )
) )
@doNotLog = 1 @doNotLog = 1
load: (data) => load: (data, force) =>
# reset old indexes # reset old indexes
@ticket = undefined @ticket = undefined
@articles = undefined @articles = undefined
@ -143,9 +137,9 @@ class App.TicketZoom extends App.Controller
App.Collection.load( type: 'TicketArticle', data: data.articles ) App.Collection.load( type: 'TicketArticle', data: data.articles )
# render page # render page
@render() @render(force)
render: => render: (force) =>
# get data # get data
if !@ticket if !@ticket
@ -159,10 +153,191 @@ class App.TicketZoom extends App.Controller
# update taskbar with new meta data # update taskbar with new meta data
App.Event.trigger 'task:render' App.Event.trigger 'task:render'
# rework articles if !@renderDone
for article in @articles @renderDone = true
new Article( article: article ) @html App.view('ticket_zoom')(
ticket: @ticket
articles: @articles
nav: @nav
isCustomer: @isRole('Customer')
)
# show frontend times
@frontendTimeUpdate()
@TicketTitle()
@TicketInfo()
@TicketAction()
@ArticleView()
if force || !@editDone
@editDone = true
@Edit()
# scroll to article if given
if @article_id && document.getElementById( 'article-' + @article_id )
offset = document.getElementById( 'article-' + @article_id ).offsetTop
offset = offset - 45
scrollTo = ->
@scrollTo( 0, offset )
@delay( scrollTo, 100, undefined, 'page' )
TicketTitle: =>
# show ticket title
new TicketTitle(
articles: @articles
ticket: @ticket
el: @el.find('.ticket-title')
)
TicketInfo: =>
# show ticket info
new TicketInfo(
articles: @articles
ticket: @ticket
el: @el.find('.ticket-info')
)
ArticleView: =>
# show article
new ArticleView(
articles: @articles
ticket: @ticket
el: @el.find('.article-view')
ui: @
)
Edit: =>
# show edit
new Edit(
articles: @articles
ticket: @ticket
el: @el.find('.edit')
form_state: @form_state
edit_form: @edit_form
task_key: @task_key
ui: @
)
TicketAction: =>
# show ticket action row
new TicketAction(
articles: @articles
ticket: @ticket
el: @el.find('.ticket-action')
ui: @
)
class TicketTitle extends App.Controller
events:
'blur .ticket-title-update': 'update'
constructor: ->
super
@render()
render: ->
@html App.view('ticket_zoom/ticket_title')(
ticket: @ticket
articles: @articles
)
update: (e) =>
$this = $(e.target)
title = $this.html()
title = ('' + title)
.replace(/<.+?>/g, '')
title = ('' + title)
.replace(/&nbsp;/g, ' ')
.replace(/&amp;/g, '&')
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>')
if title is '-'
title = ''
@ticket.title = title
@ticket.load( title: title )
@ticket.save()
# update taskbar with new meta data
App.Event.trigger 'task:render'
class TicketInfo extends App.Controller
constructor: ->
super
@render()
render: ->
@html App.view('ticket_zoom/ticket_info')(
ticket: @ticket
articles: @articles
)
class TicketAction extends App.Controller
constructor: ->
super
@render()
render: ->
@html App.view('ticket_zoom/ticket_action')()
# start customer info controller
if !@isRole('Customer')
new App.UserInfo(
el: @el.find('.customer_info')
user_id: @ticket.customer_id
ticket: @ticket
)
# start action controller
if !@isRole('Customer')
new TicketActionRow(
el: @el.find('.action_info')
ticket: @ticket
zoom: @ui
)
# start tag controller
if !@isRole('Customer')
new App.TagWidget(
el: @el.find('.tag_info')
object_type: 'Ticket'
object: @ticket
)
# start link info controller
if !@isRole('Customer')
new App.LinkInfo(
el: @el.find('.link_info')
object_type: 'Ticket'
object: @ticket
)
# show text module UI
if !@isRole('Customer')
new App.TextModuleUI(
el: @el.find('.text_module')
data:
ticket: @ticket
)
class Edit extends App.Controller
events:
'click .submit': 'update'
constructor: ->
super
@render()
render: ->
@html App.view('ticket_zoom/edit')(
ticket: @ticket
articles: @articles
isCustomer: @isRole('Customer')
)
@configure_attributes_ticket = [ @configure_attributes_ticket = [
{ name: 'ticket_state_id', display: 'State', tag: 'select', multiple: false, null: true, relation: 'TicketState', filter: @edit_form, translate: true, class: 'span2', item_class: 'pull-left' }, { name: 'ticket_state_id', display: 'State', tag: 'select', multiple: false, null: true, relation: 'TicketState', filter: @edit_form, translate: true, class: 'span2', item_class: 'pull-left' },
@ -194,16 +369,10 @@ class App.TicketZoom extends App.Controller
{ name: 'body', display: 'Text', tag: 'textarea', rows: 6, limit: 100, null: true, class: 'span7', item_class: '', upload: true }, { name: 'body', display: 'Text', tag: 'textarea', rows: 6, limit: 100, null: true, class: 'span7', item_class: '', upload: true },
] ]
@html App.view('agent_ticket_zoom')( @form_id = App.ControllerForm.formId()
ticket: @ticket
articles: @articles
nav: @nav
isCustomer: @isRole('Customer')
)
defaults = @form_state || @ticket defaults = @form_state || @ticket
new App.ControllerForm( new App.ControllerForm(
el: @el.find('[data-id="form-ticket-update"]') el: @el.find('.form-ticket-update')
form_id: @form_id form_id: @form_id
model: model:
configure_attributes: @configure_attributes_ticket configure_attributes: @configure_attributes_ticket
@ -213,7 +382,7 @@ class App.TicketZoom extends App.Controller
) )
new App.ControllerForm( new App.ControllerForm(
el: @el.find('[data-id="form-article-update"]') el: @el.find('.form-article-update')
form_id: @form_id form_id: @form_id
model: model:
configure_attributes: @configure_attributes_article configure_attributes: @configure_attributes_article
@ -248,179 +417,11 @@ class App.TicketZoom extends App.Controller
@el.find('textarea').elastic() @el.find('textarea').elastic()
# enable user popups # remember form defaults
@userPopups()
# show ticket action row
@ticket_action_row()
# show frontend times
@frontendTimeUpdate()
@formDefault = @formParam( @el.find('.ticket-update') ) @formDefault = @formParam( @el.find('.ticket-update') )
# scroll to article if given # enable user popups
if @article_id && document.getElementById( 'article-' + @article_id ) @userPopups()
offset = document.getElementById( 'article-' + @article_id ).offsetTop
offset = offset - 45
scrollTo = ->
@scrollTo( 0, offset )
@delay( scrollTo, 100, undefined, 'page' )
ticket_action_row: =>
# start customer info controller
if !@isRole('Customer')
new App.UserInfo(
el: @el.find('[data-id="customer_info"]')
user_id: @ticket.customer_id
ticket: @ticket
)
# start action controller
if !@isRole('Customer')
new TicketActionRow(
el: @el.find('[data-id="action_info"]')
ticket: @ticket
zoom: @
)
# start tag controller
if !@isRole('Customer')
new App.TagWidget(
el: @el.find('[data-id="tag_info"]')
object_type: 'Ticket'
object: @ticket
)
# start link info controller
if !@isRole('Customer')
new App.LinkInfo(
el: @el.find('[data-id="link_info"]')
object_type: 'Ticket'
object: @ticket
)
# show text module UI
if !@isRole('Customer')
new App.TextModuleUI(
el: @el.find('[data-id="text_module"]')
data:
ticket: @ticket
)
show_toogle: (e) ->
e.preventDefault()
$(e.target).hide()
if $(e.target).next('div')[0]
$(e.target).next('div').show()
else
$(e.target).parent().next('div').show()
public_internal: (e) ->
e.preventDefault()
article_id = $(e.target).parents('[data-id]').data('id')
# storage update
article = App.TicketArticle.find(article_id)
internal = true
if article.internal == true
internal = false
article.updateAttributes(
internal: internal
)
# runtime update
for article in @articles
if article_id is article.id
article['internal'] = internal
@render()
form_update: (e) ->
ticket_article_type_id = $(e.target).find('option:selected').val()
article_type = App.TicketArticleType.find( ticket_article_type_id )
@form_update_execute(article_type)
form_update_execute: (article_type) =>
# add signature
if !@form_state && !@signature_used && @signature && @signature.body && article_type.name is 'email'
@signature_used = true
body = @el.find('[name="body"]').val() || ''
body = body + "\n" + @signature.body
@el.find('[name="body"]').val( body )
# update textarea size
@el.find('[name="body"]').trigger('change')
reply: (e) =>
e.preventDefault()
article_id = $(e.target).parents('[data-id]').data('id')
article = App.Collection.find( 'TicketArticle', article_id )
article_type = App.Collection.find( 'TicketArticleType', article.ticket_article_type_id )
customer = App.Collection.find( 'User', article.created_by_id )
# update form
@form_update_execute(article_type)
# preselect article type
@el.find('[name="ticket_article_type_id"]').find('option:selected').removeAttr('selected')
@el.find('[name="ticket_article_type_id"]').find('[value="' + article_type.id + '"]').attr('selected',true)
@el.find('[name="ticket_article_type_id"]').trigger('change')
# empty form
@el.find('[name="to"]').val('')
@el.find('[name="cc"]').val('')
@el.find('[name="subject"]').val('')
@el.find('[name="in_reply_to"]').val('')
if article.message_id
@el.find('[name="in_reply_to"]').val(article.message_id)
if article_type.name is 'twitter status'
# set to in body
to = customer.accounts['twitter'].username || customer.accounts['twitter'].uid
@el.find('[name="body"]').val('@' + to)
else if article_type.name is 'twitter direct-message'
# show to
to = customer.accounts['twitter'].username || customer.accounts['twitter'].uid
@el.find('[name="to"]').val(to)
else if article_type.name is 'email'
@el.find('[name="to"]').val(article.from)
# @log 'reply ', article, @el.find('[name="to"]')
# add quoted text if needed
selectedText = App.ClipBoard.getSelected()
if selectedText
body = @el.find('[name="body"]').val() || ''
selectedText = selectedText.replace /^(.*)$/mg, (match) =>
'> ' + match
body = selectedText + "\n" + body
@el.find('[name="body"]').val(body)
# update textarea size
@el.find('[name="body"]').trigger('change')
title_update: (e) =>
$this = $(e.target)
title = $this.html()
title = ('' + title)
.replace(/<.+?>/g, '')
title = ('' + title)
.replace(/&nbsp;/g, ' ')
.replace(/&amp;/g, '&')
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>')
if title is '-'
title = ''
@ticket.title = title
@ticket.load( title: title )
@ticket.save()
update: (e) => update: (e) =>
e.preventDefault() e.preventDefault()
@ -455,7 +456,6 @@ class App.TicketZoom extends App.Controller
alert( App.i18n.translateContent('Text needed') ) alert( App.i18n.translateContent('Text needed') )
return return
# check attachment # check attachment
if params['body'] if params['body']
attachmentTranslated = App.i18n.translateContent('Attachment') attachmentTranslated = App.i18n.translateContent('Attachment')
@ -502,16 +502,16 @@ class App.TicketZoom extends App.Controller
@log 'TicketZoom', 'error', 'update article', errors @log 'TicketZoom', 'error', 'update article', errors
article.save( article.save(
success: (r) => success: (r) =>
@fetch( @ticket.id, true ) @ui.fetch( @ticket.id, true )
error: (r) => error: (r) =>
@log 'TicketZoom', 'error', 'update article', r @log 'TicketZoom', 'error', 'update article', r
) )
else else
@fetch( @ticket.id, true ) @ui.fetch( @ticket.id, true )
# reset form after save # reset form after save
App.TaskManager.update( @task_key, { 'state': undefined }) App.TaskManager.update( @task_key, { 'state': undefined })
@form_state = undefined @ui.form_state = undefined
) )
# errors = article.validate() # errors = article.validate()
@ -519,6 +519,130 @@ class App.TicketZoom extends App.Controller
# @formValidate( form: e.target, errors: errors ) # @formValidate( form: e.target, errors: errors )
return false return false
class ArticleView extends App.Controller
events:
'click [data-type=public]': 'public_internal'
'click [data-type=internal]': 'public_internal'
'click .show_toogle': 'show_toogle'
'click [data-type=reply]': 'reply'
# 'click [data-type=reply-all]': 'replyall'
constructor: ->
super
@render()
render: ->
# rework articles
for article in @articles
new Article( article: article )
@html App.view('ticket_zoom/article_view')(
ticket: @ticket
articles: @articles
isCustomer: @isRole('Customer')
)
# show frontend times
@frontendTimeUpdate()
# enable user popups
@userPopups()
public_internal: (e) ->
e.preventDefault()
article_id = $(e.target).parents('[data-id]').data('id')
# storage update
article = App.TicketArticle.find(article_id)
internal = true
if article.internal == true
internal = false
article.updateAttributes(
internal: internal
)
# runtime update
for article in @articles
if article_id is article.id
article['internal'] = internal
@render()
show_toogle: (e) ->
e.preventDefault()
$(e.target).hide()
if $(e.target).next('div')[0]
$(e.target).next('div').show()
else
$(e.target).parent().next('div').show()
checkIfSignatureIsNeeded: (article_type) =>
# add signature
if @ui.signature && @ui.signature.body && article_type.name is 'email'
body = @ui.el.find('[name="body"]').val() || ''
regexp = new RegExp( escapeRegExp( @ui.signature.body ) , 'i')
if !body.match(regexp)
body = body + "\n" + @ui.signature.body
@ui.el.find('[name="body"]').val( body )
# update textarea size
@ui.el.find('[name="body"]').trigger('change')
reply: (e) =>
e.preventDefault()
article_id = $(e.target).parents('[data-id]').data('id')
article = App.Collection.find( 'TicketArticle', article_id )
article_type = App.Collection.find( 'TicketArticleType', article.ticket_article_type_id )
customer = App.Collection.find( 'User', article.created_by_id )
# update form
@checkIfSignatureIsNeeded(article_type)
# preselect article type
@ui.el.find('[name="ticket_article_type_id"]').find('option:selected').removeAttr('selected')
@ui.el.find('[name="ticket_article_type_id"]').find('[value="' + article_type.id + '"]').attr('selected',true)
@ui.el.find('[name="ticket_article_type_id"]').trigger('change')
# empty form
#@ui.el.find('[name="to"]').val('')
#@ui.el.find('[name="cc"]').val('')
#@ui.el.find('[name="subject"]').val('')
@ui.el.find('[name="in_reply_to"]').val('')
console.log('repl2', article_type.name)
if article.message_id
@ui.el.find('[name="in_reply_to"]').val(article.message_id)
if article_type.name is 'twitter status'
# set to in body
to = customer.accounts['twitter'].username || customer.accounts['twitter'].uid
@ui.el.find('[name="body"]').val('@' + to)
else if article_type.name is 'twitter direct-message'
# show to
to = customer.accounts['twitter'].username || customer.accounts['twitter'].uid
@ui.el.find('[name="to"]').val(to)
else if article_type.name is 'email'
@ui.el.find('[name="to"]').val(article.from)
# @log 'reply ', article, @el.find('[name="to"]')
# add quoted text if needed
selectedText = App.ClipBoard.getSelected()
if selectedText
body = @ui.el.find('[name="body"]').val() || ''
selectedText = selectedText.replace /^(.*)$/mg, (match) =>
'> ' + match
body = selectedText + "\n" + body
@ui.el.find('[name="body"]').val(body)
# update textarea size
@ui.el.find('[name="body"]').trigger('change')
class Article extends App.Controller class Article extends App.Controller
constructor: -> constructor: ->
super super

View file

@ -1,103 +0,0 @@
<div class="page-header ticket-zoom">
<div class="row">
<div class="span10">
<h1><span contenteditable="true" class="title_update inline-edit"><%= @P( @ticket.title ) %></span> <small><%= @ticket.number %></small></h1>
</div>
<div class="span2">
<% if @C( 'LastOverview' ) && @nav: %>
<div class="pagination pagination-small pagination-right">
<span class="count"><%= @C( 'LastOverviewPosition' ) %>/<%= @C( 'LastOverviewTotal' ) %></span>
<% base_url ="#ticket_view/#{ @C('LastOverview') }/#{ @C('LastOverviewPosition') }/" %>
<ul>
<li class="<% if @C('LastOverviewPosition') <= 1: %>disabled<% end %>"><a href="<%- base_url %>previous" title="<%- @Ti( 'previous Ticket in Overview' ) %>">«</a></li>
<li class="<% if @C('LastOverviewPosition') is @C('LastOverviewTotal'): %>disabled<% end %>"><a href="<%- base_url %>next" title="<%- @Ti( 'next Ticket in Overview' ) %>">»</a></li>
</ul>
</div>
<% end %>
</div>
</div>
<div class="row">
<div class="span12">
<%= @ticket.group.name %> -
<%- @T( @ticket.ticket_state.name ) %> -
<%- @T( @ticket.ticket_priority.name ) %> -
<span class="humanTimeFromNow" data-time="<%- @ticket.created_at %>">?</span>
<% if !@isCustomer && @ticket.escalation_time: %>
- <%- @T('Escalation in') %>
<span class="humanTimeFromNow escalation" data-time="<%- @ticket.escalation_time %>">?</span>
<% end %>
</div>
</div>
</div>
<div class="row ticket-answer">
<div class="span9">
<% for article in @articles: %>
<div class="row article" data-id="<%= article.id %>" id="article-<%= article.id %>">
<div class="avatar span1 thumbnails">
<img class="thumbnail user-data" data-id="<%= article.created_by_id %>" src="<%= article.created_by.image %>" alt="">
<ul>
<li style="font-size: 10px;"><%- @T(article.article_type.name) %></li>
<% if article.article_type.name is 'email': %><li style="font-size: 10px;"><a href="api/ticket_article_plain/<%= article.id %>"><%- @T( 'raw' ) %></a></li><% end %>
</ul>
</div>
<div class="span8 well-muted article-message <% if article.internal is true: %> internal<% end %>">
<% if article.from: %>
<div>
<strong title="<%- @Ti( 'From' ) %>: <%= article.from %>"><%= article.from %></strong>
<% if article.actions: %>
<% for action in article.actions: %>
-
<a href="<%= action.href %>" data-type="<%= action.type %>" class="<% if action.class: %><%= action.class %><% end %>"><%- @T( action.name ) %></a>
<% end %>
<% end %>
- <span class="humanTimeFromNow" data-time="<%- article.created_at %>">?</span>
</div>
<% end %>
<% if article.to: %>
<div title="<%- @Ti( 'To' ) %>: <%= article.to %>"><%= article.to %></div>
<% end %>
<% if article.cc: %>
<div title="<%- @Ti( 'Cc' ) %>: <%= article.cc %>"><%= article.cc %></div>
<% end %>
<% if article.subject: %>
<div title="<%- @Ti( 'Subject' ) %>: <%= article.subject %>"><%= article.subject %></div>
<% end %>
<% if article.attachments: %>
<div>
<% for attachment in article.attachments: %>
<a href="api/ticket_attachment/<%= article.ticket_id %>/<%= article.id %>/<%= attachment.id %>" target="_blank" data-type="attachment" class="" title="<%= attachment.size %>"><%= attachment.filename %></a>
<% end %>
</div>
<% end %>
<hr/>
<div style="white-space:pre-wrap;" class="article-content"><%- article.html %></div>
</div>
</div>
<% end %>
<div class="row article">
<div class="avatar span1 thumbnails">
<img class="thumbnail user-data" data-id="<%= @S('id') %>" src="<%- @S('image') %>" alt="">
</div>
<div class="span8 well-muted article-message">
<form class="form-stacked pull-left ticket-update">
<div data-id="form-ticket-update"></div>
<div data-id="form-article-update"></div>
<button type="submit" class="btn btn-primary submit"><%- @T( 'Submit' ) %></button>
</form>
</div>
</div>
</div>
<div class="span3">
<div data-id="customer_info"></div>
<div data-id="action_info"></div>
<div data-id="tag_info"></div>
<div data-id="link_info"></div>
<div data-id="text_module"></div>
</div>
</div>

View file

@ -0,0 +1,28 @@
<div class="page-header ticket-zoom">
<div class="row">
<div class="span10 ticket-title"></div>
<div class="span2">
<% if @C( 'LastOverview' ) && @nav: %>
<div class="pagination pagination-small pagination-right">
<span class="count"><%= @C( 'LastOverviewPosition' ) %>/<%= @C( 'LastOverviewTotal' ) %></span>
<% base_url ="#ticket_view/#{ @C('LastOverview') }/#{ @C('LastOverviewPosition') }/" %>
<ul>
<li class="<% if @C('LastOverviewPosition') <= 1: %>disabled<% end %>"><a href="<%- base_url %>previous" title="<%- @Ti( 'previous Ticket in Overview' ) %>">«</a></li>
<li class="<% if @C('LastOverviewPosition') is @C('LastOverviewTotal'): %>disabled<% end %>"><a href="<%- base_url %>next" title="<%- @Ti( 'next Ticket in Overview' ) %>">»</a></li>
</ul>
</div>
<% end %>
</div>
</div>
<div class="row ticket-info"></div>
</div>
<div class="row ticket-answer">
<div class="span9">
<div class="article-view"></div>
<div class="edit"></div>
</div>
<div class="span3 ticket-action"></div>
</div>

View file

@ -0,0 +1,43 @@
<% for article in @articles: %>
<div class="row article" data-id="<%= article.id %>" id="article-<%= article.id %>">
<div class="avatar span1 thumbnails">
<img class="thumbnail user-data" data-id="<%= article.created_by_id %>" src="<%= article.created_by.image %>" alt="">
<ul>
<li style="font-size: 10px;"><%- @T(article.article_type.name) %></li>
<% if article.article_type.name is 'email': %><li style="font-size: 10px;"><a href="api/ticket_article_plain/<%= article.id %>"><%- @T( 'raw' ) %></a></li><% end %>
</ul>
</div>
<div class="span8 well-muted article-message <% if article.internal is true: %> internal<% end %>">
<% if article.from: %>
<div>
<strong title="<%- @Ti( 'From' ) %>: <%= article.from %>"><%= article.from %></strong>
<% if article.actions: %>
<% for action in article.actions: %>
-
<a href="<%= action.href %>" data-type="<%= action.type %>" class="<% if action.class: %><%= action.class %><% end %>"><%- @T( action.name ) %></a>
<% end %>
<% end %>
- <span class="humanTimeFromNow" data-time="<%- article.created_at %>">?</span>
</div>
<% end %>
<% if article.to: %>
<div title="<%- @Ti( 'To' ) %>: <%= article.to %>"><%= article.to %></div>
<% end %>
<% if article.cc: %>
<div title="<%- @Ti( 'Cc' ) %>: <%= article.cc %>"><%= article.cc %></div>
<% end %>
<% if article.subject: %>
<div title="<%- @Ti( 'Subject' ) %>: <%= article.subject %>"><%= article.subject %></div>
<% end %>
<% if article.attachments: %>
<div>
<% for attachment in article.attachments: %>
<a href="api/ticket_attachment/<%= article.ticket_id %>/<%= article.id %>/<%= attachment.id %>" target="_blank" data-type="attachment" class="" title="<%= attachment.size %>"><%= attachment.filename %></a>
<% end %>
</div>
<% end %>
<hr/>
<div style="white-space:pre-wrap;" class="article-content"><%- article.html %></div>
</div>
</div>
<% end %>

View file

@ -0,0 +1,12 @@
<div class="row article">
<div class="avatar span1 thumbnails">
<img class="thumbnail user-data" data-id="<%= @S('id') %>" src="<%- @S('image') %>" alt="">
</div>
<div class="span8 well-muted article-message">
<form class="form-stacked pull-left ticket-update">
<div class="form-ticket-update"></div>
<div class="form-article-update"></div>
<button type="submit" class="btn btn-primary submit"><%- @T( 'Submit' ) %></button>
</form>
</div>
</div>

View file

@ -0,0 +1,5 @@
<div class="customer_info"></div>
<div class="action_info"></div>
<div class="tag_info"></div>
<div class="link_info"></div>
<div class="text_module"></div>

View file

@ -0,0 +1,10 @@
<div class="span12">
<%= @ticket.group.name %> -
<%- @T( @ticket.ticket_state.name ) %> -
<%- @T( @ticket.ticket_priority.name ) %> -
<span class="humanTimeFromNow" data-time="<%- @ticket.created_at %>">?</span>
<% if !@isCustomer && @ticket.escalation_time: %>
- <%- @T('Escalation in') %>
<span class="humanTimeFromNow escalation" data-time="<%- @ticket.escalation_time %>">?</span>
<% end %>
</div>

View file

@ -0,0 +1 @@
<h1><span contenteditable="true" class="ticket-title-update inline-edit"><%= @P( @ticket.title ) %></span> <small><%= @ticket.number %></small></h1>