Init version of extended search.

This commit is contained in:
Martin Edenhofer 2016-06-27 08:42:08 +02:00
parent 682e019880
commit e7f95a9e85
3 changed files with 265 additions and 2 deletions

View file

@ -0,0 +1,232 @@
class App.Search extends App.Controller
searchResultCache: {}
elements:
'.js-search': 'searchInput'
events:
'submit form.search-holder': 'preventDefault'
'keydown .js-search': 'listNavigate'
'click .js-tab': 'showTab'
constructor: ->
super
# check authentication
if !@authenticate(false)
App.TaskManager.remove(@task_key)
return
# update taskbar with new meta data
App.TaskManager.touch(@task_key)
@render()
meta: =>
title = App.i18n.translateInline('Extended Search')
if @query
title += ": #{App.Utils.htmlEscape(@query)}"
meta =
url: @url()
id: ''
head: title
title: title
iconClass: 'magnifier'
meta
url: ->
'#search'
show: (params) =>
@navupdate(url: '#search', type: 'menu')
console.log('par', params)
return if !params.query
@$('.js-search').val(decodeURIComponent(params.query)).trigger('change')
@searchFunction(200, true)
hide: ->
# nothing
changed: ->
# nothing
render: ->
currentState = App.TaskManager.get(@task_key).state
if !@query
if currentState && currentState.query
@query = currentState.query
if !@model
if currentState && currentState.model
@model = currentState.model
else
@model = 'Ticket'
@tabs = []
for model in App.Config.get('models_searchable')
tab =
name: model
model: model
count: 0
active: false
if @model == model
tab.active = true
@tabs.push tab
# build view
@html App.view('search/index')(
query: @query
tabs: @tabs
)
if @query
@searchFunction(200, true)
listNavigate: (e) =>
if e.keyCode is 27 # close on esc
@empty()
return
# on other keys, show result
@searchFunction(200)
empty: =>
@searchInput.val('')
# remove not needed popovers
@delay(@anyPopoversDestroy, 100, 'removePopovers')
searchFunction: (delay, force = false) =>
search = =>
query = @searchInput.val().trim()
if !force
return if !query
return if query is @query
@query = query
# use cache for search result
if @searchResultCache[@query]
@renderResult(@searchResultCache[@query].result)
currentTime = new Date
return if @searchResultCache[@query].time > currentTime.setSeconds(currentTime.getSeconds() - 20)
@updateTask()
App.Ajax.request(
id: 'search'
type: 'GET'
url: "#{@apiPath}/search"
data:
query: @query
limit: 200
processData: true,
success: (data, status, xhr) =>
App.Collection.loadAssets(data.assets)
result = {}
for item in data.result
if App[item.type] && App[item.type].find
if !result[item.type]
result[item.type] = []
item_object = App[item.type].find(item.id)
if item_object.searchResultAttributes
item_object_search_attributes = item_object.searchResultAttributes()
result[item.type].push item_object_search_attributes
else
@log 'error', "No such model #{item.type.toLocaleLowerCase()}.searchResultAttributes()"
else
@log 'error', "No such model App.#{item.type}"
diff = false
if @searchResultCache[@query]
diff = difference(@searchResultCache[@query].resultRaw, data.result)
# cache search result
@searchResultCache[@query] =
result: result
resultRaw: data.result
time: new Date
# if result hasn't changed, do not rerender
return if diff isnt false && _.isEmpty(diff)
@renderResult(result)
)
@delay(search, delay, 'search')
renderResult: (result = []) =>
@result = result
for tab in @tabs
count = 0
if result[tab.model]
count = result[tab.model].length
if @model is tab.model
@renderTab(tab.model, result[tab.model] || [])
@$(".js-tab#{tab.model} .js-counter").text("(#{count})")
showTab: (e) =>
tabs = $(e.currentTarget).closest('.tabs')
tabModel = $(e.currentTarget).data('tab-content')
tabs.find('.js-tab').removeClass('active')
$(e.currentTarget).addClass('active')
@renderTab(tabModel, @result[tabModel] || [])
renderTab: (model, localList) =>
# remember last shown model
if @model isnt model
@model = model
@updateTask()
list = []
for item in localList
object = App[model].fullLocal(item.id)
list.push object
if model is 'Ticket'
ticket_ids = []
for item in localList
ticket_ids.push item.id
new App.TicketList(
table_id: "find_#{model}"
el: @$('.js-content')
columns: [ 'number', 'title', 'customer', 'group', 'owner', 'created_at' ]
ticket_ids: ticket_ids
radio: false
)
else
openObject = (id,e) =>
object = App[@model].fullLocal(id)
@navigate object.uiUrl()
new App.ControllerTable(
table_id: "find_#{model}"
el: @$('.js-content')
model: App[model]
objects: list
bindRow:
events:
'click': openObject
)
updateTask: =>
current = App.TaskManager.get(@task_key).state
current.query = @query
current.model = @model
App.TaskManager.update(@task_key, { state: current })
App.TaskManager.touch(@task_key)
class Router extends App.ControllerPermanent
constructor: (params) ->
super
# cleanup params
clean_params =
query: params.query
App.TaskManager.execute(
key: 'Search'
controller: 'Search'
params: clean_params
show: true
)
App.Config.set('search', Router, 'Routes')
App.Config.set('search/:query', Router, 'Routes')

View file

@ -6,9 +6,15 @@ class App.TicketList extends App.Controller
render: => render: =>
openTicket = (id,e) =>
ticket = App.Ticket.fullLocal(id)
@navigate ticket.uiUrl()
callbackTicketTitleAdd = (value, object, attribute, attributes, refObject) -> callbackTicketTitleAdd = (value, object, attribute, attributes, refObject) ->
attribute.title = object.title attribute.title = object.title
value value
callbackLinkToTicket = (value, object, attribute, attributes, refObject) ->
attribute.link = object.uiUrl()
value
callbackUserPopover = (value, object, attribute, attributes, refObject) -> callbackUserPopover = (value, object, attribute, attributes, refObject) ->
attribute.class = 'user-popover' attribute.class = 'user-popover'
attribute.data = attribute.data =
@ -44,10 +50,14 @@ class App.TicketList extends App.Controller
list.push ticketItem list.push ticketItem
@el.html('') @el.html('')
new App.ControllerTable( new App.ControllerTable(
table_id: @table_id
el: @el el: @el
overview: [ 'number', 'title', 'customer', 'group', 'created_at' ] overview: @columns || [ 'number', 'title', 'customer', 'group', 'created_at' ]
model: App.Ticket model: App.Ticket
objects: list objects: list
#bindRow:
# events:
# 'click': openTicket
callbackHeader: [ callbackIconHeader ] callbackHeader: [ callbackIconHeader ]
callbackAttributes: callbackAttributes:
icon: icon:
@ -59,7 +69,9 @@ class App.TicketList extends App.Controller
owner_id: owner_id:
[ callbackUserPopover ] [ callbackUserPopover ]
title: title:
[ callbackTicketTitleAdd ] [ callbackLinkToTicket, callbackTicketTitleAdd ]
number:
[ callbackLinkToTicket, callbackTicketTitleAdd ]
radio: @radio radio: @radio
) )

View file

@ -0,0 +1,19 @@
<div class="flex vertical">
<div class="searchfield">
<%- @Icon('magnifier') %>
<input class="js-search form-control" name="query" placeholder="<%- @Ti('Find what you search. E. g. "search phrase"') %>" value="<%= @query %>" type="search" autocomplete="off">
<div class="empty-search js-emptySearch">
<%- @Icon('diagonal-cross') %>
</div>
</div>
<div class="tabs tabs-wide">
<% for tab in @tabs: %>
<div data-tab-content="<%- tab.model %>" class="tab js-tab js-tab<%- tab.model %><% if tab.active: %> active<% end %>"><%- @T(tab.name) %> <span class="js-counter"><%- tab.count %></span></div>
<% end %>
</div>
<div class="js-content"></div>
</div>