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
|
||||
className: 'dropdown js-recipientDropdown'
|
||||
events:
|
||||
'hide.bs.dropdown .js-recipientDropdown': 'hideOrganizationMembers'
|
||||
'click .js-organization': 'showOrganizationMembers'
|
||||
'click .js-back': 'hideOrganizationMembers'
|
||||
'click .js-user': 'onUserClick'
|
||||
'click .js-userNew': 'newUser'
|
||||
'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) =>
|
||||
class App.UserOrganizationAutocompletion extends App.ObjectOrganizationAutocompletion
|
||||
objectSingle: 'User'
|
||||
objectIcon: 'user'
|
||||
objectSingels: 'People'
|
||||
objectCreate: 'Create new Customer'
|
||||
referenceAttribute: 'member_ids'
|
||||
|
||||
newObject: (e) =>
|
||||
if e
|
||||
e.preventDefault()
|
||||
new UserNew(
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
</div>
|
||||
<div class="recipientList-name">
|
||||
<%= @organization.displayName() %>
|
||||
<span class="recipientList-detail">- <%= @organization.member_ids.length %> <%- @T('People') %></span>
|
||||
<span class="recipientList-detail">- <%= @objectCount %> <%- @T(@objectSingels) %></span>
|
||||
</div>
|
||||
<%- @Icon('arrow-right', 'recipientList-arrow') %>
|
||||
</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">
|
||||
<%- @Icon('plus', 'recipientList-icon') %>
|
||||
</div>
|
||||
<div class="recipientList-name">
|
||||
<%- @T('Create new Customer') %>
|
||||
<%- @T(@objectCreate) %>
|
||||
</div>
|
||||
</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
|
||||
|
||||
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
|
||||
assert(true, 'ticket_customer_select')
|
||||
end
|
||||
|
@ -1928,7 +1928,7 @@ wait untill text in selector disabppears
|
|||
# ff issue, sometimes enter event gets dropped
|
||||
# take user manually
|
||||
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
|
||||
end
|
||||
end
|
||||
|
@ -2092,7 +2092,7 @@ wait untill text in selector disabppears
|
|||
sleep 2.5
|
||||
|
||||
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
|
||||
|
||||
click(browser: instance, css: '.modal .js-submit')
|
||||
|
|
Loading…
Reference in a new issue