Refactoring of object organization selector.
This commit is contained in:
parent
058bd93fcb
commit
873df9528a
8 changed files with 445 additions and 438 deletions
|
@ -0,0 +1,431 @@
|
||||||
|
class App.ObjectOrganizationAutocompletion extends App.Controller
|
||||||
|
className: 'dropdown js-recipientDropdown'
|
||||||
|
events:
|
||||||
|
'hide.bs.dropdown .js-recipientDropdown': 'hideOrganizationMembers'
|
||||||
|
'click .js-organization': 'showOrganizationMembers'
|
||||||
|
'click .js-back': 'hideOrganizationMembers'
|
||||||
|
'click .js-object': 'onObjectClick'
|
||||||
|
'click .js-objectNew': 'newObject'
|
||||||
|
'focus .js-objectSelect': 'onFocus'
|
||||||
|
'click .js-objectSelect': 'stopPropagation'
|
||||||
|
'blur .js-objectSelect': 'onBlur'
|
||||||
|
'click .form-control': 'focusInput'
|
||||||
|
'click': 'stopPropagation'
|
||||||
|
'change .js-objectId': 'executeCallback'
|
||||||
|
'click .js-remove': 'removeThisToken'
|
||||||
|
|
||||||
|
elements:
|
||||||
|
'.recipientList': 'recipientList'
|
||||||
|
'.js-objectSelect': 'objectSelect'
|
||||||
|
'.js-objectId': 'objectId'
|
||||||
|
'.form-control': 'formControl'
|
||||||
|
|
||||||
|
templateObjectItem: 'generic/object_search/item_object'
|
||||||
|
templateObjectNew: 'generic/object_search/new_object'
|
||||||
|
templateOrganizationItem: 'generic/object_search/item_organization'
|
||||||
|
templateOrganizationItemMembers: 'generic/object_search/item_organization_members'
|
||||||
|
|
||||||
|
objectSingle: 'User'
|
||||||
|
objectIcon: 'user'
|
||||||
|
objectSingels: 'People'
|
||||||
|
objectCreate: 'Create new object'
|
||||||
|
referenceAttribute: 'member_ids'
|
||||||
|
|
||||||
|
constructor: (params) ->
|
||||||
|
super
|
||||||
|
|
||||||
|
@lazySearch = _.debounce(@searchObject, 200)
|
||||||
|
|
||||||
|
@key = Math.floor( Math.random() * 999999 ).toString()
|
||||||
|
|
||||||
|
if !@attribute.source
|
||||||
|
@attribute.source = "#{@apiPath}/search/user-organization"
|
||||||
|
@build()
|
||||||
|
|
||||||
|
# set current value
|
||||||
|
if @attribute.value and @callback
|
||||||
|
@callback(@attribute.value)
|
||||||
|
|
||||||
|
element: =>
|
||||||
|
@el
|
||||||
|
|
||||||
|
release: ->
|
||||||
|
$(window).off 'click.ObjectOrganizationAutocompletion'
|
||||||
|
|
||||||
|
open: =>
|
||||||
|
# prevent rebinding of keydown event
|
||||||
|
return if @el.hasClass 'open'
|
||||||
|
|
||||||
|
@el.addClass('open')
|
||||||
|
$(window).on 'click.ObjectOrganizationAutocompletion', @close
|
||||||
|
$(window).on 'keydown.ObjectOrganizationAutocompletion', @navigateByKeyboard
|
||||||
|
|
||||||
|
close: =>
|
||||||
|
$(window).off 'keydown.ObjectOrganizationAutocompletion'
|
||||||
|
@el.removeClass('open')
|
||||||
|
|
||||||
|
$(window).off 'click.ObjectOrganizationAutocompletion'
|
||||||
|
|
||||||
|
onFocus: =>
|
||||||
|
@formControl.addClass 'focus'
|
||||||
|
@open()
|
||||||
|
|
||||||
|
focusInput: =>
|
||||||
|
@objectSelect.focus() if not @formControl.hasClass 'focus'
|
||||||
|
|
||||||
|
onBlur: =>
|
||||||
|
selectObject = @objectSelect.val()
|
||||||
|
if _.isEmpty(selectObject)
|
||||||
|
@objectId.val('')
|
||||||
|
return
|
||||||
|
if @attribute.guess is true
|
||||||
|
currentObjectId = @objectId.val()
|
||||||
|
if _.isEmpty(currentObjectId) || currentObjectId.match(/^guess:/)
|
||||||
|
if !_.isEmpty(selectObject)
|
||||||
|
@objectId.val("guess:#{selectObject}")
|
||||||
|
@formControl.removeClass 'focus'
|
||||||
|
|
||||||
|
onObjectClick: (e) =>
|
||||||
|
objectId = $(e.currentTarget).data('object-id')
|
||||||
|
@selectObject(objectId)
|
||||||
|
@close()
|
||||||
|
|
||||||
|
selectObject: (objectId) =>
|
||||||
|
if @attribute.multiple and @objectId.val()
|
||||||
|
# add objectId to end of comma separated list
|
||||||
|
objectId = _.chain( @objectId.val().split(',') ).push(objectId).join(',').value()
|
||||||
|
|
||||||
|
@objectSelect.val('')
|
||||||
|
@objectId.val(objectId).trigger('change')
|
||||||
|
|
||||||
|
executeCallback: =>
|
||||||
|
# with @attribute.multiple this can be several objects ids.
|
||||||
|
# Only work with the last one since its the newest one
|
||||||
|
objectId = @objectId.val().split(',').pop()
|
||||||
|
|
||||||
|
return if !objectId
|
||||||
|
return if !App[@objectSingle].exists(objectId)
|
||||||
|
object = App[@objectSingle].find(objectId)
|
||||||
|
name = object.displayName()
|
||||||
|
|
||||||
|
if @attribute.multiple
|
||||||
|
# create token
|
||||||
|
@createToken name, objectId
|
||||||
|
else
|
||||||
|
if object.email
|
||||||
|
name += " <#{object.email}>"
|
||||||
|
|
||||||
|
@objectSelect.val(name)
|
||||||
|
|
||||||
|
if @callback
|
||||||
|
@callback(objectId)
|
||||||
|
|
||||||
|
createToken: (name, objectId) =>
|
||||||
|
@objectSelect.before App.view('generic/token')(
|
||||||
|
name: name
|
||||||
|
value: objectId
|
||||||
|
)
|
||||||
|
|
||||||
|
removeThisToken: (e) =>
|
||||||
|
@removeToken $(e.currentTarget).parents('.token')
|
||||||
|
|
||||||
|
removeToken: (which) =>
|
||||||
|
switch which
|
||||||
|
when 'last'
|
||||||
|
token = @$('.token').last()
|
||||||
|
return if not token.size()
|
||||||
|
else
|
||||||
|
token = which
|
||||||
|
|
||||||
|
# remove objectId from input
|
||||||
|
index = @$('.token').index(token)
|
||||||
|
ids = @objectId.val().split(',')
|
||||||
|
ids.splice(index, 1)
|
||||||
|
@objectId.val ids.join(',')
|
||||||
|
|
||||||
|
token.remove()
|
||||||
|
|
||||||
|
navigateByKeyboard: (e) =>
|
||||||
|
switch e.keyCode
|
||||||
|
# clean input on esc
|
||||||
|
when 27
|
||||||
|
# if org member selection is shown, go back to member list
|
||||||
|
if !@recipientList.hasClass('is-shown')
|
||||||
|
@hideOrganizationMembers()
|
||||||
|
return
|
||||||
|
|
||||||
|
# empty object selection and close
|
||||||
|
@objectSelect.val('').trigger('change')
|
||||||
|
# remove last token on backspace
|
||||||
|
when 8
|
||||||
|
if @objectSelect.val() is ''
|
||||||
|
@removeToken('last')
|
||||||
|
# close on tab
|
||||||
|
when 9 then @close()
|
||||||
|
# ignore left and right
|
||||||
|
when 37, 39 then return
|
||||||
|
# up / select upper item
|
||||||
|
when 38
|
||||||
|
e.preventDefault()
|
||||||
|
if @recipientList.hasClass('is-shown')
|
||||||
|
if @recipientList.find('li.is-active').length is 0
|
||||||
|
@recipientList.find('li').last().addClass('is-active')
|
||||||
|
else
|
||||||
|
if @recipientList.find('li.is-active').prev().length isnt 0
|
||||||
|
@recipientList.find('li.is-active').removeClass('is-active').prev().addClass('is-active')
|
||||||
|
return
|
||||||
|
recipientListOrgMemeber = @$('.recipientList-organizationMembers').not('.hide')
|
||||||
|
if recipientListOrgMemeber.not('.hide').find('li.is-active').length is 0
|
||||||
|
recipientListOrgMemeber.not('.hide').find('li').last().addClass('is-active')
|
||||||
|
else
|
||||||
|
if recipientListOrgMemeber.not('.hide').find('li.is-active').prev().length isnt 0
|
||||||
|
recipientListOrgMemeber.not('.hide').find('li.is-active').removeClass('is-active').prev().addClass('is-active')
|
||||||
|
return
|
||||||
|
# down / select lower item
|
||||||
|
when 40
|
||||||
|
e.preventDefault()
|
||||||
|
if @recipientList.hasClass('is-shown')
|
||||||
|
if @recipientList.find('li.is-active').length is 0
|
||||||
|
@recipientList.find('li').first().addClass('is-active')
|
||||||
|
else
|
||||||
|
if @recipientList.find('li.is-active').next().length isnt 0
|
||||||
|
@recipientList.find('li.is-active').removeClass('is-active').next().addClass('is-active')
|
||||||
|
return
|
||||||
|
recipientListOrgMemeber = @$('.recipientList-organizationMembers').not('.hide')
|
||||||
|
if recipientListOrgMemeber.not('.hide').find('li.is-active').length is 0
|
||||||
|
recipientListOrgMemeber.find('li').first().addClass('is-active')
|
||||||
|
else
|
||||||
|
if recipientListOrgMemeber.not('.hide').find('li.is-active').next().length isnt 0
|
||||||
|
recipientListOrgMemeber.not('.hide').find('li.is-active').removeClass('is-active').next().addClass('is-active')
|
||||||
|
return
|
||||||
|
# enter / take item
|
||||||
|
when 13
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
|
||||||
|
# nav by org member selection
|
||||||
|
if !@recipientList.hasClass('is-shown')
|
||||||
|
recipientListOrganizationMembers = @$('.recipientList-organizationMembers').not('.hide')
|
||||||
|
if recipientListOrganizationMembers.find('.js-back.is-active').get(0)
|
||||||
|
@hideOrganizationMembers()
|
||||||
|
return
|
||||||
|
objectId = recipientListOrganizationMembers.find('li.is-active').data('object-id')
|
||||||
|
return if !objectId
|
||||||
|
@selectObject(objectId)
|
||||||
|
@close() if !@attribute.multiple
|
||||||
|
return
|
||||||
|
|
||||||
|
# nav by object list selection
|
||||||
|
objectId = @recipientList.find('li.is-active').data('object-id')
|
||||||
|
if objectId
|
||||||
|
if objectId is 'new'
|
||||||
|
@newObject()
|
||||||
|
else
|
||||||
|
@selectObject(objectId)
|
||||||
|
@close() if !@attribute.multiple
|
||||||
|
return
|
||||||
|
|
||||||
|
organizationId = @recipientList.find('li.is-active').data('organization-id')
|
||||||
|
return if !organizationId
|
||||||
|
@showOrganizationMembers(undefined, @recipientList.find('li.is-active'))
|
||||||
|
|
||||||
|
|
||||||
|
buildOrganizationItem: (organization) ->
|
||||||
|
objectCount = 0
|
||||||
|
if organization[@referenceAttribute]
|
||||||
|
objectCount = organization[@referenceAttribute].length
|
||||||
|
App.view(@templateOrganizationItem)(
|
||||||
|
organization: organization
|
||||||
|
objectSingels: @objectSingels
|
||||||
|
objectCount: objectCount
|
||||||
|
)
|
||||||
|
|
||||||
|
buildOrganizationMembers: (organization) =>
|
||||||
|
organizationMemebers = $( App.view(@templateOrganizationItemMembers)(
|
||||||
|
organization: organization
|
||||||
|
) )
|
||||||
|
if organization[@referenceAttribute]
|
||||||
|
for objectId in organization[@referenceAttribute]
|
||||||
|
object = App[@objectSingle].fullLocal(objectId)
|
||||||
|
organizationMemebers.append(@buildObjectItem(object))
|
||||||
|
|
||||||
|
buildObjectItem: (object) =>
|
||||||
|
App.view(@templateObjectItem)(
|
||||||
|
object: object
|
||||||
|
icon: @objectIcon
|
||||||
|
)
|
||||||
|
|
||||||
|
buildObjectNew: =>
|
||||||
|
App.view(@templateObjectNew)(
|
||||||
|
objectCreate: @objectCreate
|
||||||
|
)
|
||||||
|
|
||||||
|
build: =>
|
||||||
|
tokens = ''
|
||||||
|
name = ''
|
||||||
|
value = ''
|
||||||
|
|
||||||
|
if @attribute.multiple && @attribute.value
|
||||||
|
|
||||||
|
# fallback for if the value is not an array
|
||||||
|
if typeof @attribute.value isnt 'object'
|
||||||
|
@attribute.value = [@attribute.value]
|
||||||
|
value = @attribute.value.join ','
|
||||||
|
|
||||||
|
# create tokens
|
||||||
|
for objectId in @attribute.value
|
||||||
|
if App[@objectSingle].exists objectId
|
||||||
|
tokens += App.view('generic/token')(
|
||||||
|
name: App[@objectSingle].find(objectId).displayName()
|
||||||
|
value: objectId
|
||||||
|
)
|
||||||
|
else
|
||||||
|
@log 'objectId doesn\'t exist', objectId
|
||||||
|
else
|
||||||
|
value = @attribute.value
|
||||||
|
if value
|
||||||
|
if App[@objectSingle].exists(value)
|
||||||
|
object = App[@objectSingle].find(value)
|
||||||
|
name = object.displayName()
|
||||||
|
if object.email
|
||||||
|
name += " <#{object.email}>"
|
||||||
|
else if @params && @params["#{@attribute.name}_completion"]
|
||||||
|
name = @params["#{@attribute.name}_completion"]
|
||||||
|
else
|
||||||
|
@log 'objectId doesn\'t exist', value
|
||||||
|
|
||||||
|
@html App.view('generic/object_search/input')(
|
||||||
|
attribute: @attribute
|
||||||
|
value: value
|
||||||
|
tokens: tokens
|
||||||
|
name: name
|
||||||
|
)
|
||||||
|
|
||||||
|
if !@attribute.disableCreateObject
|
||||||
|
@recipientList.append(@buildObjectNew())
|
||||||
|
|
||||||
|
# start search
|
||||||
|
@searchTerm = ''
|
||||||
|
|
||||||
|
@objectSelect.on 'keyup', @onKeyUp
|
||||||
|
|
||||||
|
onKeyUp: (e) =>
|
||||||
|
query = $(e.target).val().trim()
|
||||||
|
return if @searchTerm is query
|
||||||
|
@searchTerm = query
|
||||||
|
|
||||||
|
@hideOrganizationMembers()
|
||||||
|
|
||||||
|
# hide dropdown
|
||||||
|
if !query
|
||||||
|
@emptyResultList()
|
||||||
|
|
||||||
|
if !@attribute.disableCreateObject
|
||||||
|
@recipientList.append(@buildObjectNew())
|
||||||
|
|
||||||
|
# show dropdown
|
||||||
|
if query && ( !@attribute.minLengt || @attribute.minLengt <= query.length )
|
||||||
|
@lazySearch(query)
|
||||||
|
|
||||||
|
searchObject: (query) =>
|
||||||
|
@ajax(
|
||||||
|
id: "searchObject#{@key}"
|
||||||
|
type: 'GET'
|
||||||
|
url: @attribute.source
|
||||||
|
data:
|
||||||
|
query: query
|
||||||
|
processData: true
|
||||||
|
success: (data, status, xhr) =>
|
||||||
|
@emptyResultList()
|
||||||
|
|
||||||
|
# load assets
|
||||||
|
App.Collection.loadAssets(data.assets)
|
||||||
|
|
||||||
|
# build markup
|
||||||
|
for item in data.result
|
||||||
|
|
||||||
|
# organization
|
||||||
|
if item.type is 'Organization'
|
||||||
|
organization = App.Organization.fullLocal(item.id)
|
||||||
|
@recipientList.append(@buildOrganizationItem(organization))
|
||||||
|
|
||||||
|
# objectss of organization
|
||||||
|
if organization[@referenceAttribute]
|
||||||
|
@$('.dropdown-menu').append(@buildOrganizationMembers(organization))
|
||||||
|
|
||||||
|
# objectss
|
||||||
|
if item.type is @objectSingle
|
||||||
|
object = App[@objectSingle].fullLocal(item.id)
|
||||||
|
@recipientList.append(@buildObjectItem(object))
|
||||||
|
|
||||||
|
if !@attribute.disableCreateObject
|
||||||
|
@recipientList.append(@buildObjectNew())
|
||||||
|
|
||||||
|
@recipientList.find('.js-object').first().addClass('is-active')
|
||||||
|
)
|
||||||
|
|
||||||
|
emptyResultList: =>
|
||||||
|
@recipientList.empty()
|
||||||
|
@$('.recipientList-organizationMembers').remove()
|
||||||
|
|
||||||
|
showOrganizationMembers: (e,listEntry) =>
|
||||||
|
if e
|
||||||
|
e.stopPropagation()
|
||||||
|
listEntry = $(e.currentTarget)
|
||||||
|
|
||||||
|
organizationId = listEntry.data('organization-id')
|
||||||
|
|
||||||
|
@organizationList = @$("[organization-id=#{ organizationId }]")
|
||||||
|
|
||||||
|
return if !@organizationList.get(0)
|
||||||
|
|
||||||
|
@recipientList.removeClass('is-shown')
|
||||||
|
@$('.recipientList-organizationMembers').addClass('is-shown')
|
||||||
|
|
||||||
|
# move organization-list to the right and slide it in
|
||||||
|
$.Velocity.hook(@organizationList, 'translateX', '100%')
|
||||||
|
@organizationList.removeClass('hide')
|
||||||
|
|
||||||
|
@organizationList.velocity
|
||||||
|
properties:
|
||||||
|
translateX: 0
|
||||||
|
options:
|
||||||
|
speed: 300
|
||||||
|
|
||||||
|
# fade out list
|
||||||
|
@recipientList.velocity
|
||||||
|
properties:
|
||||||
|
translateX: '-100%'
|
||||||
|
options:
|
||||||
|
speed: 300
|
||||||
|
complete: => @recipientList.height(@organizationList.height())
|
||||||
|
|
||||||
|
hideOrganizationMembers: (e) =>
|
||||||
|
e && e.stopPropagation()
|
||||||
|
|
||||||
|
@recipientList.addClass('is-shown')
|
||||||
|
@$('.recipientList-organizationMembers').removeClass('is-shown')
|
||||||
|
|
||||||
|
return if !@organizationList
|
||||||
|
|
||||||
|
# fade list back in
|
||||||
|
@recipientList.velocity
|
||||||
|
properties:
|
||||||
|
translateX: 0
|
||||||
|
options:
|
||||||
|
speed: 300
|
||||||
|
|
||||||
|
# reset list height
|
||||||
|
@recipientList.height('')
|
||||||
|
|
||||||
|
# slide out organization-list and hide it
|
||||||
|
@organizationList.velocity
|
||||||
|
properties:
|
||||||
|
translateX: '100%'
|
||||||
|
options:
|
||||||
|
speed: 300
|
||||||
|
complete: => @organizationList.addClass('hide')
|
||||||
|
|
||||||
|
newObject: (e) ->
|
||||||
|
if e
|
||||||
|
e.preventDefault()
|
|
@ -1,412 +1,11 @@
|
||||||
class App.UserOrganizationAutocompletion extends App.Controller
|
class App.UserOrganizationAutocompletion extends App.ObjectOrganizationAutocompletion
|
||||||
className: 'dropdown js-recipientDropdown'
|
objectSingle: 'User'
|
||||||
events:
|
objectIcon: 'user'
|
||||||
'hide.bs.dropdown .js-recipientDropdown': 'hideOrganizationMembers'
|
objectSingels: 'People'
|
||||||
'click .js-organization': 'showOrganizationMembers'
|
objectCreate: 'Create new Customer'
|
||||||
'click .js-back': 'hideOrganizationMembers'
|
referenceAttribute: 'member_ids'
|
||||||
'click .js-user': 'onUserClick'
|
|
||||||
'click .js-userNew': 'newUser'
|
newObject: (e) =>
|
||||||
'focus .js-userSelect': 'onFocus'
|
|
||||||
'click .js-userSelect': 'stopPropagation'
|
|
||||||
'blur .js-userSelect': 'onBlur'
|
|
||||||
'click .form-control': 'focusInput'
|
|
||||||
'click': 'stopPropagation'
|
|
||||||
'change .js-userId': 'executeCallback'
|
|
||||||
'click .js-remove': 'removeThisToken'
|
|
||||||
|
|
||||||
elements:
|
|
||||||
'.recipientList': 'recipientList'
|
|
||||||
'.js-userSelect': 'userSelect'
|
|
||||||
'.js-userId': 'userId'
|
|
||||||
'.form-control': 'formControl'
|
|
||||||
|
|
||||||
constructor: (params) ->
|
|
||||||
super
|
|
||||||
|
|
||||||
@lazySearch = _.debounce(@searchUser, 200)
|
|
||||||
|
|
||||||
@key = Math.floor( Math.random() * 999999 ).toString()
|
|
||||||
|
|
||||||
if !@attribute.source
|
|
||||||
@attribute.source = "#{@apiPath}/search/user-organization"
|
|
||||||
@build()
|
|
||||||
|
|
||||||
# set current value
|
|
||||||
if @attribute.value and @callback
|
|
||||||
@callback(@attribute.value)
|
|
||||||
|
|
||||||
element: =>
|
|
||||||
@el
|
|
||||||
|
|
||||||
release: ->
|
|
||||||
$(window).off 'click.UserOrganizationAutocompletion'
|
|
||||||
|
|
||||||
open: =>
|
|
||||||
# prevent rebinding of keydown event
|
|
||||||
return if @el.hasClass 'open'
|
|
||||||
|
|
||||||
@el.addClass('open')
|
|
||||||
$(window).on 'click.UserOrganizationAutocompletion', @close
|
|
||||||
$(window).on 'keydown.UserOrganizationAutocompletion', @navigateByKeyboard
|
|
||||||
|
|
||||||
close: =>
|
|
||||||
$(window).off 'keydown.UserOrganizationAutocompletion'
|
|
||||||
@el.removeClass('open')
|
|
||||||
|
|
||||||
$(window).off 'click.UserOrganizationAutocompletion'
|
|
||||||
|
|
||||||
onFocus: =>
|
|
||||||
@formControl.addClass 'focus'
|
|
||||||
@open()
|
|
||||||
|
|
||||||
focusInput: =>
|
|
||||||
@userSelect.focus() if not @formControl.hasClass 'focus'
|
|
||||||
|
|
||||||
onBlur: =>
|
|
||||||
selectUser = @userSelect.val()
|
|
||||||
if _.isEmpty(selectUser)
|
|
||||||
@userId.val('')
|
|
||||||
return
|
|
||||||
if @attribute.guess is true
|
|
||||||
currentUserId = @userId.val()
|
|
||||||
if _.isEmpty(currentUserId) || currentUserId.match(/^guess:/)
|
|
||||||
if !_.isEmpty(selectUser)
|
|
||||||
@userId.val("guess:#{selectUser}")
|
|
||||||
@formControl.removeClass 'focus'
|
|
||||||
|
|
||||||
onUserClick: (e) =>
|
|
||||||
userId = $(e.currentTarget).data('user-id')
|
|
||||||
@selectUser(userId)
|
|
||||||
@close()
|
|
||||||
|
|
||||||
selectUser: (userId) =>
|
|
||||||
if @attribute.multiple and @userId.val()
|
|
||||||
# add userId to end of comma separated list
|
|
||||||
userId = _.chain( @userId.val().split(',') ).push(userId).join(',').value()
|
|
||||||
|
|
||||||
@userSelect.val('')
|
|
||||||
@userId.val(userId).trigger('change')
|
|
||||||
|
|
||||||
executeCallback: =>
|
|
||||||
# with @attribute.multiple this can be several user ids.
|
|
||||||
# Only work with the last one since its the newest one
|
|
||||||
userId = @userId.val().split(',').pop()
|
|
||||||
|
|
||||||
return if !userId
|
|
||||||
return if !App.User.exists(userId)
|
|
||||||
user = App.User.find(userId)
|
|
||||||
name = user.displayName()
|
|
||||||
|
|
||||||
if @attribute.multiple
|
|
||||||
# create token
|
|
||||||
@createToken name, userId
|
|
||||||
else
|
|
||||||
if user.email
|
|
||||||
name += " <#{user.email}>"
|
|
||||||
|
|
||||||
@userSelect.val(name)
|
|
||||||
|
|
||||||
if @callback
|
|
||||||
@callback(userId)
|
|
||||||
|
|
||||||
createToken: (name, userId) =>
|
|
||||||
@userSelect.before App.view('generic/token')(
|
|
||||||
name: name
|
|
||||||
value: userId
|
|
||||||
)
|
|
||||||
|
|
||||||
removeThisToken: (e) =>
|
|
||||||
@removeToken $(e.currentTarget).parents('.token')
|
|
||||||
|
|
||||||
removeToken: (which) =>
|
|
||||||
switch which
|
|
||||||
when 'last'
|
|
||||||
token = @$('.token').last()
|
|
||||||
return if not token.size()
|
|
||||||
else
|
|
||||||
token = which
|
|
||||||
|
|
||||||
# remove userId from input
|
|
||||||
index = @$('.token').index(token)
|
|
||||||
ids = @userId.val().split(',')
|
|
||||||
ids.splice(index, 1)
|
|
||||||
@userId.val ids.join(',')
|
|
||||||
|
|
||||||
token.remove()
|
|
||||||
|
|
||||||
navigateByKeyboard: (e) =>
|
|
||||||
switch e.keyCode
|
|
||||||
# clean input on esc
|
|
||||||
when 27
|
|
||||||
# if org member selection is shown, go back to member list
|
|
||||||
if !@recipientList.hasClass('is-shown')
|
|
||||||
@hideOrganizationMembers()
|
|
||||||
return
|
|
||||||
|
|
||||||
# empty user selection and close
|
|
||||||
@userSelect.val('').trigger('change')
|
|
||||||
# remove last token on backspace
|
|
||||||
when 8
|
|
||||||
if @userSelect.val() is ''
|
|
||||||
@removeToken('last')
|
|
||||||
# close on tab
|
|
||||||
when 9 then @close()
|
|
||||||
# ignore left and right
|
|
||||||
when 37, 39 then return
|
|
||||||
# up / select upper item
|
|
||||||
when 38
|
|
||||||
e.preventDefault()
|
|
||||||
if @recipientList.hasClass('is-shown')
|
|
||||||
if @recipientList.find('li.is-active').length is 0
|
|
||||||
@recipientList.find('li').last().addClass('is-active')
|
|
||||||
else
|
|
||||||
if @recipientList.find('li.is-active').prev().length isnt 0
|
|
||||||
@recipientList.find('li.is-active').removeClass('is-active').prev().addClass('is-active')
|
|
||||||
return
|
|
||||||
recipientListOrgMemeber = @$('.recipientList-organizationMembers').not('.hide')
|
|
||||||
if recipientListOrgMemeber.not('.hide').find('li.is-active').length is 0
|
|
||||||
recipientListOrgMemeber.not('.hide').find('li').last().addClass('is-active')
|
|
||||||
else
|
|
||||||
if recipientListOrgMemeber.not('.hide').find('li.is-active').prev().length isnt 0
|
|
||||||
recipientListOrgMemeber.not('.hide').find('li.is-active').removeClass('is-active').prev().addClass('is-active')
|
|
||||||
return
|
|
||||||
# down / select lower item
|
|
||||||
when 40
|
|
||||||
e.preventDefault()
|
|
||||||
if @recipientList.hasClass('is-shown')
|
|
||||||
if @recipientList.find('li.is-active').length is 0
|
|
||||||
@recipientList.find('li').first().addClass('is-active')
|
|
||||||
else
|
|
||||||
if @recipientList.find('li.is-active').next().length isnt 0
|
|
||||||
@recipientList.find('li.is-active').removeClass('is-active').next().addClass('is-active')
|
|
||||||
return
|
|
||||||
recipientListOrgMemeber = @$('.recipientList-organizationMembers').not('.hide')
|
|
||||||
if recipientListOrgMemeber.not('.hide').find('li.is-active').length is 0
|
|
||||||
recipientListOrgMemeber.find('li').first().addClass('is-active')
|
|
||||||
else
|
|
||||||
if recipientListOrgMemeber.not('.hide').find('li.is-active').next().length isnt 0
|
|
||||||
recipientListOrgMemeber.not('.hide').find('li.is-active').removeClass('is-active').next().addClass('is-active')
|
|
||||||
return
|
|
||||||
# enter / take item
|
|
||||||
when 13
|
|
||||||
e.preventDefault()
|
|
||||||
e.stopPropagation()
|
|
||||||
|
|
||||||
# nav by org member selection
|
|
||||||
if !@recipientList.hasClass('is-shown')
|
|
||||||
recipientListOrganizationMembers = @$('.recipientList-organizationMembers').not('.hide')
|
|
||||||
if recipientListOrganizationMembers.find('.js-back.is-active').get(0)
|
|
||||||
@hideOrganizationMembers()
|
|
||||||
return
|
|
||||||
userId = recipientListOrganizationMembers.find('li.is-active').data('user-id')
|
|
||||||
return if !userId
|
|
||||||
@selectUser(userId)
|
|
||||||
@close() if !@attribute.multiple
|
|
||||||
return
|
|
||||||
|
|
||||||
# nav by user list selection
|
|
||||||
userId = @recipientList.find('li.is-active').data('user-id')
|
|
||||||
if userId
|
|
||||||
if userId is 'new'
|
|
||||||
@newUser()
|
|
||||||
else
|
|
||||||
@selectUser(userId)
|
|
||||||
@close() if !@attribute.multiple
|
|
||||||
return
|
|
||||||
|
|
||||||
organizationId = @recipientList.find('li.is-active').data('organization-id')
|
|
||||||
return if !organizationId
|
|
||||||
@showOrganizationMembers(undefined, @recipientList.find('li.is-active'))
|
|
||||||
|
|
||||||
|
|
||||||
buildOrganizationItem: (organization) ->
|
|
||||||
App.view('generic/user_search/item_organization')(
|
|
||||||
organization: organization
|
|
||||||
)
|
|
||||||
|
|
||||||
buildOrganizationMembers: (organization) =>
|
|
||||||
organizationMemebers = $( App.view('generic/user_search/item_organization_members')(
|
|
||||||
organization: organization
|
|
||||||
) )
|
|
||||||
for userId in organization.member_ids
|
|
||||||
user = App.User.fullLocal(userId)
|
|
||||||
organizationMemebers.append(@buildUserItem(user))
|
|
||||||
|
|
||||||
buildUserItem: (user) ->
|
|
||||||
App.view('generic/user_search/item_user')(
|
|
||||||
user: user
|
|
||||||
)
|
|
||||||
|
|
||||||
buildUserNew: ->
|
|
||||||
App.view('generic/user_search/new_user')()
|
|
||||||
|
|
||||||
build: =>
|
|
||||||
tokens = ''
|
|
||||||
name = ''
|
|
||||||
value = ''
|
|
||||||
|
|
||||||
if @attribute.multiple && @attribute.value
|
|
||||||
|
|
||||||
# fallback for if the value is not an array
|
|
||||||
if typeof @attribute.value isnt 'object'
|
|
||||||
@attribute.value = [@attribute.value]
|
|
||||||
value = @attribute.value.join ','
|
|
||||||
|
|
||||||
# create tokens
|
|
||||||
for userId in @attribute.value
|
|
||||||
if App.User.exists userId
|
|
||||||
tokens += App.view('generic/token')(
|
|
||||||
name: App.User.find(userId).displayName()
|
|
||||||
value: userId
|
|
||||||
)
|
|
||||||
else
|
|
||||||
@log 'userId doesn\'t exist', userId
|
|
||||||
else
|
|
||||||
value = @attribute.value
|
|
||||||
if value
|
|
||||||
if App.User.exists value
|
|
||||||
user = App.User.find(value)
|
|
||||||
name = user.displayName()
|
|
||||||
if user.email
|
|
||||||
name += " <#{user.email}>"
|
|
||||||
else if @params && @params["#{@attribute.name}_completion"]
|
|
||||||
name = @params["#{@attribute.name}_completion"]
|
|
||||||
else
|
|
||||||
@log 'userId doesn\'t exist', value
|
|
||||||
|
|
||||||
@html App.view('generic/user_search/input')(
|
|
||||||
attribute: @attribute
|
|
||||||
value: value
|
|
||||||
tokens: tokens
|
|
||||||
name: name
|
|
||||||
)
|
|
||||||
|
|
||||||
if !@attribute.disableCreateUser
|
|
||||||
@recipientList.append(@buildUserNew())
|
|
||||||
|
|
||||||
# start search
|
|
||||||
@searchTerm = ''
|
|
||||||
|
|
||||||
@userSelect.on 'keyup', @onKeyUp
|
|
||||||
|
|
||||||
onKeyUp: (e) =>
|
|
||||||
query = $(e.target).val().trim()
|
|
||||||
return if @searchTerm is query
|
|
||||||
@searchTerm = query
|
|
||||||
|
|
||||||
@hideOrganizationMembers()
|
|
||||||
|
|
||||||
# hide dropdown
|
|
||||||
if !query
|
|
||||||
@emptyResultList()
|
|
||||||
|
|
||||||
if !@attribute.disableCreateUser
|
|
||||||
@recipientList.append(@buildUserNew())
|
|
||||||
|
|
||||||
# show dropdown
|
|
||||||
if query && ( !@attribute.minLengt || @attribute.minLengt <= query.length )
|
|
||||||
@lazySearch(query)
|
|
||||||
|
|
||||||
searchUser: (query) =>
|
|
||||||
@ajax(
|
|
||||||
id: "searchUser#{@key}"
|
|
||||||
type: 'GET'
|
|
||||||
url: @attribute.source
|
|
||||||
data:
|
|
||||||
query: query
|
|
||||||
processData: true
|
|
||||||
success: (data, status, xhr) =>
|
|
||||||
@emptyResultList()
|
|
||||||
|
|
||||||
# load assets
|
|
||||||
App.Collection.loadAssets(data.assets)
|
|
||||||
|
|
||||||
# build markup
|
|
||||||
for item in data.result
|
|
||||||
|
|
||||||
# organization
|
|
||||||
if item.type is 'Organization'
|
|
||||||
organization = App.Organization.fullLocal(item.id)
|
|
||||||
@recipientList.append(@buildOrganizationItem(organization))
|
|
||||||
|
|
||||||
# users of organization
|
|
||||||
if organization.member_ids
|
|
||||||
@$('.dropdown-menu').append(@buildOrganizationMembers(organization))
|
|
||||||
|
|
||||||
# users
|
|
||||||
if item.type is 'User'
|
|
||||||
user = App.User.fullLocal(item.id)
|
|
||||||
@recipientList.append(@buildUserItem(user))
|
|
||||||
|
|
||||||
if !@attribute.disableCreateUser
|
|
||||||
@recipientList.append(@buildUserNew())
|
|
||||||
|
|
||||||
@recipientList.find('.js-user').first().addClass('is-active')
|
|
||||||
)
|
|
||||||
|
|
||||||
emptyResultList: =>
|
|
||||||
@recipientList.empty()
|
|
||||||
@$('.recipientList-organizationMembers').remove()
|
|
||||||
|
|
||||||
showOrganizationMembers: (e,listEntry) =>
|
|
||||||
if e
|
|
||||||
e.stopPropagation()
|
|
||||||
listEntry = $(e.currentTarget)
|
|
||||||
|
|
||||||
organizationId = listEntry.data('organization-id')
|
|
||||||
|
|
||||||
@organizationList = @$("[organization-id=#{ organizationId }]")
|
|
||||||
|
|
||||||
return if !@organizationList.get(0)
|
|
||||||
|
|
||||||
@recipientList.removeClass('is-shown')
|
|
||||||
@$('.recipientList-organizationMembers').addClass('is-shown')
|
|
||||||
|
|
||||||
# move organization-list to the right and slide it in
|
|
||||||
$.Velocity.hook(@organizationList, 'translateX', '100%')
|
|
||||||
@organizationList.removeClass('hide')
|
|
||||||
|
|
||||||
@organizationList.velocity
|
|
||||||
properties:
|
|
||||||
translateX: 0
|
|
||||||
options:
|
|
||||||
speed: 300
|
|
||||||
|
|
||||||
# fade out list
|
|
||||||
@recipientList.velocity
|
|
||||||
properties:
|
|
||||||
translateX: '-100%'
|
|
||||||
options:
|
|
||||||
speed: 300
|
|
||||||
complete: => @recipientList.height(@organizationList.height())
|
|
||||||
|
|
||||||
hideOrganizationMembers: (e) =>
|
|
||||||
e && e.stopPropagation()
|
|
||||||
|
|
||||||
@recipientList.addClass('is-shown')
|
|
||||||
@$('.recipientList-organizationMembers').removeClass('is-shown')
|
|
||||||
|
|
||||||
return if !@organizationList
|
|
||||||
|
|
||||||
# fade list back in
|
|
||||||
@recipientList.velocity
|
|
||||||
properties:
|
|
||||||
translateX: 0
|
|
||||||
options:
|
|
||||||
speed: 300
|
|
||||||
|
|
||||||
# reset list height
|
|
||||||
@recipientList.height('')
|
|
||||||
|
|
||||||
# slide out organization-list and hide it
|
|
||||||
@organizationList.velocity
|
|
||||||
properties:
|
|
||||||
translateX: '100%'
|
|
||||||
options:
|
|
||||||
speed: 300
|
|
||||||
complete: => @organizationList.addClass('hide')
|
|
||||||
|
|
||||||
newUser: (e) =>
|
|
||||||
if e
|
if e
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
new UserNew(
|
new UserNew(
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="recipientList-name">
|
<div class="recipientList-name">
|
||||||
<%= @organization.displayName() %>
|
<%= @organization.displayName() %>
|
||||||
<span class="recipientList-detail">- <%= @organization.member_ids.length %> <%- @T('People') %></span>
|
<span class="recipientList-detail">- <%= @objectCount %> <%- @T(@objectSingels) %></span>
|
||||||
</div>
|
</div>
|
||||||
<%- @Icon('arrow-right', 'recipientList-arrow') %>
|
<%- @Icon('arrow-right', 'recipientList-arrow') %>
|
||||||
</li>
|
</li>
|
|
@ -1,8 +1,8 @@
|
||||||
<li class="recipientList-entry recipientList--new js-userNew" data-user-id="new">
|
<li class="recipientList-entry recipientList--new js-objectNew" data-object-id="new">
|
||||||
<div class="recipientList-iconSpacer">
|
<div class="recipientList-iconSpacer">
|
||||||
<%- @Icon('plus', 'recipientList-icon') %>
|
<%- @Icon('plus', 'recipientList-icon') %>
|
||||||
</div>
|
</div>
|
||||||
<div class="recipientList-name">
|
<div class="recipientList-name">
|
||||||
<%- @T('Create new Customer') %>
|
<%- @T(@objectCreate) %>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
|
@ -1,12 +0,0 @@
|
||||||
<div class="tokenfield form-control u-positionOrigin">
|
|
||||||
<input class="js-userId" type="hidden" value="<%= @value %>" name="<%- @attribute.name %>" tabindex="-1">
|
|
||||||
<% if @attribute.multiple: %>
|
|
||||||
<%- @tokens %>
|
|
||||||
<% end %>
|
|
||||||
<input name="<%- @attribute.name %>_completion" class="user-select token-input js-userSelect" autocapitalize="off" placeholder="<%- @attribute.placeholder %>" autocomplete="off" role="textbox" aria-autocomplete="list" value="<%= @name %>" aria-haspopup="true">
|
|
||||||
<% if @attribute.disableCreateUser isnt true: %><%- @Icon('arrow-down', 'dropdown-arrow') %><% end %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="dropdown-menu" aria-labelledby="customer_id">
|
|
||||||
<ul class="recipientList" role="menu"></ul>
|
|
||||||
</div>
|
|
|
@ -1,11 +0,0 @@
|
||||||
<li class="recipientList-entry js-user" data-user-id="<%= @user.id %>">
|
|
||||||
<div class="recipientList-iconSpacer">
|
|
||||||
<%- @Icon('user', 'recipientList-icon') %>
|
|
||||||
</div>
|
|
||||||
<div class="recipientList-name">
|
|
||||||
<%= @user.displayName() %>
|
|
||||||
<% if @user.organization: %>
|
|
||||||
<span class="recipientList-detail">- <%= @user.organization.displayName() %></span>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
|
@ -1564,7 +1564,7 @@ wait untill text in selector disabppears
|
||||||
sleep 2.5
|
sleep 2.5
|
||||||
|
|
||||||
element.send_keys(:enter)
|
element.send_keys(:enter)
|
||||||
#instance.find_elements(css: params[:css] + ' .recipientList-entry.js-user.is-active')[0].click
|
#instance.find_elements(css: params[:css] + ' .recipientList-entry.js-object.is-active')[0].click
|
||||||
sleep 0.4
|
sleep 0.4
|
||||||
assert(true, 'ticket_customer_select')
|
assert(true, 'ticket_customer_select')
|
||||||
end
|
end
|
||||||
|
@ -1928,7 +1928,7 @@ wait untill text in selector disabppears
|
||||||
# ff issue, sometimes enter event gets dropped
|
# ff issue, sometimes enter event gets dropped
|
||||||
# take user manually
|
# take user manually
|
||||||
if instance.find_elements(css: '.content.active .newTicket .js-recipientDropdown.open')[0]
|
if instance.find_elements(css: '.content.active .newTicket .js-recipientDropdown.open')[0]
|
||||||
instance.find_elements(css: '.content.active .newTicket .recipientList-entry.js-user.is-active')[0].click
|
instance.find_elements(css: '.content.active .newTicket .recipientList-entry.js-object.is-active')[0].click
|
||||||
sleep 0.4
|
sleep 0.4
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -2092,7 +2092,7 @@ wait untill text in selector disabppears
|
||||||
sleep 2.5
|
sleep 2.5
|
||||||
|
|
||||||
element.send_keys(:enter)
|
element.send_keys(:enter)
|
||||||
#instance.find_elements(css: '.modal .user_autocompletion .recipientList-entry.js-user.is-active')[0].click
|
#instance.find_elements(css: '.modal .user_autocompletion .recipientList-entry.js-object.is-active')[0].click
|
||||||
sleep 0.2
|
sleep 0.2
|
||||||
|
|
||||||
click(browser: instance, css: '.modal .js-submit')
|
click(browser: instance, css: '.modal .js-submit')
|
||||||
|
|
Loading…
Reference in a new issue