From f3ff650bfea78c042468b96a700832bfa9cda95a Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Tue, 14 Nov 2017 14:35:31 +0100 Subject: [PATCH] Split of article actions into separate backends. --- .../ticket_zoom/article_action/delete.coffee | 34 ++ .../article_action/email_reply.coffee | 135 ++++++ .../article_action/facebook_reply.coffee | 37 ++ .../article_action/internal.coffee | 40 ++ .../ticket_zoom/article_action/split.coffee | 18 + .../article_action/telegram.coffee | 45 ++ .../article_action/twitter_reply.coffee | 128 ++++++ .../ticket_zoom/article_actions.coffee | 390 +----------------- .../ticket_zoom/article_view_actions.jst.eco | 4 +- 9 files changed, 460 insertions(+), 371 deletions(-) create mode 100644 app/assets/javascripts/app/controllers/ticket_zoom/article_action/delete.coffee create mode 100644 app/assets/javascripts/app/controllers/ticket_zoom/article_action/email_reply.coffee create mode 100644 app/assets/javascripts/app/controllers/ticket_zoom/article_action/facebook_reply.coffee create mode 100644 app/assets/javascripts/app/controllers/ticket_zoom/article_action/internal.coffee create mode 100644 app/assets/javascripts/app/controllers/ticket_zoom/article_action/split.coffee create mode 100644 app/assets/javascripts/app/controllers/ticket_zoom/article_action/telegram.coffee create mode 100644 app/assets/javascripts/app/controllers/ticket_zoom/article_action/twitter_reply.coffee diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/article_action/delete.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/article_action/delete.coffee new file mode 100644 index 000000000..7436c15f6 --- /dev/null +++ b/app/assets/javascripts/app/controllers/ticket_zoom/article_action/delete.coffee @@ -0,0 +1,34 @@ +class Delete + @action: (actions, ticket, article, ui) -> + return actions if ui.permissionCheck('ticket.customer') + + if article.type.name is 'note' + user = undefined + if App.Session.get('id') == article.created_by_id + user = App.User.find(App.Session.get('id')) + if user.permission('ticket.agent') + actions.push { + name: 'delete' + type: 'delete' + icon: 'trash' + href: '#' + } + + actions + + @perform: (articleContainer, type, ticket, article, ui) -> + return true if type isnt 'delete' + + callback = -> + article = App.TicketArticle.find(article.id) + article.destroy() + + new App.ControllerConfirm( + message: 'Sure?' + callback: callback + container: ui.el.closest('.content') + ) + + true + +App.Config.set('900-Delete', Delete, 'TicketZoomArticleAction') diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/article_action/email_reply.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/article_action/email_reply.coffee new file mode 100644 index 000000000..eacd9cf14 --- /dev/null +++ b/app/assets/javascripts/app/controllers/ticket_zoom/article_action/email_reply.coffee @@ -0,0 +1,135 @@ +class EmailReply extends App.Controller + @action: (actions, ticket, article, ui) -> + return actions if ui.permissionCheck('ticket.customer') + + group = ticket.group + if group.email_address_id && (article.type.name is 'email' || article.type.name is 'web') + actions.push { + name: 'reply' + type: 'emailReply' + icon: 'reply' + href: '#' + } + recipients = [] + if article.sender.name is 'Customer' + if article.from + localRecipients = emailAddresses.parseAddressList(article.from) + if localRecipients + recipients = recipients.concat localRecipients + if article.to + localRecipients = emailAddresses.parseAddressList(article.to) + if localRecipients + recipients = recipients.concat localRecipients + if article.cc + localRecipients = emailAddresses.parseAddressList(article.cc) + if localRecipients + recipients = recipients.concat localRecipients + + # remove system addresses + localAddresses = App.EmailAddress.all() + forgeinRecipients = [] + recipientUsed = {} + for recipient in recipients + if !_.isEmpty(recipient.address) + localRecipientAddress = recipient.address.toString().toLowerCase() + if !recipientUsed[localRecipientAddress] + recipientUsed[localRecipientAddress] = true + localAddress = false + for address in localAddresses + if localRecipientAddress is address.email.toString().toLowerCase() + recipientUsed[localRecipientAddress] = true + localAddress = true + if !localAddress + forgeinRecipients.push recipient + + # check if reply all is neede + if forgeinRecipients.length > 1 + actions.push { + name: 'reply all' + type: 'emailReplyAll' + icon: 'reply-all' + href: '#' + } + if article.sender.name is 'Customer' && article.type.name is 'phone' + actions.push { + name: 'reply' + type: 'emailReply' + icon: 'reply' + href: '#' + } + if article.sender.name is 'Agent' && article.type.name is 'phone' + actions.push { + name: 'reply' + type: 'emailReply' + icon: 'reply' + href: '#' + } + + actions + + @perform: (articleContainer, type, ticket, article, ui) -> + return true if type isnt 'emailReply' && type isnt 'emailReplyAll' + + if type isnt 'emailReply' + @emailReply(true, ticket, article, ui) + + else if type isnt 'emailReplyAll' + @emailReply(false, ticket, article, ui) + + true + + @emailReply: (all = false, ticket, article, ui) -> + + # get reference article + type = App.TicketArticleType.find(article.type_id) + article_created_by = App.User.find(article.created_by_id) + email_addresses = App.EmailAddress.all() + + ui.scrollToCompose() + + # empty form + articleNew = App.Utils.getRecipientArticle(ticket, article, article_created_by, type, email_addresses, all) + + # get current body + body = ui.el.closest('.ticketZoom').find('.article-add [data-name="body"]').html() || '' + + # check if quote need to be added + signaturePosition = 'bottom' + selected = App.ClipBoard.getSelected('html') + if selected + selected = App.Utils.htmlCleanup(selected).html() + if !selected + selected = App.ClipBoard.getSelected('text') + if selected + selected = App.Utils.textCleanup(selected) + selected = App.Utils.text2html(selected) + + # full quote, if needed + if !selected && article && App.Config.get('ui_ticket_zoom_article_email_full_quote') + signaturePosition = 'top' + if article.content_type.match('html') + selected = App.Utils.textCleanup(article.body) + if article.content_type.match('plain') + selected = App.Utils.textCleanup(article.body) + selected = App.Utils.text2html(selected) + + if selected + selected = "


#{selected}

" + + # add selected text to body + body = selected + body + + articleNew.body = body + + type = App.TicketArticleType.findByAttribute(name:'email') + + App.Event.trigger('ui::ticket::setArticleType', { + ticket: ticket + type: type + article: articleNew + signaturePosition: signaturePosition + }) + + true + +App.Config.set('200-EmailReply', EmailReply, 'TicketZoomArticleAction') diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/article_action/facebook_reply.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/article_action/facebook_reply.coffee new file mode 100644 index 000000000..41c9ad4e8 --- /dev/null +++ b/app/assets/javascripts/app/controllers/ticket_zoom/article_action/facebook_reply.coffee @@ -0,0 +1,37 @@ +class FacebookReply + @action: (actions, ticket, article, ui) -> + return actions if ui.permissionCheck('ticket.customer') + + if article.type.name is 'facebook feed post' || article.type.name is 'facebook feed comment' + actions.push { + name: 'reply' + type: 'facebookFeedReply' + icon: 'reply' + href: '#' + } + + actions + + @perform: (articleContainer, type, ticket, article, ui) -> + return true if type isnt 'facebookFeedReply' + + ui.scrollToCompose() + + type = App.TicketArticleType.findByAttribute('name', 'facebook feed comment') + + articleNew = { + to: '' + cc: '' + body: '' + in_reply_to: '' + } + + App.Event.trigger('ui::ticket::setArticleType', { + ticket: ticket + type: type + article: articleNew + }) + + true + +App.Config.set('300-FacebookReply', FacebookReply, 'TicketZoomArticleAction') diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/article_action/internal.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/article_action/internal.coffee new file mode 100644 index 000000000..8fc1e88bd --- /dev/null +++ b/app/assets/javascripts/app/controllers/ticket_zoom/article_action/internal.coffee @@ -0,0 +1,40 @@ +class Internal + @action: (actions, ticket, article, ui) -> + return actions if ui.permissionCheck('ticket.customer') + + if article.internal is true + actions.push { + name: 'set to public' + type: 'public' + icon: 'lock-open' + } + else + actions.push { + name: 'set to internal' + type: 'internal' + icon: 'lock' + } + + actions + + @perform: (articleContainer, type, ticket, article, ui) -> + return true if type isnt 'internal' && type isnt 'public' + + # storage update + internal = true + if article.internal == true + internal = false + ui.lastAttributres.internal = internal + article.updateAttributes(internal: internal) + + # runtime update + if internal + articleContainer.addClass('is-internal') + else + articleContainer.removeClass('is-internal') + + ui.render() + + true + +App.Config.set('100-Internal', Internal, 'TicketZoomArticleAction') diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/article_action/split.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/article_action/split.coffee new file mode 100644 index 000000000..716267dd2 --- /dev/null +++ b/app/assets/javascripts/app/controllers/ticket_zoom/article_action/split.coffee @@ -0,0 +1,18 @@ +class Split + @action: (actions, ticket, article, ui) -> + return actions if ui.permissionCheck('ticket.customer') + + actions.push { + name: 'split' + type: 'split' + icon: 'split' + href: "#ticket/create/#{article.ticket_id}/#{article.id}" + } + actions + + @perform: (articleContainer, type, ticket, article, ui) -> + return true if type isnt 'split' + ui.navigate "#ticket/create/#{article.ticket_id}/#{article.id}" + true + +App.Config.set('700-Split', Split, 'TicketZoomArticleAction') diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/article_action/telegram.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/article_action/telegram.coffee new file mode 100644 index 000000000..6f18a172d --- /dev/null +++ b/app/assets/javascripts/app/controllers/ticket_zoom/article_action/telegram.coffee @@ -0,0 +1,45 @@ +class TelegramReply + @action: (actions, ticket, article, ui) -> + return actions if ui.permissionCheck('ticket.customer') + + if article.sender.name is 'Customer' && article.type.name is 'telegram personal-message' + actions.push { + name: 'reply' + type: 'telegramPersonalMessageReply' + icon: 'reply' + href: '#' + } + + actions + + @perform: (articleContainer, type, ticket, article, ui) -> + return true if type isnt 'telegramPersonalMessageReply' + + ui.scrollToCompose() + + # get reference article + type = App.TicketArticleType.find(article.type_id) + + articleNew = { + to: '' + cc: '' + body: '' + in_reply_to: '' + } + + if article.message_id + articleNew.in_reply_to = article.message_id + + # get current body + articleNew.body = ui.el.closest('.ticketZoom').find('.article-add [data-name="body"]').html().trim() || '' + + App.Event.trigger('ui::ticket::setArticleType', { + ticket: ticket + type: type + article: articleNew + position: 'end' + }) + + true + +App.Config.set('300-TelegramReply', TelegramReply, 'TicketZoomArticleAction') diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/article_action/twitter_reply.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/article_action/twitter_reply.coffee new file mode 100644 index 000000000..8b03ba249 --- /dev/null +++ b/app/assets/javascripts/app/controllers/ticket_zoom/article_action/twitter_reply.coffee @@ -0,0 +1,128 @@ +class TwitterReply + @action: (actions, ticket, article, ui) -> + return actions if ui.permissionCheck('ticket.customer') + + if article.type.name is 'twitter status' + actions.push { + name: 'reply' + type: 'twitterStatusReply' + icon: 'reply' + href: '#' + } + if article.type.name is 'twitter direct-message' + actions.push { + name: 'reply' + type: 'twitterDirectMessageReply' + icon: 'reply' + href: '#' + } + + actions + + @perform: (articleContainer, type, ticket, article, ui) -> + return true if type isnt 'twitterStatusReply' && type isnt 'twitterDirectMessageReply' + + if type is 'twitterStatusReply' + @twitterStatusReply(ticket, article, ui) + + else if type is 'twitterDirectMessageReply' + @twitterDirectMessageReply(ticket, article, ui) + + true + + @twitterStatusReply: (ticket, article, ui) -> + + ui.scrollToCompose() + + # get reference article + type = App.TicketArticleType.find(article.type_id) + + # empty form + articleNew = { + to: '' + cc: '' + body: '' + in_reply_to: '' + } + + if article.message_id + articleNew.in_reply_to = article.message_id + + # get current body + body = ui.el.closest('.ticketZoom').find('.article-add [data-name="body"]').html().trim() || '' + articleNew.body = body + + recipients = article.from + if article.to + if recipients + recipients += ', ' + recipients += article.to + + if recipients + recipientString = '' + recipientScreenNames = recipients.split(',') + for recipientScreenName in recipientScreenNames + if recipientScreenName + recipientScreenName = recipientScreenName.trim().toLowerCase() + + # exclude already listed screen name + exclude = false + if body && body.toLowerCase().match(recipientScreenName) + exclude = true + + # exclude own screen_name + if recipientScreenName is "@#{@ticket.preferences.channel_screen_name}".toLowerCase() + exclude = true + + if exclude is false + if recipientString isnt '' + recipientString += ' ' + recipientString += recipientScreenName + + if body + articleNew.body = "#{recipientString} #{body} " + else + articleNew.body = "#{recipientString} " + + App.Event.trigger('ui::ticket::setArticleType', { + ticket: ticket + type: type + article: articleNew + position: 'end' + }) + + @twitterDirectMessageReply: (ticket, article, ui) -> + + # get reference article + type = App.TicketArticleType.find(article.type_id) + sender = App.TicketArticleSender.find(article.sender_id) + customer = App.User.find(article.created_by_id) + + ui.scrollToCompose() + + # empty form + articleNew = { + to: '' + cc: '' + body: '' + in_reply_to: '' + } + + if article.message_id + articleNew.in_reply_to = article.message_id + + if sender.name is 'Agent' + articleNew.to = article.to + else + articleNew.to = article.from + + if !articleNew.to + articleNew.to = customer.accounts['twitter'].username || customer.accounts['twitter'].uid + + App.Event.trigger('ui::ticket::setArticleType', { + ticket: ticket + type: type + article: articleNew + }) + +App.Config.set('300-TwitterReply', TwitterReply, 'TicketZoomArticleAction') 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 3f42ce106..fbece5315 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom/article_actions.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom/article_actions.coffee @@ -1,21 +1,13 @@ class App.TicketZoomArticleActions extends App.Controller events: - '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' - 'click [data-type=facebookFeedReply]': 'facebookFeedReply' - 'click [data-type=telegramPersonalMessageReply]': 'telegramPersonalMessageReply' - 'click [data-type=delete]': 'delete' + 'click .js-ArticleAction': 'actionPerform' constructor: -> super @render() render: -> - actions = @actionRow(@article) + actions = @actionRow(@ticket, @article) if actions @html App.view('ticket_zoom/article_view_actions')( @@ -25,371 +17,31 @@ class App.TicketZoomArticleActions extends App.Controller else @html '' - publicInternal: (e) => - e.preventDefault() - articleContainer = $(e.target).closest('.ticket-article-item') - 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 - @lastAttributres.internal = internal - article.updateAttributes(internal: internal) - - # runntime update - if internal - articleContainer.addClass('is-internal') - else - articleContainer.removeClass('is-internal') - - @render() - - actionRow: (article) -> - if @permissionCheck('ticket.customer') - return [] - + actionRow: (ticket, article) -> + actionConfig = App.Config.get('TicketZoomArticleAction') + keys = _.keys(actionConfig).sort() actions = [] - if article.internal is true - actions = [ - { - name: 'set to public' - type: 'public' - icon: 'lock-open' - } - ] - else - actions = [ - { - name: 'set to internal' - type: 'internal' - icon: 'lock' - } - ] - #if @article.type.name is 'note' - # actions.push [] - group = @ticket.group - if group.email_address_id && (article.type.name is 'email' || article.type.name is 'web') - actions.push { - name: 'reply' - type: 'emailReply' - icon: 'reply' - href: '#' - } - recipients = [] - if article.sender.name is 'Customer' - if article.from - localRecipients = emailAddresses.parseAddressList(article.from) - if localRecipients - recipients = recipients.concat localRecipients - if article.to - localRecipients = emailAddresses.parseAddressList(article.to) - if localRecipients - recipients = recipients.concat localRecipients - if article.cc - localRecipients = emailAddresses.parseAddressList(article.cc) - if localRecipients - recipients = recipients.concat localRecipients - - # remove system addresses - localAddresses = App.EmailAddress.all() - forgeinRecipients = [] - recipientUsed = {} - for recipient in recipients - if !_.isEmpty(recipient.address) - localRecipientAddress = recipient.address.toString().toLowerCase() - if !recipientUsed[localRecipientAddress] - recipientUsed[localRecipientAddress] = true - localAddress = false - for address in localAddresses - if localRecipientAddress is address.email.toString().toLowerCase() - recipientUsed[localRecipientAddress] = true - localAddress = true - if !localAddress - forgeinRecipients.push recipient - - # check if reply all is neede - if forgeinRecipients.length > 1 - actions.push { - name: 'reply all' - type: 'emailReplyAll' - icon: 'reply-all' - href: '#' - } - if article.sender.name is 'Customer' && article.type.name is 'phone' - actions.push { - name: 'reply' - type: 'emailReply' - icon: 'reply' - href: '#' - } - if article.sender.name is 'Agent' && article.type.name is 'phone' - actions.push { - name: 'reply' - type: 'emailReply' - icon: 'reply' - href: '#' - } - if article.type.name is 'twitter status' - actions.push { - name: 'reply' - type: 'twitterStatusReply' - icon: 'reply' - href: '#' - } - if article.type.name is 'twitter direct-message' - actions.push { - name: 'reply' - type: 'twitterDirectMessageReply' - icon: 'reply' - href: '#' - } - if article.type.name is 'facebook feed post' || article.type.name is 'facebook feed comment' - actions.push { - name: 'reply' - type: 'facebookFeedReply' - icon: 'reply' - href: '#' - } - if article.sender.name is 'Customer' && article.type.name is 'telegram personal-message' - actions.push { - name: 'reply' - type: 'telegramPersonalMessageReply' - icon: 'reply' - href: '#' - } - - actions.push { - name: 'split' - type: 'split' - icon: 'split' - href: '#ticket/create/' + article.ticket_id + '/' + article.id - } - - if article.type.name is 'note' - user = undefined - if App.Session.get('id') == article.created_by_id - user = App.User.find(App.Session.get('id')) - if user.permission('ticket.agent') - actions.push { - name: 'delete' - type: 'delete' - icon: 'trash' - href: '#' - } + for key in keys + config = actionConfig[key] + if config + actions = config.action(actions, ticket, article, @) actions - facebookFeedReply: (e) => + actionPerform: (e) => e.preventDefault() - type = App.TicketArticleType.findByAttribute('name', 'facebook feed comment') - @scrollToCompose() + articleContainer = $(e.target).closest('.ticket-article-item') + type = $(e.currentTarget).attr('data-type') + ticket = App.Ticket.fullLocal(@ticket.id) + article = App.TicketArticle.fullLocal(@article.id) - # empty form - articleNew = { - to: '' - cc: '' - body: '' - in_reply_to: '' - } - - App.Event.trigger('ui::ticket::setArticleType', { ticket: @ticket, type: type, article: articleNew } ) - - twitterStatusReply: (e) => - e.preventDefault() - - # get reference article - article_id = $(e.target).parents('[data-id]').data('id') - article = App.TicketArticle.fullLocal(article_id) - sender = App.TicketArticleSender.find(article.sender_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 - - # get current body - body = @el.closest('.ticketZoom').find('.article-add [data-name="body"]').html().trim() || '' - articleNew.body = body - - recipients = article.from - if article.to - if recipients - recipients += ', ' - recipients += article.to - - if recipients - recipientString = '' - recipientScreenNames = recipients.split(',') - for recipientScreenName in recipientScreenNames - if recipientScreenName - recipientScreenName = recipientScreenName.trim().toLowerCase() - - # exclude already listed screen name - exclude = false - if body && body.toLowerCase().match(recipientScreenName) - exclude = true - - # exclude own screen_name - if recipientScreenName is "@#{@ticket.preferences.channel_screen_name}".toLowerCase() - exclude = true - - if exclude is false - if recipientString isnt '' - recipientString += ' ' - recipientString += recipientScreenName - - if body - articleNew.body = "#{recipientString} #{body} " - else - articleNew.body = "#{recipientString} " - - App.Event.trigger('ui::ticket::setArticleType', { ticket: @ticket, type: type, article: articleNew, position: 'end' } ) - - 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) - sender = App.TicketArticleSender.find(article.sender_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 - - if sender.name is 'Agent' - articleNew.to = article.to - else - articleNew.to = article.from - - if !articleNew.to - 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) - ticket = App.Ticket.fullLocal(article.ticket_id) - type = App.TicketArticleType.find(article.type_id) - article_created_by = App.User.find(article.created_by_id) - email_addresses = App.EmailAddress.all() - - @scrollToCompose() - - # empty form - articleNew = App.Utils.getRecipientArticle(ticket, article, article_created_by, type, email_addresses, all) - - # get current body - body = @el.closest('.ticketZoom').find('.article-add [data-name="body"]').html() || '' - - # check if quote need to be added - signaturePosition = 'bottom' - selected = App.ClipBoard.getSelected('html') - if selected - selected = App.Utils.htmlCleanup(selected).html() - if !selected - selected = App.ClipBoard.getSelected('text') - if selected - selected = App.Utils.textCleanup(selected) - selected = App.Utils.text2html(selected) - - # full quote, if needed - if !selected && article && App.Config.get('ui_ticket_zoom_article_email_full_quote') - signaturePosition = 'top' - if article.content_type.match('html') - selected = App.Utils.textCleanup(article.body) - if article.content_type.match('plain') - selected = App.Utils.textCleanup(article.body) - selected = App.Utils.text2html(selected) - - if selected - selected = "


#{selected}

" - - # add selected text to body - body = selected + body - - articleNew.body = body - - type = App.TicketArticleType.findByAttribute(name:'email') - - App.Event.trigger('ui::ticket::setArticleType', { - ticket: @ticket - type: type - article: articleNew - signaturePosition: signaturePosition - }) - - telegramPersonalMessageReply: (e) => - e.preventDefault() - - # get reference article - article_id = $(e.target).parents('[data-id]').data('id') - article = App.TicketArticle.fullLocal(article_id) - sender = App.TicketArticleSender.find(article.sender_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 - - # get current body - articleNew.body = @el.closest('.ticketZoom').find('.article-add [data-name="body"]').html().trim() || '' - - App.Event.trigger('ui::ticket::setArticleType', { ticket: @ticket, type: type, article: articleNew, position: 'end' } ) - - delete: (e) => - e.preventDefault() - - callback = -> - article_id = $(e.target).parents('[data-id]').data('id') - article = App.TicketArticle.find(article_id) - article.destroy() - - new App.ControllerConfirm( - message: 'Sure?' - callback: callback - container: @el.closest('.content') - ) + actionConfig = App.Config.get('TicketZoomArticleAction') + keys = _.keys(actionConfig).sort() + actions = [] + for key in keys + config = actionConfig[key] + if config + return if !config.perform(articleContainer, type, ticket, article, @) scrollToCompose: => @el.closest('.content').find('.article-add').ScrollTo() diff --git a/app/assets/javascripts/app/views/ticket_zoom/article_view_actions.jst.eco b/app/assets/javascripts/app/views/ticket_zoom/article_view_actions.jst.eco index 26cd41ec2..e0301172b 100644 --- a/app/assets/javascripts/app/views/ticket_zoom/article_view_actions.jst.eco +++ b/app/assets/javascripts/app/views/ticket_zoom/article_view_actions.jst.eco @@ -1,7 +1,7 @@
<% for action in @actions: %> - - <%- @Icon(action.icon, 'article-action-icon') %><%- @T( action.name ) %> + + <%- @Icon(action.icon, 'article-action-icon') %><%- @T(action.name) %> <% end %>
\ No newline at end of file