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
|
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 ) ) )
|
||||||
|
|
||||||
|
|
|
@ -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) ->
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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(/\./)
|
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
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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',
|
||||||
|
|
Loading…
Reference in a new issue