Merge branch 'interface' of github.com:martini/zammad into interface

Conflicts:
	app/assets/stylesheets/zzz.css.erb
This commit is contained in:
Martin Edenhofer 2014-09-29 21:04:46 +02:00
commit c48668303a
5 changed files with 353 additions and 26 deletions

View file

@ -14,6 +14,7 @@ class App.clickCatcher extends Spine.Controller
render: ->
@el.addClass("zIndex-#{ @zIndexScale }") if @zIndexScale
@el.on('click', @triggerCallback)
@el.height(@holder.prop('scrollHeight'))
@el.appendTo(@holder)
remove: ->

View file

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

View file

@ -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>

View file

@ -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>

View file

@ -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;
@ -2586,6 +2605,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;
}
@ -2764,10 +2796,11 @@ footer {
border-color: #b3b3b3;
white-space: normal;
border-radius: 5px;
overflow: hidden;
}
.ticket-edit .text-bubble [contenteditable] {
.ticket-edit .text-bubble [contenteditable],
.ticket-edit textarea,
.ticketEdit-body {
width: 100%;
/*height: 38px;*/
min-height: 20px;
@ -2778,6 +2811,11 @@ footer {
resize: none;
}
.ticketEdit-body {
height: auto;
min-height: 38px;
}
.ticket-edit .bubble-arrow:after {
border-color: #b3b3b3;
box-shadow: none;
@ -2787,19 +2825,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;
@ -3437,25 +3531,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;
}