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')