Added new user/org autocompletion.

This commit is contained in:
Martin Edenhofer 2014-09-19 23:35:40 +02:00
parent db4df87be1
commit e116941d1c
19 changed files with 718 additions and 343 deletions

View file

@ -753,6 +753,11 @@ class App.ControllerForm extends App.Controller
$('#' + attribute.id ).parent().css('height', 'auto') $('#' + attribute.id ).parent().css('height', 'auto')
App.Delay.set( a, 120, undefined, 'tags' ) App.Delay.set( a, 120, undefined, 'tags' )
# user
else if attribute.tag is 'user_autocompletion'
completion = new App.UserOrganizationAutocompletion( attribute: attribute )
item = completion.element()
# autocompletion # autocompletion
else if attribute.tag is 'autocompletion' else if attribute.tag is 'autocompletion'
item = $( App.view('generic/autocompletion')( attribute: attribute ) ) item = $( App.view('generic/autocompletion')( attribute: attribute ) )

View file

@ -4,13 +4,9 @@ class App.TicketCreate extends App.Controller
events: events:
'click .type-tabs .tab': 'changeFormType' 'click .type-tabs .tab': 'changeFormType'
'click .customer_new': 'userNew'
'submit form': 'submit' 'submit form': 'submit'
'click .submit': 'submit' 'click .submit': 'submit'
'click .cancel': 'cancel' 'click .cancel': 'cancel'
'hide.bs.dropdown .js-recipientDropdown': 'hideOrganisationMembers'
'click .js-organisation': 'showOrganisationMembers'
'click .js-back': 'hideOrganisationMembers'
constructor: (params) -> constructor: (params) ->
super super
@ -40,61 +36,6 @@ class App.TicketCreate extends App.Controller
@log 'notice', 'error', defaults @log 'notice', 'error', defaults
@render(defaults) @render(defaults)
showOrganisationMembers: (e) =>
e.stopPropagation()
listEntry = $(e.currentTarget)
organisationId = listEntry.data('organisation')
@recipientList = @$('.recipientList')
@organisationList = @$("##{ organisationId }")
# move organisation-list to the right and slide it in
$.Velocity.hook(@organisationList, 'translateX', '100%')
@organisationList.removeClass('hide')
@organisationList.velocity
properties:
translateX: 0
options:
speed: 300
# fade out list
@recipientList.velocity
properties:
translateX: '-100%'
options:
speed: 300
complete: => @recipientList.height(@organisationList.height())
hideOrganisationMembers: (e) =>
e && e.stopPropagation()
return if !@organisationList
# fade list back in
@recipientList.velocity
properties:
translateX: 0
options:
speed: 300
# reset list height
@recipientList.height('')
# slide out organisation-list and hide it
@organisationList.velocity
properties:
translateX: '100%'
options:
speed: 300
complete: => @organisationList.addClass('hide')
changeFormType: (e) => changeFormType: (e) =>
type = $(e.target).data('type') type = $(e.target).data('type')
if !type if !type
@ -353,12 +294,6 @@ class App.TicketCreate extends App.Controller
params: params params: params
) )
userNew: (e) =>
e.preventDefault()
new UserNew(
create_screen: @
)
cancel: (e) -> cancel: (e) ->
e.preventDefault() e.preventDefault()
@navigate '#' @navigate '#'
@ -545,68 +480,6 @@ class Sidebar extends App.Controller
items: items items: items
) )
class UserNew extends App.ControllerModal
constructor: ->
super
@head = 'New User'
@cancel = true
@button = true
controller = new App.ControllerForm(
el: @el.find('#form-user')
model: App.User
screen: 'edit'
autofocus: true
)
@show( controller.form )
onSubmit: (e) ->
e.preventDefault()
params = @formParam(e.target)
# if no login is given, use emails as fallback
if !params.login && params.email
params.login = params.email
# find role_id
if !params.role_ids || _.isEmpty( params.role_ids )
role = App.Role.findByAttribute( 'name', 'Customer' )
params.role_ids = role.id
@log 'notice', 'updateAttributes', params
user = new App.User
user.load(params)
errors = user.validate()
if errors
@log 'error', errors
@formValidate( form: e.target, errors: errors )
return
# save user
ui = @
user.save(
done: ->
# force to reload object
callbackReload = (user) ->
realname = user.displayName()
if user.email
realname = "#{ realname } <#{ user.email }>"
ui.create_screen.el.find('[name=customer_id]').val( user.id )
ui.create_screen.el.find('[name=customer_id_autocompletion]').val( realname )
# start customer info controller
ui.userInfo( user_id: user.id )
ui.hide()
App.User.full( @id, callbackReload , true )
fail: ->
ui.hide()
)
class Router extends App.ControllerPermanent class Router extends App.ControllerPermanent
constructor: (params) -> constructor: (params) ->
super super

View file

@ -10,6 +10,11 @@ App.Config.set( 'layout_ref', Index, 'Routes' )
class Content extends App.ControllerContent class Content extends App.ControllerContent
events:
'hide.bs.dropdown .js-recipientDropdown': 'hideOrganisationMembers'
'click .js-organisation': 'showOrganisationMembers'
'click .js-back': 'hideOrganisationMembers'
constructor: -> constructor: ->
super super
@render() @render()
@ -35,6 +40,60 @@ class Content extends App.ControllerContent
render: -> render: ->
@html App.view('layout_ref/content')() @html App.view('layout_ref/content')()
showOrganisationMembers: (e) =>
e.stopPropagation()
listEntry = $(e.currentTarget)
organisationId = listEntry.data('organisation-id')
@recipientList = @$('.recipientList')
@organisationList = @$("##{ organisationId }")
# move organisation-list to the right and slide it in
$.Velocity.hook(@organisationList, 'translateX', '100%')
@organisationList.removeClass('hide')
@organisationList.velocity
properties:
translateX: 0
options:
speed: 300
# fade out list
@recipientList.velocity
properties:
translateX: '-100%'
options:
speed: 300
complete: => @recipientList.height(@organisationList.height())
hideOrganisationMembers: (e) =>
e && e.stopPropagation()
return if !@organisationList
# fade list back in
@recipientList.velocity
properties:
translateX: 0
options:
speed: 300
# reset list height
@recipientList.height('')
# slide out organisation-list and hide it
@organisationList.velocity
properties:
translateX: '100%'
options:
speed: 300
complete: => @organisationList.addClass('hide')
App.Config.set( 'layout_ref/content', Content, 'Routes' ) App.Config.set( 'layout_ref/content', Content, 'Routes' )

View file

@ -2,15 +2,13 @@ class App.TicketCustomer extends App.ControllerModal
constructor: -> constructor: ->
super super
configure_attributes = [ configure_attributes = [
{ name: 'customer_id', display: 'Customer', tag: 'autocompletion', type: 'text', limit: 100, null: false, relation: 'User', class: 'span5', autocapitalize: false, help: 'Select the new customer of the Ticket.', source: @apiPath + '/users/search', minLengt: 2 }, { name: 'customer_id', display: 'Customer', tag: 'user_autocompletion', null: false, placeholder: 'Enter Person or Organisation/Company', minLengt: 2, disableCreateUser: true },
] ]
controller = new App.ControllerForm( controller = new App.ControllerForm(
model: { model:
configure_attributes: configure_attributes, configure_attributes: configure_attributes,
className: 'update', autofocus: true
},
autofocus: true,
) )
@head = 'Change Customer' @head = 'Change Customer'
@close = true @close = true

View file

@ -0,0 +1,257 @@
class App.UserOrganizationAutocompletion extends App.Controller
events:
'hide.bs.dropdown .js-recipientDropdown': 'hideOrganisationMembers'
'click .js-organisation': 'showOrganisationMembers'
'click .js-back': 'hideOrganisationMembers'
'click .js-user': 'selectUser'
'click .js-user-new': 'newUser'
constructor: (params) ->
super
@key = Math.floor( Math.random() * 999999 ).toString()
if !@attribute.source
@attribute.source = @apiPath + '/search_user_org'
@build()
element: =>
@el
selectUser: (e) ->
userId = $(e.target).parents('.recipientList-entry').data('user-id')
if !userId
userId = $(e.target).data('user-id')
@el.find('[name="' + @attribute.name + '"]').val( userId ).trigger('change')
setUser: ->
userId = @el.find('[name="' + @attribute.name + '"]').val()
return if !userId
user = App.User.find(userId)
name = user.displayName()
if user.email
name += " <#{user.email}>"
@el.find('[name="' + @attribute.name + '_completion"]').val( name ).trigger('change')
if @callback
@callback(userId)
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: =>
@el.html App.view('generic/user_search/input')(
attribute: @attribute
)
@el.find('[name="' + @attribute.name + '"]').on(
'change',
(e) =>
@setUser()
)
@el.find('[name="' + @attribute.name + '_completion"]').on(
'keyup',
(e) =>
item = $(e.target).val()
#@log('CC', e.keyCode, item)
# clean input field on ESC
if e.keyCode is 27
$(e.target).val('')
item = ''
# ignore arrow keys
return if e.keyCode is 37
return if e.keyCode is 38
return if e.keyCode is 39
return if e.keyCode is 40
# ignore shift
return if e.keyCode is 16
# ignore ctrl
return if e.keyCode is 17
# ignore alt
return if e.keyCode is 18
# hide dropdown
@el.find('.recipientList').html('')
@el.find('.recipientList-organisationMembers').remove()
if !item && !@attribute.disableCreateUser
@el.find('.recipientList').append( @buildUserNew() )
# show dropdown
if item && ( !@attribute.minLengt || @attribute.minLengt <= item.length )
execute = => @searchUser(item)
@delay( execute, 400, 'userSearch' )
)
searchUser: (term) =>
@ajax(
id: 'searchUser' + @key
type: 'GET'
url: @attribute.source
data:
query: term
processData: true
success: (data, status, xhr) =>
# 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 )
@el.find('.recipientList').append( @buildOrganizationItem(organization) )
# users of organization
if organization.member_ids
@el.find('.dropdown-menu').append( @buildOrganizationMembers(organization) )
# users
if item.type is 'User'
user = App.User.fullLocal( item.id )
@el.find('.recipientList').append( @buildUserItem(user) )
if !@attribute.disableCreateUser
@el.find('.recipientList').append( @buildUserNew() )
)
showOrganisationMembers: (e) =>
e.stopPropagation()
listEntry = $(e.currentTarget)
organisationId = listEntry.data('organisation-id')
@recipientList = @$('.recipientList')
@organisationList = @$("##{ organisationId }")
# move organisation-list to the right and slide it in
$.Velocity.hook(@organisationList, 'translateX', '100%')
@organisationList.removeClass('hide')
@organisationList.velocity
properties:
translateX: 0
options:
speed: 300
# fade out list
@recipientList.velocity
properties:
translateX: '-100%'
options:
speed: 300
complete: => @recipientList.height(@organisationList.height())
hideOrganisationMembers: (e) =>
e && e.stopPropagation()
return if !@organisationList
# fade list back in
@recipientList.velocity
properties:
translateX: 0
options:
speed: 300
# reset list height
@recipientList.height('')
# slide out organisation-list and hide it
@organisationList.velocity
properties:
translateX: '100%'
options:
speed: 300
complete: => @organisationList.addClass('hide')
newUser: (e) =>
e.preventDefault()
new UserNew(
parent: @
)
class UserNew extends App.ControllerModal
constructor: ->
super
@head = 'New User'
@cancel = true
@button = true
controller = new App.ControllerForm(
el: @el.find('#form-user')
model: App.User
screen: 'edit'
autofocus: true
)
@show( controller.form )
onSubmit: (e) ->
e.preventDefault()
params = @formParam(e.target)
# if no login is given, use emails as fallback
if !params.login && params.email
params.login = params.email
# find role_id
if !params.role_ids || _.isEmpty( params.role_ids )
role = App.Role.findByAttribute( 'name', 'Customer' )
params.role_ids = role.id
@log 'notice', 'updateAttributes', params
user = new App.User
user.load(params)
errors = user.validate()
if errors
@log 'error', errors
@formValidate( form: e.target, errors: errors )
return
# save user
ui = @
user.save(
done: ->
# force to reload object
callbackReload = (user) ->
ui.parent.el.find('[name=customer_id]').val( user.id ).trigger('change')
# start customer info controller
ui.hide()
App.User.full( @id, callbackReload , true )
fail: ->
ui.hide()
)

View file

@ -25,189 +25,7 @@
<form role="form" class="ticket-create"> <form role="form" class="ticket-create">
<input type="hidden" name="formSenderType"/> <input type="hidden" name="formSenderType"/>
<div class="form-group">
<label for="customer_id">Customer</label>
<div class="dropdown js-recipientDropdown">
<div class="dropdown-toggle u-positionOrigin" data-toggle="dropdown">
<input id="customer_id" name="customer_id_autocompletion" class="ui-autocomplete-input form-control" autocapitalize="off" placeholder="Enter Person or Organisation/Company" autocomplete="off" role="textbox" aria-autocomplete="list" aria-haspopup="true">
<span class="caret"></span>
</div>
<div class="dropdown-menu" aria-labelledby="customer_id">
<ul class="recipientList" role="menu">
<li class="recipientList-entry u-clickable horizontal center js-organisation" data-organisation="AlbrechtBertschlerGmbG">
<div class="recipientList-iconSpacer centered">
<div class="white organisation icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat">
Albrecht &amp; Bertschler GmbH
<span class="recipientList-detail">- 4 Personen</span>
</div>
<div class="white right arrow icon"></div>
<li class="recipientList-entry u-clickable horizontal center js-organisation" data-organisation="BENCHMARKhumanresources">
<div class="recipientList-iconSpacer centered">
<div class="white organisation icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat">
BENCHMARK human resources
<span class="recipientList-detail">- 2 Personen</span>
</div>
<div class="white right arrow icon"></div>
<li class="recipientList-entry u-clickable horizontal center">
<div class="recipientList-iconSpacer centered">
<div class="white user icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat">
Belinda Matt
<span class="recipientList-detail">- Albrecht &amp; Bertschler GmbG</span>
</div>
<li class="recipientList-entry u-clickable horizontal center">
<div class="recipientList-iconSpacer centered">
<div class="white user icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat">
Benjamin Wahlers
<span class="recipientList-detail">- Wahlers Würste GmbH</span>
</div>
<li class="recipientList-entry u-clickable horizontal center">
<div class="recipientList-iconSpacer centered">
<div class="white user icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat ">
Benjamin Weiß
<span class="recipientList-detail">- Zeughaus Werbeagentur GmbH</span>
</div>
<li class="recipientList-entry u-clickable horizontal center">
<div class="recipientList-iconSpacer centered">
<div class="white organisation icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat">
Benteler SGL Composite Technology GmbH
<span class="recipientList-detail"></span>
</div>
<li class="recipientList-entry u-clickable horizontal center js-organisation">
<div class="recipientList-iconSpacer centered">
<div class="white team icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat">
Support Team Berlin
<span class="recipientList-detail">- 5 Personen</span>
</div>
<div class="white right arrow icon"></div>
<li class="recipientList-entry u-clickable horizontal center js-organisation">
<div class="recipientList-iconSpacer centered">
<div class="white organisation icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat">
Bernecker + Rainer Industrie-Elektronik Ges.m.b.H.
<span class="recipientList-detail">- 3 Personen</span>
</div>
<div class="white right arrow icon"></div>
<li class="recipientList-entry u-clickable horizontal center js-organisation">
<div class="recipientList-iconSpacer centered">
<div class="white organisation icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat">
Bertsch Ecopower GmbH
<span class="recipientList-detail">- 1 Person</span>
</div>
<div class="white right arrow icon"></div>
<li class="recipientList-entry recipientList-new u-clickable horizontal center">
<div class="recipientList-iconSpacer centered">
<div class="white plus icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat">
<%- @T('Create new Customer') %>
</div>
</ul>
<ul class="recipientList-organisationMembers hide" id="AlbrechtBertschlerGmbG">
<li class="recipientList-controls u-clickable js-back">
<div class="recipientList-backClickArea centered">
<div class="recipientList-backButton">
<div class="white arrow left icon"></div>
<%- @T('Back') %>
</div>
</div>
<li class="recipientList-entry u-clickable horizontal center">
<div class="recipientList-iconSpacer centered">
<div class="white user icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat ">
Andreas Kramer
<span class="recipientList-detail">- Albrecht &amp; Bertschler GmbG</span>
</div>
<li class="recipientList-entry u-clickable horizontal center">
<div class="recipientList-iconSpacer centered">
<div class="white user icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat ">
Belinda Matt
<span class="recipientList-detail">- Albrecht &amp; Bertschler GmbG</span>
</div>
<li class="recipientList-entry u-clickable horizontal center">
<div class="recipientList-iconSpacer centered">
<div class="white user icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat ">
Damian Sprengler
<span class="recipientList-detail">- Albrecht &amp; Bertschler GmbG</span>
</div>
<li class="recipientList-entry u-clickable horizontal center">
<div class="recipientList-iconSpacer centered">
<div class="white user icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat ">
Katharina Nussman
<span class="recipientList-detail">- Albrecht &amp; Bertschler GmbG</span>
</div>
</ul>
<ul class="recipientList-organisationMembers hide" id="BENCHMARKhumanresources">
<li class="recipientList-controls u-clickable js-back">
<div class="recipientList-backClickArea centered">
<div class="recipientList-backButton">
<div class="white arrow left icon"></div>
<%- @T('Back') %>
</div>
</div>
<li class="recipientList-entry u-clickable horizontal center">
<div class="recipientList-iconSpacer centered">
<div class="white user icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat ">
Hubert Lang
<span class="recipientList-detail">- BENCHMARK human resources</span>
</div>
<li class="recipientList-entry u-clickable horizontal center">
<div class="recipientList-iconSpacer centered">
<div class="white user icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat ">
Mario Steibel
<span class="recipientList-detail">- BENCHMARK human resources</span>
</div>
</ul>
</div>
</div>
</div>
<div class="ticket-form-top"></div> <div class="ticket-form-top"></div>
<div class="article-form-top"></div> <div class="article-form-top"></div>
@ -216,7 +34,6 @@
<div class="ticket-form-bottom"></div> <div class="ticket-form-bottom"></div>
</div> </div>
<div class="form-actions horizontal"> <div class="form-actions horizontal">
<a class="subtle-link standalone cancel" href="#/"><%- @T( 'Cancel & Go Back' ) %></a> <a class="subtle-link standalone cancel" href="#/"><%- @T( 'Cancel & Go Back' ) %></a>
<button type="submit" class="btn btn-create submit align-right"><%- @T( 'Create' ) %></button> <button type="submit" class="btn btn-create submit align-right"><%- @T( 'Create' ) %></button>

View file

@ -0,0 +1,12 @@
<div class="dropdown js-recipientDropdown">
<div class="dropdown-toggle u-positionOrigin" data-toggle="dropdown">
<input type="hidden" name="<%- @attribute.name %>">
<input name="<%- @attribute.name %>_completion" class="ui-autocomplete-input form-control" autocapitalize="off" placeholder="<%- @attribute.placeholder %>" autocomplete="off" role="textbox" aria-autocomplete="list" aria-haspopup="true">
</div>
<div class="dropdown-menu" aria-labelledby="customer_id">
<ul class="recipientList" role="menu"></ul>
</div>
</div>

View file

@ -0,0 +1,10 @@
<li class="recipientList-entry u-clickable horizontal center js-organisation" data-organisation-id="<%- @organization.id %>">
<div class="recipientList-iconSpacer centered">
<div class="white organisation icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat">
<%= @organization.displayName() %>
<span class="recipientList-detail">- <%= @organization.member_ids.length %> <%- @T('People') %></span>
</div>
<div class="white right arrow icon"></div>
</li>

View file

@ -0,0 +1,10 @@
<ul class="recipientList-organisationMembers hide" id="<%- @organization.id %>">
<li class="recipientList-controls u-clickable js-back">
<div class="recipientList-backClickArea centered">
<div class="recipientList-backButton">
<div class="white arrow left icon"></div>
<%- @T('Back') %>
</div>
</div>
</li>
</ul>

View file

@ -0,0 +1,11 @@
<li class="recipientList-entry u-clickable horizontal center js-user" data-user-id="<%= @user.id %>"">
<div class="recipientList-iconSpacer centered">
<div class="white user icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat">
<%= @user.displayName() %>
<% if @user.organization: %>
<span class="recipientList-detail">- <%= @user.organization.displayName() %></span>
<% end %>
</div>
</li>

View file

@ -0,0 +1,8 @@
<li class="recipientList-entry recipientList-new u-clickable horizontal center js-user-new">
<div class="recipientList-iconSpacer centered">
<div class="white plus icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat">
<%- @T('Create new Customer') %>
</div>
</li>

View file

@ -40,6 +40,203 @@
<span class="big user avatar" data-firstname="Luisa" data-lastname="Hofner" data-userid="10"></span> <span class="big user avatar" data-firstname="Luisa" data-lastname="Hofner" data-userid="10"></span>
<span class="big user avatar" data-firstname="Clara" data-lastname="Altman" data-userid="11"></span> <span class="big user avatar" data-firstname="Clara" data-lastname="Altman" data-userid="11"></span>
<hr>
<h2>User Selection</h2>
<form>
<div class="form-group">
<label for="customer_id">Customer</label>
<div class="dropdown js-recipientDropdown">
<div class="dropdown-toggle u-positionOrigin" data-toggle="dropdown">
<input id="customer_id_autocompletion2" name="customer_id_autocompletion" class="ui-autocomplete-input form-control" autocapitalize="off" placeholder="Enter Person or Organisation/Company" autocomplete="off" role="textbox" aria-autocomplete="list" aria-haspopup="true">
<span class="caret"></span>
</div>
<div class="dropdown-menu" aria-labelledby="customer_id">
<ul class="recipientList" role="menu">
<li class="recipientList-entry u-clickable horizontal center js-organisation" data-organisation-id="AlbrechtBertschlerGmbG">
<div class="recipientList-iconSpacer centered">
<div class="white organisation icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat">
Albrecht &amp; Bertschler GmbH
<span class="recipientList-detail">- 4 Personen</span>
</div>
<div class="white right arrow icon"></div>
<li class="recipientList-entry u-clickable horizontal center js-organisation" data-organisation-id="BENCHMARKhumanresources">
<div class="recipientList-iconSpacer centered">
<div class="white organisation icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat">
BENCHMARK human resources
<span class="recipientList-detail">- 2 Personen</span>
</div>
<div class="white right arrow icon"></div>
<li class="recipientList-entry u-clickable horizontal center">
<div class="recipientList-iconSpacer centered">
<div class="white user icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat">
Belinda Matt
<span class="recipientList-detail">- Albrecht &amp; Bertschler GmbG</span>
</div>
<li class="recipientList-entry u-clickable horizontal center">
<div class="recipientList-iconSpacer centered">
<div class="white user icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat">
Benjamin Wahlers
<span class="recipientList-detail">- Wahlers Würste GmbH</span>
</div>
<li class="recipientList-entry u-clickable horizontal center">
<div class="recipientList-iconSpacer centered">
<div class="white user icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat ">
Benjamin Weiß
<span class="recipientList-detail">- Zeughaus Werbeagentur GmbH</span>
</div>
<li class="recipientList-entry u-clickable horizontal center">
<div class="recipientList-iconSpacer centered">
<div class="white organisation icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat">
Benteler SGL Composite Technology GmbH
<span class="recipientList-detail"></span>
</div>
<li class="recipientList-entry u-clickable horizontal center js-organisation">
<div class="recipientList-iconSpacer centered">
<div class="white team icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat">
Support Team Berlin
<span class="recipientList-detail">- 5 Personen</span>
</div>
<div class="white right arrow icon"></div>
<li class="recipientList-entry u-clickable horizontal center js-organisation">
<div class="recipientList-iconSpacer centered">
<div class="white organisation icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat">
Bernecker + Rainer Industrie-Elektronik Ges.m.b.H.
<span class="recipientList-detail">- 3 Personen</span>
</div>
<div class="white right arrow icon"></div>
<li class="recipientList-entry u-clickable horizontal center js-organisation">
<div class="recipientList-iconSpacer centered">
<div class="white organisation icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat">
Bertsch Ecopower GmbH
<span class="recipientList-detail">- 1 Person</span>
</div>
<div class="white right arrow icon"></div>
<li class="recipientList-entry recipientList-new u-clickable horizontal center">
<div class="recipientList-iconSpacer centered">
<div class="white plus icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat">
<%- @T('Create new Customer') %>
</div>
</ul>
<ul class="recipientList-organisationMembers hide" id="AlbrechtBertschlerGmbG">
<li class="recipientList-controls u-clickable js-back">
<div class="recipientList-backClickArea centered">
<div class="recipientList-backButton">
<div class="white arrow left icon"></div>
<%- @T('Back') %>
</div>
</div>
<li class="recipientList-entry u-clickable horizontal center">
<div class="recipientList-iconSpacer centered">
<div class="white user icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat ">
Andreas Kramer
<span class="recipientList-detail">- Albrecht &amp; Bertschler GmbG</span>
</div>
<li class="recipientList-entry u-clickable horizontal center">
<div class="recipientList-iconSpacer centered">
<div class="white user icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat ">
Belinda Matt
<span class="recipientList-detail">- Albrecht &amp; Bertschler GmbG</span>
</div>
<li class="recipientList-entry u-clickable horizontal center">
<div class="recipientList-iconSpacer centered">
<div class="white user icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat ">
Damian Sprengler
<span class="recipientList-detail">- Albrecht &amp; Bertschler GmbG</span>
</div>
<li class="recipientList-entry u-clickable horizontal center">
<div class="recipientList-iconSpacer centered">
<div class="white user icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat ">
Katharina Nussman
<span class="recipientList-detail">- Albrecht &amp; Bertschler GmbG</span>
</div>
</ul>
<ul class="recipientList-organisationMembers hide" id="BENCHMARKhumanresources">
<li class="recipientList-controls u-clickable js-back">
<div class="recipientList-backClickArea centered">
<div class="recipientList-backButton">
<div class="white arrow left icon"></div>
<%- @T('Back') %>
</div>
</div>
<li class="recipientList-entry u-clickable horizontal center">
<div class="recipientList-iconSpacer centered">
<div class="white user icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat ">
Hubert Lang
<span class="recipientList-detail">- BENCHMARK human resources</span>
</div>
<li class="recipientList-entry u-clickable horizontal center">
<div class="recipientList-iconSpacer centered">
<div class="white user icon"></div>
</div>
<div class="recipientList-name flex u-textTruncat ">
Mario Steibel
<span class="recipientList-detail">- BENCHMARK human resources</span>
</div>
</ul>
</div>
</div>
</div>
<form>
<hr> <hr>
<h2>Headlines</h2> <h2>Headlines</h2>

View file

@ -3,6 +3,70 @@
class SearchController < ApplicationController class SearchController < ApplicationController
before_filter :authentication_check before_filter :authentication_check
# GET /api/v1/search_user_org
def search_user_org
# enable search only for agents and admins
if !current_user.is_role('Agent') && !current_user.is_role('Admin')
response_access_deny
return true
end
# get params
query = params[:query]
limit = params[:limit] || 10
# try search index backend
assets = {}
result = []
if SearchIndexBackend.enabled?
items = SearchIndexBackend.search( query, limit, ['User', 'Organization'] )
items.each { |item|
require item[:type].to_filename
record = Kernel.const_get( item[:type] ).find( item[:id] )
assets = record.assets(assets)
result.push item
}
else
# do query
users = User.search(
:query => query,
:limit => limit,
:current_user => current_user,
)
user_result = []
users.each do |user|
item = {
:id => user.id,
:type => user.class.to_s
}
result.push item
assets = user.assets(assets)
end
organizations = Organization.search(
:query => query,
:limit => limit,
:current_user => current_user,
)
organization_result = []
organizations.each do |organization|
item = {
:id => organization.id,
:type => organization.class.to_s
}
result.push item
assets = organization.assets(assets)
end
end
render :json => {
:assets => assets,
:result => result,
}
end
# GET /api/v1/search # GET /api/v1/search
def search def search

View file

@ -30,10 +30,10 @@ returns
# try search index backend # try search index backend
if SearchIndexBackend.enabled? if SearchIndexBackend.enabled?
ids = SearchIndexBackend.search( query, limit, 'Organization' ) items = SearchIndexBackend.search( query, limit, 'Organization' )
organizations = [] organizations = []
ids.each { |id| items.each { |item|
organizations.push Organization.lookup( :id => id ) organizations.push Organization.lookup( :id => item[:id] )
} }
return organizations return organizations
end end

View file

@ -78,13 +78,17 @@ returns
query_extention['bool']['must'].push access_condition query_extention['bool']['must'].push access_condition
end end
ids = SearchIndexBackend.search( query, limit, 'Ticket', query_extention ) items = SearchIndexBackend.search( query, limit, 'Ticket', query_extention )
if !full if !full
ids = []
items.each {|item|
ids.push item[:id]
}
return ids return ids
end end
tickets = [] tickets = []
ids.each { |id| items.each { |item|
tickets.push Ticket.lookup( :id => id ) tickets.push Ticket.lookup( :id => item[:id] )
} }
return tickets return tickets
end end

View file

@ -4,22 +4,6 @@ module User::Search
=begin =begin
search tickets
result = Ticket.search(
:current_user => User.find(123),
:query => 'search something',
:limit => 15,
)
returns
result = [ticket_model1, ticket_model2]
=end
=begin
search user search user
result = User.search( result = User.search(
@ -46,10 +30,10 @@ returns
# try search index backend # try search index backend
if SearchIndexBackend.enabled? if SearchIndexBackend.enabled?
ids = SearchIndexBackend.search( query, limit, 'User' ) items = SearchIndexBackend.search( query, limit, 'User' )
users = [] users = []
ids.each { |id| items.each { |item|
users.push User.lookup( :id => id ) users.push User.lookup( :id => item[:id] )
} }
return users return users
end end

View file

@ -2,6 +2,9 @@ Zammad::Application.routes.draw do
api_path = Rails.configuration.api_path api_path = Rails.configuration.api_path
# search # search
match api_path + '/search', :to => 'search#search', :via => [:get, :post] match api_path + '/search', :to => 'search#search', :via => [:get, :post]
# search_user_org
match api_path + '/search_user_org', :to => 'search#search_user_org', :via => [:get, :post]
end end

View file

@ -0,0 +1,38 @@
class UpdateObjectManager2 < ActiveRecord::Migration
def up
ObjectManager::Attribute.add(
:object => 'Ticket',
:name => 'customer_id',
:display => 'Customer',
:data_type => 'user_autocompletion',
:data_option => {
:autocapitalize => false,
:multiple => false,
:null => false,
:limit => 200,
:placeholder => 'Enter Person or Organisation/Company',
:minLengt => 2,
:translate => false,
},
:editable => false,
:active => true,
:screens => {
:create_top => {
:Agent => {
:null => false,
},
},
:edit => {},
},
:pending_migration => false,
:position => 10,
:created_by_id => 1,
:updated_by_id => 1,
)
end
def down
end
end

View file

@ -113,8 +113,25 @@ remove whole data from index
return search result return search result
result = SearchIndexBackend.search( 'search query', limit, ['User', 'Organization'] )
result = SearchIndexBackend.search( 'search query', limit, 'User' ) result = SearchIndexBackend.search( 'search query', limit, 'User' )
result = [
{
:id => 123,
:type => 'User',
},
{
:id => 125,
:type => 'User',
},
{
:id => 15,
:type => 'Organization',
}
]
=end =end
def self.search( query, limit = 10, index = nil, query_extention = {} ) def self.search( query, limit = 10, index = nil, query_extention = {} )
@ -123,7 +140,11 @@ return search result
url = build_url() url = build_url()
return if !url return if !url
if index if index
url += "/#{index}/_search" if index.class == Array
url += "/#{index.join(',')}/_search"
else
url += "/#{index}/_search"
end
else else
url += '/_search' url += '/_search'
end end
@ -176,7 +197,11 @@ return search result
return ids if !data['hits']['hits'] return ids if !data['hits']['hits']
data['hits']['hits'].each { |item| data['hits']['hits'].each { |item|
puts "... #{item['_type'].to_s} #{item['_id'].to_s}" puts "... #{item['_type'].to_s} #{item['_id'].to_s}"
ids.push item['_id'] data = {
:id => item['_id'],
:type => item['_type'],
}
ids.push data
} }
ids ids
end end