Added placeholder support for notification tags (just use :: in notifications or text modules).
This commit is contained in:
parent
65c0d5e0e1
commit
6fb9371302
7 changed files with 177 additions and 13 deletions
|
@ -7,6 +7,13 @@ class App.UiElement.richtext
|
|||
mode: attribute.type
|
||||
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
|
||||
item.append( $( App.view('generic/attachment')( attribute: attribute ) ) )
|
||||
|
||||
|
|
|
@ -328,6 +328,22 @@ class App.UiElement.ticket_perform_action
|
|||
placeholder: 'message'
|
||||
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)
|
||||
|
||||
@humanText: (condition) ->
|
||||
|
|
|
@ -405,7 +405,7 @@ class App.TicketZoomArticleNew extends App.Controller
|
|||
@$('.js-selectableTypes').addClass('hide').filter("[data-type='#{ type }']").removeClass('hide')
|
||||
|
||||
# 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
|
||||
task = App.TaskManager.get(@task_key)
|
||||
if task && task.state && task.state.ticket && task.state.ticket.group_id
|
||||
|
|
|
@ -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
|
|
@ -457,15 +457,20 @@ class App.Utils
|
|||
levels = key.split(/\./)
|
||||
dataRef = objects
|
||||
for level in levels
|
||||
if dataRef[level]
|
||||
if level of dataRef
|
||||
dataRef = dataRef[level]
|
||||
else
|
||||
dataRef = ''
|
||||
break
|
||||
if typeof dataRef is 'function'
|
||||
value = dataRef()
|
||||
else if typeof dataRef is 'string'
|
||||
value = dataRef
|
||||
else if dataRef.toString
|
||||
value = dataRef.toString()
|
||||
else
|
||||
value = ''
|
||||
#console.log( "tag replacement #{key}, #{value} env: ", objects)
|
||||
if value is ''
|
||||
value = '-'
|
||||
value
|
||||
)
|
||||
|
||||
|
|
|
@ -3,11 +3,28 @@ class App.TextModule extends App.Model
|
|||
@extend Spine.Model.Ajax
|
||||
@url: @apiPath + '/text_modules'
|
||||
@configure_attributes = [
|
||||
{ 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: 'content', display: 'Content', tag: 'richtext', limit: 2000, null: false },
|
||||
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
|
||||
{ name: 'active', display: 'Active', tag: 'active', default: true },
|
||||
{ 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: 'content', display: 'Content', tag: 'richtext', limit: 2000, null: false, plugins: [
|
||||
{
|
||||
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_overview = [
|
||||
|
@ -22,9 +39,9 @@ Create Text Modules to **spend less time writing responses**. TextModules can in
|
|||
|
||||
Examples of snippets are:
|
||||
|
||||
* Hallo Frau #{ticket.customer.lastname},
|
||||
* Hallo Herr #{ticket.customer.lastname},
|
||||
* Hallo #{ticket.customer.firstname},
|
||||
* Hello Mrs. #{ticket.customer.lastname},
|
||||
* Hello Mr. #{ticket.customer.lastname},
|
||||
* Hello #{ticket.customer.firstname},
|
||||
* My Name is #{user.firstname},
|
||||
|
||||
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.owner (e. g. ticket.owner.firstname, ticket.owner.lastname)
|
||||
* 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
|
||||
|
|
|
@ -857,7 +857,39 @@ test("check replace tags", function() {
|
|||
equal(verify, result)
|
||||
|
||||
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 = {
|
||||
user: {
|
||||
firstname: 'Bob',
|
||||
|
|
Loading…
Reference in a new issue