attachment upload in content layout_ref
This commit is contained in:
parent
a78fb9def7
commit
e811cd173d
4 changed files with 351 additions and 26 deletions
|
@ -10,15 +10,39 @@ App.Config.set( 'layout_ref', Index, 'Routes' )
|
|||
|
||||
|
||||
class Content extends App.ControllerContent
|
||||
elements:
|
||||
'.js-textarea' : 'textarea'
|
||||
'.attachmentPlaceholder': 'attachmentPlaceholder'
|
||||
'.attachmentPlaceholder-inputHolder': 'attachmentInputHolder'
|
||||
'.attachmentPlaceholder-hint': 'attachmentHint'
|
||||
'.ticket-edit': 'ticketEdit'
|
||||
'.attachments': 'attachmentsHolder'
|
||||
'.attachmentUpload': 'attachmentUpload'
|
||||
'.attachmentUpload-progressBar':'progressBar'
|
||||
'.js-percentage': 'progressText'
|
||||
|
||||
events:
|
||||
'hide.bs.dropdown .js-recipientDropdown': 'hideOrganisationMembers'
|
||||
'click .js-organisation': 'showOrganisationMembers'
|
||||
'click .js-back': 'hideOrganisationMembers'
|
||||
'click .js-organisation': 'showOrganisationMembers'
|
||||
'click .js-back': 'hideOrganisationMembers'
|
||||
'focus .js-textarea': 'open_textarea'
|
||||
'input .js-textarea': 'detect_empty_textarea'
|
||||
'dragenter': 'onDragenter'
|
||||
'dragleave': 'onDragleave'
|
||||
'drop': 'onFileDrop'
|
||||
'change input[type=file]': 'onFilePick'
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
@render()
|
||||
|
||||
@textareaHeight =
|
||||
open: 148
|
||||
closed: 38
|
||||
|
||||
@dragEventCounter = 0
|
||||
@attachments = []
|
||||
|
||||
for avatar in @$('.user.avatar')
|
||||
avatar = $(avatar)
|
||||
size = if avatar.hasClass('big') then 50 else 40
|
||||
|
@ -94,6 +118,168 @@ class Content extends App.ControllerContent
|
|||
speed: 300
|
||||
complete: => @organisationList.addClass('hide')
|
||||
|
||||
detect_empty_textarea: =>
|
||||
if !@textarea.text()
|
||||
@add_textarea_catcher()
|
||||
else
|
||||
@remove_textarea_catcher()
|
||||
|
||||
open_textarea: =>
|
||||
if !@textareaCatcher and !@textarea.text() and !@attachments.length
|
||||
@ticketEdit.addClass('is-open')
|
||||
|
||||
@textarea.velocity
|
||||
properties:
|
||||
minHeight: "#{ @textareaHeight.open - 38 }px"
|
||||
marginBottom: 38
|
||||
options:
|
||||
duration: 300
|
||||
easing: 'easeOutQuad'
|
||||
complete: => @add_textarea_catcher()
|
||||
|
||||
# scroll to bottom
|
||||
# @textarea.velocity "scroll",
|
||||
# container: @textarea.scrollParent()
|
||||
# offset: 99999
|
||||
# duration: 300
|
||||
# easing: 'easeOutQuad'
|
||||
# queue: false
|
||||
|
||||
# @editControlItem.velocity "transition.slideRightIn",
|
||||
# duration: 300
|
||||
# stagger: 50
|
||||
# drag: true
|
||||
|
||||
# move attachment text to the left bottom (bottom happens automatically)
|
||||
|
||||
@attachmentPlaceholder.velocity
|
||||
properties:
|
||||
translateX: -@attachmentInputHolder.position().left + "px"
|
||||
options:
|
||||
duration: 300
|
||||
easing: 'easeOutQuad'
|
||||
|
||||
@attachmentHint.velocity
|
||||
properties:
|
||||
opacity: 0
|
||||
options:
|
||||
duration: 300
|
||||
|
||||
add_textarea_catcher: ->
|
||||
@textareaCatcher = new App.clickCatcher
|
||||
holder: @ticketEdit.offsetParent()
|
||||
callback: @close_textarea
|
||||
zIndexScale: 4
|
||||
|
||||
remove_textarea_catcher: ->
|
||||
return if !@textareaCatcher
|
||||
@textareaCatcher.remove()
|
||||
@textareaCatcher = null
|
||||
|
||||
close_textarea: =>
|
||||
@remove_textarea_catcher()
|
||||
if !@textarea.text() && !@attachments.length
|
||||
|
||||
@textarea.velocity
|
||||
properties:
|
||||
minHeight: "#{ @textareaHeight.closed }px"
|
||||
marginBottom: 0
|
||||
options:
|
||||
duration: 300
|
||||
easing: 'easeOutQuad'
|
||||
complete: => @ticketEdit.removeClass('is-open')
|
||||
|
||||
@attachmentPlaceholder.velocity
|
||||
properties:
|
||||
translateX: 0
|
||||
options:
|
||||
duration: 300
|
||||
easing: 'easeOutQuad'
|
||||
|
||||
@attachmentHint.velocity
|
||||
properties:
|
||||
opacity: 1
|
||||
options:
|
||||
duration: 300
|
||||
|
||||
# @editControlItem.css('display', 'none')
|
||||
|
||||
onDragenter: (event) =>
|
||||
# on the first event,
|
||||
# open textarea (it will only open if its closed)
|
||||
@open_textarea() if @dragEventCounter is 0
|
||||
|
||||
@dragEventCounter++
|
||||
@ticketEdit.addClass('is-dropTarget')
|
||||
|
||||
onDragleave: (event) =>
|
||||
@dragEventCounter--
|
||||
|
||||
@ticketEdit.removeClass('is-dropTarget') if @dragEventCounter is 0
|
||||
|
||||
onFileDrop: (event) =>
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
files = event.originalEvent.dataTransfer.files
|
||||
@ticketEdit.removeClass('is-dropTarget')
|
||||
|
||||
@queueUpload(files)
|
||||
|
||||
onFilePick: (event) =>
|
||||
@open_textarea()
|
||||
@queueUpload(event.target.files)
|
||||
|
||||
queueUpload: (files) ->
|
||||
@uploadQueue ?= []
|
||||
|
||||
# add files
|
||||
for file in files
|
||||
@uploadQueue.push(file)
|
||||
|
||||
@workOfUploadQueue()
|
||||
|
||||
workOfUploadQueue: =>
|
||||
if !@uploadQueue.length
|
||||
return
|
||||
|
||||
file = @uploadQueue.shift()
|
||||
# console.log "working of", file, "from", @uploadQueue
|
||||
@fakeUpload file.name, file.size, @workOfUploadQueue
|
||||
|
||||
humanFileSize: (size) =>
|
||||
i = Math.floor( Math.log(size) / Math.log(1024) )
|
||||
return ( size / Math.pow(1024, i) ).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i]
|
||||
|
||||
updateUploadProgress: (progress) =>
|
||||
@progressBar.width(progress + "%")
|
||||
@progressText.text(progress)
|
||||
|
||||
if progress is 100
|
||||
@attachmentPlaceholder.removeClass('hide')
|
||||
@attachmentUpload.addClass('hide')
|
||||
|
||||
fakeUpload: (fileName, fileSize, callback) ->
|
||||
@attachmentPlaceholder.addClass('hide')
|
||||
@attachmentUpload.removeClass('hide')
|
||||
|
||||
progress = 0;
|
||||
duration = fileSize / 1024
|
||||
|
||||
for i in [0..100]
|
||||
setTimeout @updateUploadProgress, i*duration/100 , i
|
||||
|
||||
setTimeout (=>
|
||||
callback()
|
||||
@renderAttachment(fileName, fileSize)
|
||||
), duration
|
||||
|
||||
renderAttachment: (fileName, fileSize) =>
|
||||
@attachments.push([fileName, fileSize])
|
||||
@attachmentsHolder.append App.view('ticket_zoom/attachment')
|
||||
fileName: fileName
|
||||
fileSize: @humanFileSize(fileSize)
|
||||
|
||||
|
||||
App.Config.set( 'layout_ref/content', Content, 'Routes' )
|
||||
|
||||
|
||||
|
|
|
@ -40,6 +40,64 @@
|
|||
<span class="big user avatar" data-firstname="Luisa" data-lastname="Hofner" data-userid="10"></span>
|
||||
<span class="big user avatar" data-firstname="Clara" data-lastname="Altman" data-userid="11"></span>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>Article Reply</h2>
|
||||
|
||||
<div class="ticket-edit">
|
||||
<div class="article-content zIndex-5">
|
||||
<div class="internal-border">
|
||||
<div class="text-bubble">
|
||||
<div class="bubble-arrow"></div>
|
||||
<div class="js-textarea ticketEdit-body" contenteditable="true"></div>
|
||||
<!-- .text-bubble grows with textarea (and expanding clone) -->
|
||||
<div class="attachments"></div>
|
||||
<!--
|
||||
</div>
|
||||
<div class="attachment horizontal">
|
||||
<div class="attachment-name u-highlight">sega-genesis-box.gif</div>
|
||||
<div class="attachment-size">2.4mb</div>
|
||||
<div class="attachment-delete js-delete align-right u-clickable">
|
||||
<div class="delete icon"></div><%- @T('Delete File') %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="attachment horizontal">
|
||||
<div class="attachment-name u-highlight">license-key.txt</div>
|
||||
<div class="attachment-size">7kb</div>
|
||||
<div class="attachment-delete js-delete align-right u-clickable">
|
||||
<div class="delete icon"></div><%- @T('Delete File') %>
|
||||
</div>
|
||||
</div>
|
||||
</div>-->
|
||||
<div class="article-attachment u-unclickable">
|
||||
<div class="attachmentPlaceholder">
|
||||
<span class="attachmentPlaceholder-hint">Antwort eingeben oder</span>
|
||||
<span class="attachmentPlaceholder-inputHolder u-highlight u-clickable">
|
||||
Dateien wählen..
|
||||
<input multiple="multiple" type="file" name="file" style="position: absolute; right: 0px; top: 0px; font-family: Arial; font-size: 118px; margin: 0px; padding: 0px; cursor: pointer; opacity: 0;">
|
||||
</span>
|
||||
</div>
|
||||
<div class="attachmentUpload hide u-clickable">
|
||||
<div class="horizontal">
|
||||
<div class="u-highlight">
|
||||
<%- @T(' Uploading ') %> (<span class="js-percentage">0</span>%) ...
|
||||
</div>
|
||||
<div class="attachmentUpload-cancel align-right js-cancel u-clickable">
|
||||
<div class="delete icon"></div><%- @T('Cancel Upload') %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="attachmentUpload-progressBar" style="width: 0%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fit dropArea">
|
||||
<div class="dropArea-inner fit centered">
|
||||
<%- @T('Drop Files here') %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
<div class="attachment horizontal">
|
||||
<div class="attachment-name u-highlight"><%- @fileName %></div>
|
||||
<div class="attachment-size"><%- @fileSize %></div>
|
||||
<div class="attachment-delete js-delete align-right u-clickable">
|
||||
<div class="delete icon"></div><%- @T('Delete File') %>
|
||||
</div>
|
||||
</div>
|
|
@ -89,7 +89,7 @@ small {
|
|||
}
|
||||
|
||||
.clickCatcher {
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
@ -105,6 +105,25 @@ small {
|
|||
background: hsla(50,100%,50%,.13);
|
||||
}
|
||||
|
||||
[contenteditable] {
|
||||
margin: -1px;
|
||||
display: block;
|
||||
white-space: pre-wrap;
|
||||
outline-style: none;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 3px;
|
||||
}
|
||||
[contenteditable]:hover,
|
||||
[contenteditable]:focus {
|
||||
border-color: hsl(145,51%,45%);
|
||||
}
|
||||
[contenteditable].invalid {
|
||||
border-color: #F92;
|
||||
}
|
||||
[contenteditable] > .placeholder {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.close,
|
||||
.close:hover {
|
||||
float: none;
|
||||
|
@ -2587,6 +2606,19 @@ footer {
|
|||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
.dropArea {
|
||||
background: white;
|
||||
border: 5px solid;
|
||||
color: hsl(202,66%,55%);
|
||||
font-size: 20px;
|
||||
margin: 5px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ticket-edit.is-dropTarget .dropArea {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.edit-controls {
|
||||
position: relative;
|
||||
}
|
||||
|
@ -2766,10 +2798,10 @@ footer {
|
|||
border-color: #b3b3b3;
|
||||
white-space: normal;
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.ticket-edit textarea {
|
||||
.ticket-edit textarea,
|
||||
.ticketEdit-body {
|
||||
width: 100%;
|
||||
height: 38px;
|
||||
padding: 10px;
|
||||
|
@ -2780,6 +2812,11 @@ footer {
|
|||
resize: none;
|
||||
}
|
||||
|
||||
.ticketEdit-body {
|
||||
height: auto;
|
||||
min-height: 38px;
|
||||
}
|
||||
|
||||
.ticket-edit .bubble-arrow:after {
|
||||
border-color: #b3b3b3;
|
||||
box-shadow: none;
|
||||
|
@ -2789,19 +2826,75 @@ footer {
|
|||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 10px;
|
||||
width: 100%;
|
||||
right: 10px;
|
||||
height: 38px;
|
||||
padding: 10px 0;
|
||||
color: #b3b3b3;
|
||||
}
|
||||
|
||||
.edit-upload-button {
|
||||
.attachments:not(:empty) {
|
||||
padding: 9px 5px;
|
||||
border-top: 1px solid hsl(0,0%,93%);
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
.attachment {
|
||||
font-size: 13px;
|
||||
padding: 3px 10px 3px 7px;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.attachment:hover {
|
||||
background: hsl(200,20%,97%);
|
||||
}
|
||||
|
||||
.attachment-name {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.attachment-delete {
|
||||
color: hsl(198,19%,72%);
|
||||
text-decoration: underline;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.attachment:hover .attachment-delete {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.attachment-delete .icon {
|
||||
opacity: 0.2;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.attachmentPlaceholder-inputHolder {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.attachmentUpload {
|
||||
color: hsl(198,19%,72%);
|
||||
}
|
||||
|
||||
.attachmentUpload-cancel {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.attachmentUpload .delete.icon {
|
||||
opacity: 0.33;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.attachmentUpload-progressBar {
|
||||
position: absolute;
|
||||
height: 4px;
|
||||
background: hsl(202,66%,55%);
|
||||
left: 0;
|
||||
bottom: -5px;
|
||||
}
|
||||
|
||||
.pop-selector {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
@ -3439,25 +3532,6 @@ footer {
|
|||
margin-top: 1px;
|
||||
}
|
||||
|
||||
[contenteditable] {
|
||||
margin: -1px;
|
||||
display: block;
|
||||
white-space: pre-wrap;
|
||||
outline-style: none;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 3px;
|
||||
}
|
||||
[contenteditable]:hover,
|
||||
[contenteditable]:focus {
|
||||
border-color: hsl(145,51%,45%);
|
||||
}
|
||||
[contenteditable].invalid {
|
||||
border-color: #F92;
|
||||
}
|
||||
[contenteditable] > .placeholder {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.userSearch {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue