From 75ac4252f3d868459923d09ebaede9d0041f2bfc Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Tue, 5 Dec 2017 15:49:59 +0100 Subject: [PATCH] Implemented issue #195 - Take over attachment on ticket split. --- .../controllers/_ui_element/richtext.coffee | 71 +++++++++---------- .../controllers/agent_ticket_create.coffee | 33 +++++---- .../app/controllers/layout_ref.coffee | 20 +++--- .../ticket_zoom/article_new.coffee | 67 +++++++++-------- .../app/views/generic/attachment_item.jst.eco | 6 +- app/controllers/ticket_articles_controller.rb | 13 ++-- app/controllers/tickets_controller.rb | 22 +++++- 7 files changed, 128 insertions(+), 104 deletions(-) diff --git a/app/assets/javascripts/app/controllers/_ui_element/richtext.coffee b/app/assets/javascripts/app/controllers/_ui_element/richtext.coffee index f3cba6f7b..387a35a8f 100644 --- a/app/assets/javascripts/app/controllers/_ui_element/richtext.coffee +++ b/app/assets/javascripts/app/controllers/_ui_element/richtext.coffee @@ -1,8 +1,7 @@ # coffeelint: disable=camel_case_classes class App.UiElement.richtext - @render: (attribute) -> - - item = $( App.view('generic/richtext')( attribute: attribute ) ) + @render: (attribute, params) -> + item = $( App.view('generic/richtext')(attribute: attribute) ) item.find('[contenteditable]').ce( mode: attribute.type maxlength: attribute.maxlength @@ -15,42 +14,42 @@ class App.UiElement.richtext new App[plugin.controller](params) if attribute.upload - item.append( $( App.view('generic/attachment')( attribute: attribute ) ) ) + @attachments = [] + item.append( $( App.view('generic/attachment')(attribute: attribute) ) ) - renderAttachment = (file) => - item.find('.attachments').append( App.view('generic/attachment_item')( - fileName: file.filename - fileSize: App.Utils.humanFileSize(file.size) - store_id: file.store_id - )) - item.on( - 'click' - "[data-id=#{file.store_id}]", (e) => - @attachments = _.filter( - @attachments, - (item) -> - return if item.id isnt file.store_id - item - ) - store_id = $(e.currentTarget).data('id') + renderFile = (file) => + item.find('.attachments').append(App.view('generic/attachment_item')(file)) + @attachments.push file - # delete attachment from storage - App.Ajax.request( - type: 'DELETE' - url: "#{App.Config.get('api_path')}/ticket_attachment_upload" - data: JSON.stringify(store_id: store_id), - processData: false - ) + if params && params.attachments + for file in params.attachments + renderFile(file) - # remove attachment from dom - element = $(e.currentTarget).closest('.attachments') - $(e.currentTarget).closest('.attachment').remove() - # empty .attachment (remove spaces) to keep css working, thanks @mrflix :-o - if element.find('.attachment').length == 0 - element.empty() + # remove items + item.find('.attachments').on('click', '.js-delete', (e) => + id = $(e.currentTarget).data('id') + @attachments = _.filter( + @attachments, + (item) -> + return if item.id.toString() is id.toString() + item ) - @attachments = [] + # delete attachment from storage + App.Ajax.request( + type: 'DELETE' + url: "#{App.Config.get('api_path')}/ticket_attachment_upload" + data: JSON.stringify(id: id), + processData: false + ) + + # remove attachment from dom + element = $(e.currentTarget).closest('.attachments') + $(e.currentTarget).closest('.attachment').remove() + if element.find('.attachment').length == 0 + element.empty() + ) + @progressBar = item.find('.attachmentUpload-progressBar') @progressText = item.find('.js-percentage') @attachmentPlaceholder = item.find('.attachmentPlaceholder') @@ -84,7 +83,6 @@ class App.UiElement.richtext # Called after received response from the server onCompleted: (response) => response = JSON.parse(response) - @attachments.push response.data @attachmentPlaceholder.removeClass('hide') @attachmentUpload.addClass('hide') @@ -93,7 +91,7 @@ class App.UiElement.richtext @progressBar.width(parseInt(0) + '%') @progressText.text('') - renderAttachment(response.data) + renderFile(response.data) item.find('input').val('') App.Log.debug 'UiElement.richtext', 'upload complete', response.data @@ -111,4 +109,5 @@ class App.UiElement.richtext ) ) App.Delay.set(u, 100, undefined, 'form_upload') + item diff --git a/app/assets/javascripts/app/controllers/agent_ticket_create.coffee b/app/assets/javascripts/app/controllers/agent_ticket_create.coffee index 617c83f0c..732e9e67a 100644 --- a/app/assets/javascripts/app/controllers/agent_ticket_create.coffee +++ b/app/assets/javascripts/app/controllers/agent_ticket_create.coffee @@ -14,6 +14,8 @@ class App.TicketCreate extends App.Controller # define default type @default_type = 'phone-in' + @formId = App.ControllerForm.formId() + # remember split info if exists @split = '' if @ticket_id && @article_id @@ -158,7 +160,7 @@ class App.TicketCreate extends App.Controller # get data / in case also ticket data for split buildScreen: (params) => - if !params.ticket_id && !params.article_id + if _.isEmpty(params.ticket_id) && _.isEmpty(params.article_id) if !_.isEmpty(params.customer_id) @render(options: { customer_id: params.customer_id }) return @@ -173,6 +175,7 @@ class App.TicketCreate extends App.Controller data: ticket_id: params.ticket_id article_id: params.article_id + form_id: @formId processData: true success: (data, status, xhr) => @@ -194,6 +197,9 @@ class App.TicketCreate extends App.Controller else t.body = App.Utils.text2html(a.body) + # add attachments + t.attachments = data.attachments + # render page @render(options: t) ) @@ -206,18 +212,15 @@ class App.TicketCreate extends App.Controller params = template.options else if App.TaskManager.get(@task_key) && !_.isEmpty(App.TaskManager.get(@task_key).state) params = App.TaskManager.get(@task_key).state + if !_.isEmpty(params['form_id']) + @formId = params['form_id'] - if params['form_id'] - @form_id = params['form_id'] - else - @form_id = App.ControllerForm.formId() - - @html App.view('agent_ticket_create')( + @html(App.view('agent_ticket_create')( head: 'New Ticket' agent: @permissionCheck('ticket.agent') admin: @permissionCheck('admin') - form_id: @form_id - ) + form_id: @formId + )) signatureChanges = (params, attribute, attributes, classname, form, ui) => if attribute && attribute.name is 'group_id' @@ -272,7 +275,7 @@ class App.TicketCreate extends App.Controller } new App.ControllerForm( el: @$('.ticket-form-top') - form_id: @form_id + form_id: @formId model: App.Ticket screen: 'create_top' events: @@ -288,14 +291,14 @@ class App.TicketCreate extends App.Controller new App.ControllerForm( el: @$('.article-form-top') - form_id: @form_id + form_id: @formId model: App.TicketArticle screen: 'create_top' params: params ) new App.ControllerForm( el: @$('.ticket-form-middle') - form_id: @form_id + form_id: @formId model: App.Ticket screen: 'create_middle' events: @@ -310,7 +313,7 @@ class App.TicketCreate extends App.Controller ) new App.ControllerForm( el: @$('.ticket-form-bottom') - form_id: @form_id + form_id: @formId model: App.Ticket screen: 'create_bottom' events: @@ -420,7 +423,7 @@ class App.TicketCreate extends App.Controller body: params.body type_id: type.id sender_id: sender.id - form_id: @form_id + form_id: @formId content_type: 'text/html' } else @@ -432,7 +435,7 @@ class App.TicketCreate extends App.Controller body: params.body type_id: type.id sender_id: sender.id - form_id: @form_id + form_id: @formId content_type: 'text/html' } diff --git a/app/assets/javascripts/app/controllers/layout_ref.coffee b/app/assets/javascripts/app/controllers/layout_ref.coffee index 6b49ed6bc..07ee4bafa 100644 --- a/app/assets/javascripts/app/controllers/layout_ref.coffee +++ b/app/assets/javascripts/app/controllers/layout_ref.coffee @@ -349,7 +349,7 @@ class LayoutRefCommunicationReply extends App.ControllerContent file = @uploadQueue.shift() # console.log "working of", file, "from", @uploadQueue - @fakeUpload file.name, file.size, @workOfUploadQueue + @fakeUpload(file.name, file.size, @workOfUploadQueue) humanFileSize: (size) -> i = Math.floor( Math.log(size) / Math.log(1024) ) @@ -363,27 +363,27 @@ class LayoutRefCommunicationReply extends App.ControllerContent @attachmentPlaceholder.removeClass('hide') @attachmentUpload.addClass('hide') - fakeUpload: (fileName, fileSize, callback) -> + fakeUpload: (filename, size, callback) -> @attachmentPlaceholder.addClass('hide') @attachmentUpload.removeClass('hide') progress = 0 - duration = fileSize / 1024 + duration = size / 1024 for i in [0..100] setTimeout @updateUploadProgress, i*duration/100 , i setTimeout (=> callback() - @renderAttachment(fileName, fileSize) + @renderAttachment(filename, size) ), duration - renderAttachment: (fileName, fileSize) => - @attachments.push([fileName, fileSize]) - @attachmentsHolder.append App.view('generic/attachment_item') - fileName: fileName - fileSize: @humanFileSize(fileSize) - + renderAttachment: (filename, size) => + @attachments.push([filename, size]) + @attachmentsHolder.append(App.view('generic/attachment_item') + filename: filename + size: @humanFileSize(size) + ) App.Config.set( 'layout_ref/communication_reply/:content', LayoutRefCommunicationReply, 'Routes' ) diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee index 42b036c6f..e2c854bae 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee @@ -245,7 +245,7 @@ class App.TicketZoomArticleNew extends App.Controller controller = new App.ControllerForm( el: @$('.recipients') model: - configure_attributes: configure_attributes, + configure_attributes: configure_attributes ) @$('[data-name="body"]').ce({ @@ -255,12 +255,13 @@ class App.TicketZoomArticleNew extends App.Controller }) html5Upload.initialize( - uploadUrl: App.Config.get('api_path') + '/ticket_attachment_upload', - dropContainer: @$('.article-add').get(0), - cancelContainer: @cancelContainer, - inputField: @$('.article-attachment input').get(0), - key: 'File', - data: { form_id: @form_id }, + uploadUrl: App.Config.get('api_path') + '/ticket_attachment_upload' + dropContainer: @$('.article-add').get(0) + cancelContainer: @cancelContainer + inputField: @$('.article-attachment input').get(0) + key: 'File' + data: + form_id: @form_id maxSimultaneousUploads: 1, onFileAdded: (file) => @@ -303,6 +304,8 @@ class App.TicketZoomArticleNew extends App.Controller ) ) + @bindAttachmentDelete() + # show text module UI if !@permissionCheck('ticket.customer') textModule = new App.WidgetTextModule( @@ -737,33 +740,29 @@ class App.TicketZoomArticleNew extends App.Controller @articleNewEdit.parent().removeClass('is-dropTarget') if @dragEventCounter is 0 renderAttachment: (file) => - @attachmentsHolder.append App.view('generic/attachment_item') - fileName: file.filename - fileSize: @humanFileSize( file.size ) - store_id: file.store_id - @attachmentsHolder.on( - 'click' - "[data-id=#{file.store_id}]", (e) => - @attachments = _.filter( - @attachments, - (item) -> - return if item.id isnt file.store_id - item - ) - store_id = $(e.currentTarget).data('id') + @attachmentsHolder.append(App.view('generic/attachment_item')(file)) - # delete attachment from storage - App.Ajax.request( - type: 'DELETE' - url: App.Config.get('api_path') + '/ticket_attachment_upload' - data: JSON.stringify(store_id: store_id) - processData: false - ) + bindAttachmentDelete: => + @attachmentsHolder.on('click', '.js-delete', (e) => + id = $(e.currentTarget).data('id') + @attachments = _.filter( + @attachments, + (item) -> + return if item.id.toString() is id.toString() + item + ) - # remove attachment from dom - element = $(e.currentTarget).closest('.attachments') - $(e.currentTarget).closest('.attachment').remove() - # empty .attachment (remove spaces) to keep css working, thanks @mrflix :-o - if element.find('.attachment').length == 0 - element.empty() + # delete attachment from storage + App.Ajax.request( + type: 'DELETE' + url: App.Config.get('api_path') + '/ticket_attachment_upload' + data: JSON.stringify(id: id) + processData: false + ) + + # remove attachment from dom + element = $(e.currentTarget).closest('.attachments') + $(e.currentTarget).closest('.attachment').remove() + if element.find('.attachment').length == 0 + element.empty() ) diff --git a/app/assets/javascripts/app/views/generic/attachment_item.jst.eco b/app/assets/javascripts/app/views/generic/attachment_item.jst.eco index dfa927c95..d4de0ce4a 100644 --- a/app/assets/javascripts/app/views/generic/attachment_item.jst.eco +++ b/app/assets/javascripts/app/views/generic/attachment_item.jst.eco @@ -1,7 +1,7 @@
-
<%= @fileName %>
-
<%= @fileSize %>
-
+
<%= @filename %>
+
<%= @humanFileSize(@size) %>
+
<%- @Icon('diagonal-cross') %><%- @T('Delete File') %>
\ No newline at end of file diff --git a/app/controllers/ticket_articles_controller.rb b/app/controllers/ticket_articles_controller.rb index 6585a43e0..10468c8b5 100644 --- a/app/controllers/ticket_articles_controller.rb +++ b/app/controllers/ticket_articles_controller.rb @@ -150,13 +150,16 @@ class TicketArticlesController < ApplicationController # DELETE /ticket_attachment_upload def ticket_attachment_upload_delete - if params[:store_id] - Store.remove_item(params[:store_id]) + + if params[:id].present? + Store.remove_item(params[:id]) render json: { success: true, } return - elsif params[:form_id] + end + + if params[:form_id].present? Store.remove( object: 'UploadCache', o_id: params[:form_id], @@ -167,7 +170,7 @@ class TicketArticlesController < ApplicationController return end - render json: { message: 'No such store_id or form_id!' }, status: :unprocessable_entity + render json: { message: 'No such id or form_id!' }, status: :unprocessable_entity end # POST /ticket_attachment_upload @@ -198,7 +201,7 @@ class TicketArticlesController < ApplicationController render json: { success: true, data: { - store_id: store.id, + id: store.id, filename: file.original_filename, size: store.size, } diff --git a/app/controllers/tickets_controller.rb b/app/controllers/tickets_controller.rb index dbf33b33f..9b471d5ee 100644 --- a/app/controllers/tickets_controller.rb +++ b/app/controllers/tickets_controller.rb @@ -357,8 +357,28 @@ class TicketsController < ApplicationController article = Ticket::Article.find(params[:article_id]) assets = article.assets(assets) + attachments = [] + if params[:form_id].present? + attachments = Store.list( + object: 'UploadCache', + o_id: params[:form_id], + ).to_a + article.attachments.each do |attachment| + next if attachment.preferences['Content-ID'].present? + file = Store.add( + object: 'UploadCache', + o_id: params[:form_id], + data: attachment.content, + filename: attachment.filename, + preferences: attachment.preferences, + ) + attachments.push file + end + end + render json: { - assets: assets + assets: assets, + attachments: attachments, } end