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

This commit is contained in:
Felix Niklas 2015-11-20 12:03:30 +01:00
commit f530720435
11 changed files with 158 additions and 133 deletions

View file

@ -262,15 +262,16 @@ class App.ControllerTable extends App.Controller
# get content # get content
table = App.view('generic/table')( table = App.view('generic/table')(
table_id: @table_id table_id: @table_id
header: @headers header: @headers
objects: @objects attributes: attributes
checkbox: @checkbox objects: @objects
radio: @radio checkbox: @checkbox
groupBy: @groupBy radio: @radio
class: @class groupBy: @groupBy
destroy: destroy class: @class
callbacks: @callbackAttributes destroy: destroy
callbacks: @callbackAttributes
) )
# convert to jquery object # convert to jquery object

View file

@ -40,33 +40,23 @@ class App.TicketZoom extends App.Controller
@interval(update, 1800000, 'pull_check') @interval(update, 1800000, 'pull_check')
# fetch new data if triggered # fetch new data if triggered
@bind( @bind('Ticket:update Ticket:touch', (data) =>
'Ticket:update Ticket:touch'
(data) =>
# check if current ticket has changed # check if current ticket has changed
return if data.id.toString() isnt @ticket_id.toString() return if data.id.toString() isnt @ticket_id.toString()
# check if we already have the request queued # check if we already have the request queued
#@log 'notice', 'TRY', @ticket_id, new Date(data.updated_at), new Date(@ticketUpdatedAtLastCall) #@log 'notice', 'TRY', @ticket_id, new Date(data.updated_at), new Date(@ticketUpdatedAtLastCall)
update = => update = =>
@fetch( @ticket_id, false ) @fetch(@ticket_id, false)
if !@ticketUpdatedAtLastCall || ( new Date(data.updated_at).toString() isnt new Date(@ticketUpdatedAtLastCall).toString() ) if !@ticketUpdatedAtLastCall || ( new Date(data.updated_at).toString() isnt new Date(@ticketUpdatedAtLastCall).toString() )
@delay( update, 1200, 'ticket-zoom-' + @ticket_id ) @delay( update, 1200, 'ticket-zoom-' + @ticket_id )
) )
# rerender view, e. g. on langauge change # rerender view, e. g. on langauge change
@bind 'ui:rerender', => @bind('ui:rerender', =>
return if !@authenticate(true) @fetch(@ticket_id, true)
)
# reset controllers state vars
@shown = false
@initDone = false
@activeState = false
@renderDone = false
# rerender view
@render()
meta: => meta: =>
@ -343,7 +333,7 @@ class App.TicketZoom extends App.Controller
ticket_id: @ticket.id ticket_id: @ticket.id
) )
@article_view = new App.TicketZoomArticleView( @articleView = new App.TicketZoomArticleView(
ticket: @ticket ticket: @ticket
el: @$('.ticket-article') el: @$('.ticket-article')
ui: @ ui: @
@ -369,7 +359,7 @@ class App.TicketZoom extends App.Controller
) )
# show article # show article
@article_view.execute( @articleView.execute(
ticket_article_ids: @ticket_article_ids ticket_article_ids: @ticket_article_ids
) )

View file

@ -93,31 +93,32 @@ class App.TicketZoomArticleNew extends App.Controller
@openTextarea(null, true) @openTextarea(null, true)
# set article type and expand text area # set article type and expand text area
@bind( @bind('ui::ticket::setArticleType', (data) =>
'ui::ticket::setArticleType' return if data.ticket.id isnt @ticket_id
(data) => #@setArticleType(data.type.name)
return if data.ticket.id isnt @ticket_id
#@setArticleType(data.type.name)
@openTextarea(null, true) @openTextarea(null, true)
for key, value of data.article for key, value of data.article
if key is 'body' if key is 'body'
@$('[data-name="' + key + '"]').html(value) @$('[data-name="' + key + '"]').html(value)
else else
@$('[name="' + key + '"]').val(value) @$('[name="' + key + '"]').val(value)
# preselect article type # preselect article type
@setArticleType('email') @setArticleType('email')
) )
# reset new article screen # reset new article screen
@bind( @bind('ui::ticket::taskReset', (data) =>
'ui::ticket::taskReset' return if data.ticket_id isnt @ticket_id
(data) => @type = 'note'
return if data.ticket_id isnt @ticket_id @defaults = {}
@type = 'note' @render()
@defaults = {} )
@render()
# rerender, e. g. on language change
@bind('ui:rerender', =>
@render()
) )
isIE10: -> isIE10: ->
@ -135,7 +136,7 @@ class App.TicketZoomArticleNew extends App.Controller
render: -> render: ->
ticket = App.Ticket.fullLocal( @ticket_id ) ticket = App.Ticket.fullLocal(@ticket_id)
@html App.view('ticket_zoom/article_new')( @html App.view('ticket_zoom/article_new')(
ticket: ticket ticket: ticket

View file

@ -40,16 +40,19 @@ class ArticleViewItem extends App.Controller
@render() @render()
# set expand of text area only once # set expand of text area only once
@bind( @bind('ui::ticket::shown', (data) =>
'ui::ticket::shown' return if data.ticket_id.toString() isnt @ticket.id.toString()
(data) =>
return if data.ticket_id.toString() isnt @ticket.id.toString()
# set highlighter # set highlighter
@setHighlighter() @setHighlighter()
# set see more # set see more
@setSeeMore() @setSeeMore()
)
# rerender, e. g. on language change
@bind('ui:rerender', =>
@render(undefined, true)
) )
# subscribe to changes # subscribe to changes
@ -84,7 +87,7 @@ class ArticleViewItem extends App.Controller
@articleAttributesLastUpdate = articleAttributesLastUpdateCheck @articleAttributesLastUpdate = articleAttributesLastUpdateCheck
true true
render: (article) => render: (article, force = false) =>
# get articles # get articles
@article = App.TicketArticle.fullLocal( @ticket_article_id ) @article = App.TicketArticle.fullLocal( @ticket_article_id )
@ -103,7 +106,7 @@ class ArticleViewItem extends App.Controller
@el.removeClass('is-internal') @el.removeClass('is-internal')
# check if rerender is needed # check if rerender is needed
if !@hasChanged(@article) if !force && !@hasChanged(@article)
@lastArticle = @article.attributes() @lastArticle = @article.attributes()
return return

View file

@ -19,6 +19,11 @@ class App.TicketZoomAttributeBar extends App.Controller
@subscribeId = App.Macro.subscribe(@render) @subscribeId = App.Macro.subscribe(@render)
@render() @render()
# rerender, e. g. on language change
@bind('ui:rerender', =>
@render()
)
release: => release: =>
App.Macro.unsubscribe(@subscribeId) App.Macro.unsubscribe(@subscribeId)

View file

@ -1,12 +1,20 @@
class App.TicketZoomMeta extends App.Controller class App.TicketZoomMeta extends App.Controller
constructor: -> constructor: ->
super super
@render()
@ticket = App.Ticket.fullLocal(@ticket.id) # rerender, e. g. on language change
@render(@ticket) @bind('ui:rerender', =>
@subscribeId = @ticket.subscribe(@render) @render()
)
render: (ticket) => render: (ticket) =>
if !ticket
ticket = App.Ticket.fullLocal(@ticket.id)
if !@subscribeId
@subscribeId = @ticket.subscribe(@render)
@html App.view('ticket_zoom/meta')( @html App.view('ticket_zoom/meta')(
ticket: ticket ticket: ticket
isCustomer: @isRole('Customer') isCustomer: @isRole('Customer')

View file

@ -4,12 +4,21 @@ class App.TicketZoomTitle extends App.Controller
constructor: -> constructor: ->
super super
@render()
@ticket = App.Ticket.fullLocal( @ticket.id ) # rerender, e. g. on language change
@subscribeId = @ticket.subscribe(@render) @bind('ui:rerender', =>
@render(@ticket) @render()
)
render: (ticket) => render: (ticket) =>
if !ticket
ticket = App.Ticket.fullLocal(@ticket.id)
if !@subscribeId
@subscribeId = @ticket.subscribe(@render)
@title = ticket.title
# check if render is needed # check if render is needed
if @lastTitle && @lastTitle is ticket.title if @lastTitle && @lastTitle is ticket.title
@ -30,18 +39,19 @@ class App.TicketZoomTitle extends App.Controller
title = $(e.target).ceg() || '' title = $(e.target).ceg() || ''
# update title # update title
if title isnt @ticket.title if title isnt @title
@ticket.title = title ticket = App.Ticket.find(@ticket.id)
ticket.title = title
# reset article - should not be resubmited on next ticket update # reset article - should not be resubmited on next ticket update
@ticket.article = undefined ticket.article = undefined
@ticket.save() ticket.save()
App.TaskManager.mute( @task_key ) App.TaskManager.mute(@task_key)
# update taskbar with new meta data # update taskbar with new meta data
App.Event.trigger 'task:render' App.Event.trigger 'task:render'
release: => release: =>
App.Ticket.unsubscribe( @subscribeId ) App.Ticket.unsubscribe(@subscribeId)

View file

@ -34,7 +34,7 @@ class Widget extends App.Controller
$('body') $('body')
.on 'focus.translation', '.translation', (e) -> .on 'focus.translation', '.translation', (e) ->
element = $(e.target) element = $(e.target)
element.data 'before', element.html() element.data 'before', element.text()
element element
.on 'blur.translation', '.translation', (e) => .on 'blur.translation', '.translation', (e) =>
console.log('blur') console.log('blur')
@ -42,12 +42,7 @@ class Widget extends App.Controller
source = element.attr('title') source = element.attr('title')
# get new translation # get new translation
translation_new = element.html() translation_new = element.text()
translation_new = ('' + translation_new)
.replace(/<.+?>/g, '')
# set new translation
element.html(translation_new)
# update translation # update translation
return if element.data('before') is translation_new return if element.data('before') is translation_new
@ -58,7 +53,7 @@ class Widget extends App.Controller
App.i18n.setMap(source, translation_new) App.i18n.setMap(source, translation_new)
# replace rest in page # replace rest in page
$(".translation[title='#{source}']").html(translation_new) $(".translation[title='#{source}']").text(translation_new)
# update permanent translation mapString # update permanent translation mapString
translation = App.Translation.findByAttribute('source', source) translation = App.Translation.findByAttribute('source', source)

View file

@ -1,6 +1,5 @@
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/ # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
#= require_self #= require_self
#= require_tree ./lib/app_init #= require_tree ./lib/app_init
#= require ./config.coffee #= require ./config.coffee
@ -10,10 +9,11 @@
#= require_tree ./lib/app_post #= require_tree ./lib/app_post
class App extends Spine.Controller class App extends Spine.Controller
@viewPrint: (object, attribute_name) -> @viewPrint: (object, attribute_name, attributes) ->
attributes = {} if !attributes
if object.constructor.attributesGet attributes = {}
attributes = object.constructor.attributesGet() if object.constructor.attributesGet
attributes = object.constructor.attributesGet()
attribute_config = attributes[attribute_name] attribute_config = attributes[attribute_name]
value = object[attribute_name] value = object[attribute_name]
valueRef = undefined valueRef = undefined
@ -34,11 +34,9 @@ class App extends Spine.Controller
if parts[0] && parts[1] && object[ parts[0] ] if parts[0] && parts[1] && object[ parts[0] ]
value = object[ parts[0] ][ parts[1] ] value = object[ parts[0] ][ parts[1] ]
#console.log('Pa', attribute_name, object, attribute_config, object[attribute_name], valueRef, value)
# if we have no config, get output this way # if we have no config, get output this way
if !attribute_config if !attribute_config
return @viewPrintItem( value ) return @viewPrintItem(value)
# check if valueRef already exists, no lookup needed later # check if valueRef already exists, no lookup needed later
if !valueRef if !valueRef
@ -48,10 +46,10 @@ class App extends Spine.Controller
if object[attribute_name_without_ref] if object[attribute_name_without_ref]
valueRef = object[attribute_name_without_ref] valueRef = object[attribute_name_without_ref]
return @viewPrintItem( value, attribute_config, valueRef ) @viewPrintItem(value, attribute_config, valueRef)
# define print name helper # define print name helper
@viewPrintItem: ( item, attribute_config = {}, valueRef ) -> @viewPrintItem: (item, attribute_config = {}, valueRef) ->
return '-' if item is undefined return '-' if item is undefined
return '-' if item is '' return '-' if item is ''
return item if !item return item if !item
@ -77,13 +75,13 @@ class App extends Spine.Controller
# execute callback on content # execute callback on content
if attribute_config.callback if attribute_config.callback
result = attribute_config.callback( result, attribute_config ) result = attribute_config.callback(result, attribute_config)
# text2html in textarea view # text2html in textarea view
isHtmlEscape = false isHtmlEscape = false
if attribute_config.tag is 'textarea' if attribute_config.tag is 'textarea'
isHtmlEscape = true isHtmlEscape = true
result = App.Utils.text2html( result ) result = App.Utils.text2html(result)
# remember, html snippets are already escaped # remember, html snippets are already escaped
else if attribute_config.tag is 'richtext' else if attribute_config.tag is 'richtext'
@ -95,9 +93,9 @@ class App extends Spine.Controller
result = attribute_config.options[result] result = attribute_config.options[result]
# translate content # translate content
if attribute_config.translate || ( isObject && item.translate && item.translate() ) if attribute_config.translate || (isObject && item.translate && item.translate())
isHtmlEscape = true isHtmlEscape = true
result = App.i18n.translateContent( result ) result = App.i18n.translateContent(result)
# transform date # transform date
if attribute_config.tag is 'date' if attribute_config.tag is 'date'
@ -121,71 +119,71 @@ class App extends Spine.Controller
result result
@view: (name) -> @view: (name) ->
template = ( params = {} ) -> template = (params = {}) ->
# define print name helper # define print name helper
params.P = ( object, attribute_name ) -> params.P = (object, attribute_name, attributes) ->
App.viewPrint( object, attribute_name ) App.viewPrint(object, attribute_name, attributes)
# define date format helper # define date format helper
params.date = ( time ) -> params.date = (time) ->
return '' if !time return '' if !time
timeObject = new Date(time) timeObject = new Date(time)
d = App.Utils.formatTime( timeObject.getDate(), 2 ) d = App.Utils.formatTime(timeObject.getDate(), 2)
m = App.Utils.formatTime( timeObject.getMonth() + 1, 2 ) m = App.Utils.formatTime(timeObject.getMonth() + 1, 2)
y = timeObject.getFullYear() y = timeObject.getFullYear()
"#{y}-#{m}-#{d}" "#{y}-#{m}-#{d}"
# define datetime format helper # define datetime format helper
params.datetime = ( time ) -> params.datetime = (time) ->
return '' if !time return '' if !time
timeObject = new Date(time) timeObject = new Date(time)
d = App.Utils.formatTime( timeObject.getDate(), 2 ) d = App.Utils.formatTime(timeObject.getDate(), 2)
m = App.Utils.formatTime( timeObject.getMonth() + 1, 2 ) m = App.Utils.formatTime(timeObject.getMonth() + 1, 2)
y = timeObject.getFullYear() y = timeObject.getFullYear()
S = App.Utils.formatTime( timeObject.getSeconds(), 2 ) S = App.Utils.formatTime(timeObject.getSeconds(), 2)
M = App.Utils.formatTime( timeObject.getMinutes(), 2 ) M = App.Utils.formatTime(timeObject.getMinutes(), 2)
H = App.Utils.formatTime( timeObject.getHours(), 2 ) H = App.Utils.formatTime(timeObject.getHours(), 2)
"#{y}-#{m}-#{d} #{H}:#{M}:#{S}" "#{y}-#{m}-#{d} #{H}:#{M}:#{S}"
# define decimal format helper # define decimal format helper
params.decimal = ( data, positions = 2 ) -> params.decimal = (data, positions = 2) ->
App.Utils.decimal(data, positions) App.Utils.decimal(data, positions)
# define translation helper # define translation helper
params.T = ( item, args... ) -> params.T = (item, args...) ->
App.i18n.translateContent( item, args... ) App.i18n.translateContent(item, args...)
# define translation inline helper # define translation inline helper
params.Ti = ( item, args... ) -> params.Ti = (item, args...) ->
App.i18n.translateInline( item, args... ) App.i18n.translateInline(item, args...)
# define translation for date helper # define translation for date helper
params.Tdate = ( item, args... ) -> params.Tdate = (item, args...) ->
App.i18n.translateDate( item, args... ) App.i18n.translateDate(item, args...)
# define translation for timestamp helper # define translation for timestamp helper
params.Ttimestamp = ( item, args... ) -> params.Ttimestamp = (item, args...) ->
App.i18n.translateTimestamp( item, args... ) App.i18n.translateTimestamp(item, args...)
# define linkify helper # define linkify helper
params.L = ( item ) -> params.L = (item) ->
if item && typeof item is 'string' if item && typeof item is 'string'
return App.Utils.linkify( item ) return App.Utils.linkify(item)
item item
# define config helper # define config helper
params.C = ( key ) -> params.C = (key) ->
App.Config.get( key ) App.Config.get(key)
# define session helper # define session helper
params.S = ( key ) -> params.S = (key) ->
App.Session.get( key ) App.Session.get(key)
# define address line helper # define address line helper
params.AddressLine = ( line ) -> params.AddressLine = (line) ->
return '' if !line return '' if !line
items = emailAddresses.parseAddressList(line) items = emailAddresses.parseAddressList(line)
@ -202,15 +200,14 @@ class App extends Spine.Controller
result = result + App.Utils.htmlEscape(item.name) + ' ' result = result + App.Utils.htmlEscape(item.name) + ' '
if item.address if item.address
result = result + " <span class=\"text-muted\">&lt;#{App.Utils.htmlEscape(item.address)}&gt</span>" result = result + " <span class=\"text-muted\">&lt;#{App.Utils.htmlEscape(item.address)}&gt</span>"
result result
# define file size helper # define file size helper
params.humanFileSize = ( size ) -> params.humanFileSize = (size) ->
App.Utils.humanFileSize(size) App.Utils.humanFileSize(size)
# define pretty/human time helper # define pretty/human time helper
params.humanTime = ( time, escalation = false, cssClass = '') -> params.humanTime = (time, escalation = false, cssClass = '') ->
timestamp = App.i18n.translateTimestamp(time) timestamp = App.i18n.translateTimestamp(time)
if escalation if escalation
cssClass += ' escalation' cssClass += ' escalation'
@ -222,7 +219,7 @@ class App extends Spine.Controller
App.Utils.icon(name, className) App.Utils.icon(name, className)
# define richtext helper # define richtext helper
params.RichText = ( string ) -> params.RichText = (string) ->
if string.match(/@T\('/) if string.match(/@T\('/)
string = string.replace(/@T\('(.+?)'\)/g, (match, capture) -> string = string.replace(/@T\('(.+?)'\)/g, (match, capture) ->
App.i18n.translateContent(capture) App.i18n.translateContent(capture)

View file

@ -27,6 +27,11 @@ class App.Log
_instance ?= new _Singleton _instance ?= new _Singleton
_instance.config( type, regex ) _instance.config( type, regex )
@timeTrack: (message) ->
if _instance == undefined
_instance ?= new _Singleton
_instance.timeTrack(message)
class _Singleton class _Singleton
constructor: -> constructor: ->
@moduleColorsMap = {} @moduleColorsMap = {}
@ -115,4 +120,14 @@ class _Singleton
goldenRatio = 0.618033988749895 goldenRatio = 0.618033988749895
@hue += goldenRatio @hue += goldenRatio
@hue = @hue % 1 @hue = @hue % 1
@hue * 360 @hue * 360
timeTrack: (message) =>
currentTime = new Date().getTime()
if !@lastTime
@lastTime = currentTime
console.log('timeTrack start', message)
else
diff = currentTime - @lastTime
@lastTime = currentTime
console.log('timeTrack start', message, diff)

View file

@ -41,7 +41,7 @@
<% groupLast = '' %> <% groupLast = '' %>
<% for object in @objects: %> <% for object in @objects: %>
<% if @groupBy: %> <% if @groupBy: %>
<% groupByName = @P( object, @groupBy ) %> <% groupByName = @P( object, @groupBy, @attributes ) %>
<% if groupLast isnt groupByName: %> <% if groupLast isnt groupByName: %>
<tr class=""><td colspan="<%= length %>"><b><%= groupByName %></b></td></tr> <tr class=""><td colspan="<%= length %>"><b><%= groupByName %></b></td></tr>
<% groupLast = groupByName %> <% groupLast = groupByName %>
@ -68,7 +68,7 @@
</td> </td>
<% end %> <% end %>
<% for item in @header: %> <% for item in @header: %>
<% value = @P( object, item.name ) %> <% value = @P( object, item.name, @attributes ) %>
<% if @callbacks: %> <% if @callbacks: %>
<% if item.name.substr(item.name.length-3, item.name.length) is '_id' && object[ item.name.substr(0, item.name.length-3) ]: %> <% if item.name.substr(item.name.length-3, item.name.length) is '_id' && object[ item.name.substr(0, item.name.length-3) ]: %>
<% refObject = object[ item.name.substr(0, item.name.length-3) ] %> <% refObject = object[ item.name.substr(0, item.name.length-3) ] %>