Packages | Custom attachment

Hi I created a modal controller in which I added a custom file_upload tag which is used to upload files to this controller. I think the files are uploaded to the server using some api I have no idea if they are in some database (this tag is a reworked richtext which has no text entry capability). I don’t know how to download these table attachments now someone could help.

# coffeelint: disable=camel_case_classes
class App.UiElement.file_upload
  @render: (attributeConfig, params, form) ->
    attribute = $.extend(true, {}, attributeConfig)

    if _.isObject(attribute.value)
      attribute.attachments = attribute.value.attachments
      attribute.value = attribute.value.text

    item = $( App.view('generic/file_upload')(attribute: attribute) )

    item.find('a.btn--action[data-action]').on 'click', (event) => @toolButtonClicked(event, form)

    attachments = []


    renderFile = (file) ->
      item.find('.attachments').append(App.view('generic/attachment_item')(file))
      attachments.push file
      if form.richTextUploadRenderCallback
        form.richTextUploadRenderCallback(attribute, attachments)

    if params && params.attachments
      for file in params.attachments
        renderFile(file)

    if attribute.attachments
      for file in attribute.attachments
        renderFile(file)

    App.Event.bind('ui::ticket::addArticleAttachent', (data) ->
      form_id = item.closest('form').find('[name=form_id]').val()

      return if data.form_id isnt form_id
      return if _.isEmpty(data.attachments)
      for file in data.attachments
        renderFile(file)
    , form.form_id)

    # 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
      )
      if form.richTextUploadDeleteCallback
        form.richTextUploadDeleteCallback(attribute, attachments)

      form_id = item.closest('form').find('[name=form_id]').val()

      # delete attachment from storage
      App.Ajax.request(
        type:        'DELETE'
        url:         "#{App.Config.get('api_path')}/upload_caches/#{form_id}/items/#{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()
    )

    App.Delay.set( ->
      uploader = new App.Html5Upload(
        uploadUrl:              "#{App.Config.get('api_path')}/attachments"
        dropContainer:          item.find("[name=#{attribute.name}]")
        cancelContainer:        item.find('.js-cancel')
        inputField:             item.find('input')
        data:
          form_id: item.closest('form').find('[name=form_id]').val()

        onFileStartCallback: ->
          item.find('[contenteditable]').trigger('fileUploadStart')

        onFileCompletedCallback: (response) ->
          renderFile(response.data)
          item.find('input').val('')
          item.find('[contenteditable]').trigger('fileUploadStop', ['completed'])

        onFileAbortedCallback: ->
          item.find('input').val('')
          item.find('[contenteditable]').trigger('fileUploadStop', ['aborted'])

        attachmentPlaceholder: item.find('.attachmentPlaceholder')
        attachmentUpload:      item.find('.attachmentUpload')
        progressBar:           item.find('.attachmentUpload-progressBar')
        progressText:          item.find('.js-percentage')
      )

      uploader.render()
    , 100, undefined, 'form_upload')

    item

  @toolButtonClicked: (event, form) ->
    action = $(event.currentTarget).data('action')
    @toolButtons[action]?.onClick(event, form)

  @toolButtons = {}
  @additions   = {}


  # 1 next, -1 previous
  # jQuery's helper doesn't work because it doesn't include non-element nodes
  @allDirectionalSiblings: (elem, direction, to = null) ->
    if !elem?
      return []

    output = []
    next = elem

    while sibling = App.UiElement.file_upload.directionalSibling(next, direction)
      next = sibling
      if to? and sibling is to
        break

      output.push sibling

    output

  # 1 next, -1 previous
  @directionalSibling: (elem, direction) ->
    if direction > 0
      elem.nextSibling
    else
      elem.previousSibling

  @buildParentsList: (elem, container) ->
    $(elem)
      .parentsUntil(container)
      .toArray()

  @buildParentsListWithSelf: (elem, container) ->
    output = App.UiElement.file_upload.buildParentsList(elem, container)
    output.unshift(elem)
    output

class Asset extends App.ControllerSubContent
  @requiredPermission: 'admin.asset'
  header: __('Lista aktywów')

  events:
    'click .js-description': 'showDescriptionModal'
    'click .js-new-asset': 'showNewAssetModal'

  constructor: ->
    super
    @load()

  load: =>
    @startLoading()

    @ajax(
      id: 'assets_index'
      type: 'GET'
      url: "#{@apiPath}/assets/"
      processData: true
      success: (data) =>
        @stopLoading()
        @render(data)
    )

  removeAsset: (id) =>
    new App.ControllerConfirm(
      message: __('Are you sure?')
      buttonClass: 'btn--danger'
      callback: =>
        @ajax(
          id: 'assets_remove'
          type: 'DELETE'
          url: "#{@apiPath}/assets/#{id}"
          success: =>
            @stopLoading()
            @load()
        )
      container: @el.closest('.content')
    )

  editAssets: (data, id) =>
    assetData = _.find(data, (assetData) -> assetData.id is id)
    @showEditAssetModal(assetData)

  renderTable: (customData, el) =>
    new App.ControllerTable(
      el: el
      overviewAttributes: ['name', 'serial_number', 'organization_id', 'user_id', 'invoice', 'attachments', 'asset_model_id', 'seller_model_id', 'purchase_date', 'purchase_cost', 'description']
      attribute_list: [
        { name: 'name', display: __('Nazwa')},
        { name: 'serial_number', display: __('Numer seryjny') },
        { name: 'organization_id', display: __('Organizacja') },
        { name: 'user_ids', display: __('User') },
        { name: 'invoice', display: __('Faktura')},
        { name: 'attachments', display: __('Załączniki')},
        { name: 'asset_model_id', display: __('Aktywo')},
        { name: 'seller_model_id', display: __('Sprzedawca')},
        { name: 'purchase_date', display: __('Data kupna')},
        { name: 'purchase_cost', display: __('Koszt kupna')},
        { name: 'description', display: __('Opis')},
      ]
      objects: customData
      bindRow:
        events:
          'click': (id) => @editAssets(customData, id)
      customActions: [
        {
          name: 'edit',
          display: __('Edit')
          icon: 'pen'
          class: 'js-edit'
          callback: (id) => @editAssets(customData, id)
        },
        {
          name: 'remove',
          display: __('Remove')
          icon: 'trash'
          class: 'btn--danger js-remove'
          callback: @removeAsset
          available: (assetData) ->
           not assetData.is_synchronized_from_codebase
        },
      ]
    )

  render: (customData) =>
    content = $(App.view('asset/index')(
      hasDescriptionButton: customData.length > 0,
    ))

    if customData.length > 0
      @renderTable(customData, content.find('.js-content-container'))
    else
      content.find('.js-content-container').html(@description())

    @html content

  description: ->
    $(App.view('asset/description')(
      inlineAssetKey: App.Browser.hotkeys().split('+').reverse().join('+') + '+t'
    ))

  showDescriptionModal: =>
    new AssetDescriptionModal
      contentInline: @description()
      container: @el.closest('.content')

  showNewAssetModal: =>
    new AssetModal
      headPrefix: __('New')
      container: @el.closest('.content')
      successCallback: =>
        @load()

  showEditAssetModal: (assetData) =>
    new AssetModal
      headPrefix: __('Edit')
      data: assetData
      container: @el.closest('.content')
      successCallback: =>
        @load()

class AssetDescriptionModal extends App.ControllerModal
  head: __('Description')
  buttonSubmit: __('Close')
  shown: true

  onSubmit: =>
    @close()

class AssetModal extends App.ControllerModal
  head: __('Model')
  shown: true
  buttonSubmit: true
  buttonCancel: true
  large: true

  content: ->
    false

  render: ->
    super

    content = $(App.view('asset/form')())

    @form = new App.ControllerForm(
      el: content.find('.js-form')
      model:
        configure_attributes: [
          { name: 'name', display: __('Nazwa'), tag: 'input', null: false, },
          { name: 'serial_number', display: __('Numer seryjny'), tag: 'input',null: false },
          { name: 'organization_id', display: __('Organization'), tag: 'autocompletion_ajax_customer_organization', multiple: false, null: false, relation: 'Organization', },
          { name: 'user_ids', display: __('User'), tag: 'autocompletion_ajax', relation: 'User', null: true, },
          { name: 'invoice', display: __('Faktura'), tag: 'file_upload', class: 'input', null: true,  },
          { name: 'attachments', display: __('Załączniki'), tag: 'file_upload', class: 'input', null: true,  },
          { name: 'asset_model_id', display: __('Aktywo'), tag: 'autocompletion_ajax', relation: 'AssetModel', null: true, },
          { name: 'seller_model_id', display: __('Sprzedawca'), tag: 'autocompletion_ajax', relation: 'SellerModel', null: true,},
          { name: 'purchase_date', display: __('Data kupna'), tag: 'date', class: 'input', null: true },
          { name: 'purchase_cost', display: __('Koszt kupna'), tag: 'decimal', null: true},
          { name: 'description', display: __('Opis'), tag: 'textarea', class: 'input', null: true},
        ]
      params: @data
    )

    callback = (data) =>
      @objects = data.items
      return if data.items.length >= data.total_count

    @el.find('.modal-body').html(content)
      
  onSubmit: (e) =>
    params = @formParam(e.target)
    error = @form.validate(params)

    if error
      @formValidate(form: e.target, errors: error)
      return false

    isEditing = Boolean(@data)
  
    if isEditing
      @ajax({
      id: 'assets_edit',
      type: 'PUT',
      url: "#{@apiPath}/assets/#{@data.id}",
      data: JSON.stringify(params),
      processData: true,
      success: (data) =>
        @close()
        @successCallback()
      })
      return
    @ajax({
      id: 'assets_add',
      type: 'POST',
      url: "#{@apiPath}/assets/",
      data: JSON.stringify(params),
      processData: true,
      success: (data) =>
        @close()
        @successCallback()
    })

App.Config.set('Asset', { prio: 3400, name: __('Lista aktywów'), parent: '#orders', target: '#orders/assets', controller: Asset, permission: ['admin.assets'] }, 'NavBarAdmin')