Added placeholder support for notification tags (just use :: in notifications or text modules).

This commit is contained in:
Martin Edenhofer 2016-05-06 09:53:24 +02:00
parent 65c0d5e0e1
commit 6fb9371302
7 changed files with 177 additions and 13 deletions

View file

@ -7,6 +7,13 @@ class App.UiElement.richtext
mode: attribute.type mode: attribute.type
maxlength: attribute.maxlength maxlength: attribute.maxlength
) )
if attribute.plugins
for plugin in attribute.plugins
params = plugin.params || {}
params.el = item.find('[contenteditable]').parent()
new App[plugin.controller](params)
if attribute.upload if attribute.upload
item.append( $( App.view('generic/attachment')( attribute: attribute ) ) ) item.append( $( App.view('generic/attachment')( attribute: attribute ) ) )

View file

@ -328,6 +328,22 @@ class App.UiElement.ticket_perform_action
placeholder: 'message' placeholder: 'message'
maxlength: 2000 maxlength: 2000
) )
new App.WidgetPlaceholder(
el: notificationElement.find('.js-body div[contenteditable="true"]').parent()
objects: [
{
prefix: 'ticket'
object: 'Ticket'
display: 'Ticket'
},
{
prefix: 'user'
object: 'User'
display: 'Current User'
},
]
)
elementRow.find('.js-setNotification').html(notificationElement) elementRow.find('.js-setNotification').html(notificationElement)
@humanText: (condition) -> @humanText: (condition) ->

View file

@ -405,7 +405,7 @@ class App.TicketZoomArticleNew extends App.Controller
@$('.js-selectableTypes').addClass('hide').filter("[data-type='#{ type }']").removeClass('hide') @$('.js-selectableTypes').addClass('hide').filter("[data-type='#{ type }']").removeClass('hide')
# detect current signature (use current group_id, if not set, use ticket.group_id) # detect current signature (use current group_id, if not set, use ticket.group_id)
ticketCurrent = App.Ticket.find(@ticket_id) ticketCurrent = App.Ticket.fullLocal(@ticket_id)
group_id = ticketCurrent.group_id group_id = ticketCurrent.group_id
task = App.TaskManager.get(@task_key) task = App.TaskManager.get(@task_key)
if task && task.state && task.state.ticket && task.state.ticket.group_id if task && task.state && task.state.ticket && task.state.ticket.group_id

View file

@ -0,0 +1,84 @@
class App.WidgetPlaceholder extends App.Controller
constructor: ->
super
if !@data
@data = {}
# remember instances
@bindElements = []
if @selector
@bindElements = @$( @selector ).textmodule()
else
if @el.attr('contenteditable')
@bindElements = @el.textmodule()
else
@bindElements = @$('[contenteditable]').textmodule()
@update()
update: =>
all = []
ignoreAttributes = {
password: true
active: true
}
ignoreSubAttributes = {
password: true
active: true
created_at: true
updated_at: true
}
# add config
for setting in App.Setting.all()
if setting.preferences && setting.preferences.placeholder
all.push {
id: setting.name
keywords: setting.name
name: "#{App.i18n.translateInline('Config')} > #{setting.name}"
content: content
}
for item in @objects
list = {}
if App[item.object] && App[item.object].configure_attributes
for attribute in App[item.object].configure_attributes
if !ignoreAttributes[attribute.name] && attribute.name.substr(attribute.name.length-4,attribute.name.length) isnt '_ids'
list[attribute.name] = attribute
for name in _.keys(list).sort()
attribute = list[name]
name = "\#{#{item.prefix}.#{attribute.name}}"
content = "\#{#{item.prefix}.#{attribute.name}}"
if attribute.relation
subAttributes = {
name: 'Name'
}
if App[attribute.relation] && App[attribute.relation].configure_attributes
subList = {}
subAttributes = {}
for subAttribute in App[attribute.relation].configure_attributes
if !ignoreSubAttributes[subAttribute.name] && subAttribute.name.substr(subAttribute.name.length-3,subAttribute.name.length) isnt '_id' && subAttribute.name.substr(subAttribute.name.length-4,subAttribute.name.length) isnt '_ids'
subList[subAttribute.name] = subAttribute
for subName in _.keys(subList).sort()
subAttributes[subName] = subList[subName].display
relation = "#{item.prefix}.#{attribute.name.substr(0,attribute.name.length-3)}"
for key, display of subAttributes
name = "\#{#{relation}.#{key}}"
content = "\#{#{relation}.#{key}}"
all.push {
id: name
keywords: name
name: "#{App.i18n.translateInline(item.display)} > #{App.i18n.translateInline(attribute.display)} > #{App.i18n.translateInline(display)}"
content: content
}
else
all.push {
id: name
keywords: name
name: "#{App.i18n.translateInline(item.display)} > #{App.i18n.translateInline(attribute.display)}"
content: content
}
# set new data
if @bindElements[0]
for element in @bindElements
if $(element).data().plugin_textmodule
$(element).data().plugin_textmodule.collection = all

View file

@ -457,15 +457,20 @@ class App.Utils
levels = key.split(/\./) levels = key.split(/\./)
dataRef = objects dataRef = objects
for level in levels for level in levels
if dataRef[level] if level of dataRef
dataRef = dataRef[level] dataRef = dataRef[level]
else
dataRef = ''
break
if typeof dataRef is 'function' if typeof dataRef is 'function'
value = dataRef() value = dataRef()
else if typeof dataRef is 'string' else if dataRef.toString
value = dataRef value = dataRef.toString()
else else
value = '' value = ''
#console.log( "tag replacement #{key}, #{value} env: ", objects) #console.log( "tag replacement #{key}, #{value} env: ", objects)
if value is ''
value = '-'
value value
) )

View file

@ -3,11 +3,28 @@ class App.TextModule extends App.Model
@extend Spine.Model.Ajax @extend Spine.Model.Ajax
@url: @apiPath + '/text_modules' @url: @apiPath + '/text_modules'
@configure_attributes = [ @configure_attributes = [
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, null: false }, { name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, null: false },
{ name: 'keywords', display: 'Keywords', tag: 'input', type: 'text', limit: 100, null: true }, { name: 'keywords', display: 'Keywords', tag: 'input', type: 'text', limit: 100, null: true },
{ name: 'content', display: 'Content', tag: 'richtext', limit: 2000, null: false }, { name: 'content', display: 'Content', tag: 'richtext', limit: 2000, null: false, plugins: [
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 }, {
{ name: 'active', display: 'Active', tag: 'active', default: true }, controller: 'WidgetPlaceholder'
params:
objects: [
{
prefix: 'ticket'
object: 'Ticket'
display: 'Ticket'
},
{
prefix: 'user'
object: 'User'
display: 'Current User'
},
]
}
], note: 'To select placeholders from a list, just enter "::".'},
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
{ name: 'active', display: 'Active', tag: 'active', default: true },
] ]
@configure_delete = true @configure_delete = true
@configure_overview = [ @configure_overview = [
@ -22,9 +39,9 @@ Create Text Modules to **spend less time writing responses**. TextModules can in
Examples of snippets are: Examples of snippets are:
* Hallo Frau #{ticket.customer.lastname}, * Hello Mrs. #{ticket.customer.lastname},
* Hallo Herr #{ticket.customer.lastname}, * Hello Mr. #{ticket.customer.lastname},
* Hallo #{ticket.customer.firstname}, * Hello #{ticket.customer.firstname},
* My Name is #{user.firstname}, * My Name is #{user.firstname},
Of course you can also use multi line snippets. Of course you can also use multi line snippets.
@ -34,6 +51,9 @@ Available objects are:
* ticket.customer (e. g. ticket.customer.firstname, ticket.customer.lastname) * ticket.customer (e. g. ticket.customer.firstname, ticket.customer.lastname)
* ticket.owner (e. g. ticket.owner.firstname, ticket.owner.lastname) * ticket.owner (e. g. ticket.owner.firstname, ticket.owner.lastname)
* ticket.organization (e. g. ticket.organization.name) * ticket.organization (e. g. ticket.organization.name)
* user (e. g. user.firstname, user.email)
To select placeholders from a list, just enter "::".
''' '''
# coffeelint: enable=no_interpolation_in_single_quotes # coffeelint: enable=no_interpolation_in_single_quotes

View file

@ -857,7 +857,39 @@ test("check replace tags", function() {
equal(verify, result) equal(verify, result)
message = "<div>#{user.firstname} #{user.lastname}</div>" message = "<div>#{user.firstname} #{user.lastname}</div>"
result = '<div>Bob </div>' result = '<div>Bob -</div>'
data = {
user: {
firstname: 'Bob',
},
}
verify = App.Utils.replaceTags(message, data)
equal(verify, result)
message = "<div>#{user.firstname} #{user.lastname}</div>"
result = '<div>Bob 0</div>'
data = {
user: {
firstname: 'Bob',
lastname: 0,
},
}
verify = App.Utils.replaceTags(message, data)
equal(verify, result)
message = "<div>#{user.firstname} #{user.lastname}</div>"
result = '<div>Bob -</div>'
data = {
user: {
firstname: 'Bob',
lastname: '',
},
}
verify = App.Utils.replaceTags(message, data)
equal(verify, result)
message = "<div>#{user.firstname} #{user.not.existing.test}</div>"
result = '<div>Bob -</div>'
data = { data = {
user: { user: {
firstname: 'Bob', firstname: 'Bob',