Fixes #445 - Add bulk option to extended search

This commit is contained in:
Bola Ahmed Buari 2021-08-18 10:47:40 +02:00 committed by Thorsten Eckel
parent 3486390843
commit db0229e629
8 changed files with 558 additions and 332 deletions

View File

@ -167,15 +167,110 @@ class App.Search extends App.Controller
object = App[model].fullLocal(item.id)
list.push object
if model is 'Ticket'
openTicket = (id,e) =>
# open ticket via task manager to provide task with overview info
ticket = App.Ticket.findNative(id)
App.TaskManager.execute(
key: "Ticket-#{ticket.id}"
controller: 'TicketZoom'
params:
ticket_id: ticket.id
overview_id: @overview.id
show: true
)
@navigate ticket.uiUrl()
checkbox = @permissionCheck('ticket.agent') ? true : false
callbackCheckbox = (id, checked, e) =>
if @shouldShowBulkForm()
@bulkForm.render()
@bulkForm.show()
else
@bulkForm.hide()
if @lastChecked && e.shiftKey
# check items in a row
currentItem = $(e.currentTarget).parents('.item')
lastCheckedItem = $(@lastChecked).parents('.item')
items = currentItem.parent().children()
if currentItem.index() > lastCheckedItem.index()
# current item is below last checked item
startId = lastCheckedItem.index()
endId = currentItem.index()
else
# current item is above last checked item
startId = currentItem.index()
endId = lastCheckedItem.index()
items.slice(startId+1, endId).find('[name="bulk"]').prop('checked', (-> !@checked))
@lastChecked = e.currentTarget
ticket_ids = []
for item in localList
ticket_ids.push item.id
localeEl = @$('.js-content')
@table = new App.TicketList(
tableId: "find_#{model}"
el: @$('.js-content')
tableId: "find_#{model}"
el: localeEl
columns: [ 'number', 'title', 'customer', 'group', 'owner', 'created_at' ]
ticket_ids: ticket_ids
radio: false
checkbox: checkbox
bindRow:
events:
'click': openTicket
bindCheckbox:
events:
'click': callbackCheckbox
select_all: callbackCheckbox
)
updateSearch = =>
callback = =>
@search(true)
@delay(callback, 100)
@bulkForm = new App.TicketBulkForm(
holder: localeEl
view: @view
callback: updateSearch
noSidebar: true
)
# start bulk action observ
@el.append(@bulkForm.el)
localElement = @$('.js-content')
if localElement.find('input[name="bulk"]:checked').length isnt 0
@bulkForm.show()
# show/hide bulk action
localElement.delegate('input[name="bulk"], input[name="bulk_all"]', 'change', (e) =>
if @shouldShowBulkForm()
@bulkForm.show()
else
@bulkForm.hide()
@bulkForm.reset()
)
# deselect bulk_all if one item is uncheck observ
localElement.delegate('[name="bulk"]', 'change', (e) ->
bulkAll = localElement.find('[name="bulk_all"]')
checkedCount = localElement.find('input[name="bulk"]:checked').length
checkboxCount = localElement.find('input[name="bulk"]').length
if checkedCount is 0
bulkAll.prop('indeterminate', false)
bulkAll.prop('checked', false)
else
if checkedCount is checkboxCount
bulkAll.prop('indeterminate', false)
bulkAll.prop('checked', true)
else
bulkAll.prop('checked', false)
bulkAll.prop('indeterminate', true)
)
else
openObject = (id,e) =>
@ -202,6 +297,18 @@ class App.Search extends App.Controller
updateFilledClass: ->
@searchInput.toggleClass 'is-empty', !@searchInput.val()
shouldShowBulkForm: =>
items = @$('table').find('input[name="bulk"]:checked')
return false if items.length == 0
ticket_ids = _.map(items, (el) -> $(el).val() )
ticket_group_ids = _.map(App.Ticket.findAll(ticket_ids), (ticket) -> ticket.group_id)
ticket_group_ids = _.uniq(ticket_group_ids)
allowed_group_ids = App.User.find(@Session.get('id')).allGroupIds('change')
allowed_group_ids = _.map(allowed_group_ids, (id_string) -> parseInt(id_string, 10) )
_.every(ticket_group_ids, (id) -> id in allowed_group_ids)
class Router extends App.ControllerPermanent
constructor: (params) ->
super

View File

@ -1,47 +1,3 @@
ValidUsersForTicketSelectionMethods =
validUsersForTicketSelection: ->
items = $('.content.active .table-overview .table').find('[name="bulk"]:checked')
# we want to display all users for which we can assign the tickets directly
# for this we need to get the groups of all selected tickets
# after we got those we need to check which users are available in all groups
# users that are not in all groups can't get the tickets assigned
ticket_ids = _.map(items, (el) -> $(el).val() )
ticket_group_ids = _.map(App.Ticket.findAll(ticket_ids), (ticket) -> ticket.group_id)
users = @usersInGroups(ticket_group_ids)
# get the list of possible groups for the current user
# from the TicketCreateCollection
# (filled for e.g. the TicketCreation or TicketZoom assignment)
# and order them by name
group_ids = _.keys(@formMeta?.dependencies?.group_id)
groups = App.Group.findAll(group_ids)
groups_sorted = _.sortBy(groups, (group) -> group.name)
# get the number of visible users per group
# from the TicketCreateCollection
# (filled for e.g. the TicketCreation or TicketZoom assignment)
for group in groups
group.valid_users_count = @formMeta?.dependencies?.group_id?[group.id]?.owner_id.length || 0
{
users: users
groups: groups_sorted
}
usersInGroups: (group_ids) ->
ids_by_group = _.chain(@formMeta?.dependencies?.group_id)
.pick(group_ids)
.values()
.map( (e) -> e.owner_id)
.value()
# Underscore's intersection doesn't work when chained
ids_in_all_groups = _.intersection(ids_by_group...)
users = App.User.findAll(ids_in_all_groups)
_.sortBy(users, (user) -> user.firstname)
class App.TicketOverview extends App.Controller
className: 'overviews'
activeFocus: 'nav'
@ -69,7 +25,7 @@ class App.TicketOverview extends App.Controller
'mouseenter .js-batch-hover-target': 'highlightBatchEntry'
'mouseleave .js-batch-hover-target': 'unhighlightBatchEntry'
@include ValidUsersForTicketSelectionMethods
@include App.ValidUsersForTicketSelectionMethods
constructor: ->
super
@ -1280,18 +1236,19 @@ class Table extends App.Controller
@renderPopovers()
@bulkForm = new BulkForm(
@bulkForm = new App.TicketBulkForm(
holder: @el
view: @view
)
# start bulk action observ
@el.append(@bulkForm.el)
if @$('.table-overview').find('input[name="bulk"]:checked').length isnt 0
localElement = @$('.table-overview')
if localElement.find('input[name="bulk"]:checked').length isnt 0
@bulkForm.show()
# show/hide bulk action
@$('.table-overview').delegate('input[name="bulk"], input[name="bulk_all"]', 'change', (e) =>
localElement.delegate('input[name="bulk"], input[name="bulk_all"]', 'change', (e) =>
if @shouldShowBulkForm()
@bulkForm.show()
else
@ -1300,10 +1257,10 @@ class Table extends App.Controller
)
# deselect bulk_all if one item is uncheck observ
@$('.table-overview').delegate('[name="bulk"]', 'change', (e) =>
bulkAll = @$('.table-overview').find('[name="bulk_all"]')
checkedCount = @$('.table-overview').find('input[name="bulk"]:checked').length
checkboxCount = @$('.table-overview').find('input[name="bulk"]').length
localElement.delegate('[name="bulk"]', 'change', (e) ->
bulkAll = localElement.find('[name="bulk_all"]')
checkedCount = localElement.find('input[name="bulk"]:checked').length
checkboxCount = localElement.find('input[name="bulk"]').length
if checkedCount is 0
bulkAll.prop('indeterminate', false)
bulkAll.prop('checked', false)
@ -1362,281 +1319,6 @@ class Table extends App.Controller
onCloseCallback: @keyboardOn
)
class BulkForm extends App.Controller
className: 'bulkAction hide'
events:
'submit form': 'submit'
'click .js-submit': 'submit'
'click .js-confirm': 'confirm'
'click .js-cancel': 'reset'
@include ValidUsersForTicketSelectionMethods
constructor: ->
super
@configure_attributes_ticket = []
used_attributes = ['state_id', 'pending_time', 'priority_id', 'group_id', 'owner_id']
attributesClean = App.Ticket.attributesGet('edit')
for attributeName, attribute of attributesClean
if _.contains(used_attributes, attributeName)
localAttribute = clone(attribute)
localAttribute.nulloption = true
localAttribute.default = ''
localAttribute.null = true
@configure_attributes_ticket.push localAttribute
time_attribute = _.findWhere(@configure_attributes_ticket, {'name': 'pending_time'})
if time_attribute
time_attribute.orientation = 'top'
time_attribute.disableScroll = true
@holder = @options.holder
@visible = false
load = (data) =>
App.Collection.loadAssets(data.assets)
@formMeta = data.form_meta
@render()
@bindId = App.TicketCreateCollection.bind(load)
release: =>
App.TicketCreateCollection.unbind(@bindId)
render: ->
@el.css('right', App.Utils.getScrollBarWidth())
@html(App.view('agent_ticket_view/bulk')())
handlers = @Config.get('TicketZoomFormHandler')
for attribute in @configure_attributes_ticket
continue if attribute.name != 'owner_id'
{users, groups} = @validUsersForTicketSelection()
options = _.map(users, (user) -> {value: user.id, name: user.displayName()} )
attribute.possible_groups_owners = options
new App.ControllerForm(
el: @$('#form-ticket-bulk')
model:
configure_attributes: @configure_attributes_ticket
className: 'create'
labelClass: 'input-group-addon'
handlersConfig: handlers
params: {}
filter: @formMeta.filter
formMeta: @formMeta
noFieldset: true
)
new App.ControllerForm(
el: @$('#form-ticket-bulk-comment')
model:
configure_attributes: [{ name: 'body', display: 'Comment', tag: 'textarea', rows: 4, null: true, upload: false, item_class: 'flex' }]
className: 'create'
labelClass: 'input-group-addon'
noFieldset: true
)
@confirm_attributes = [
{ name: 'type_id', display: 'Type', tag: 'select', multiple: false, null: true, relation: 'TicketArticleType', filter: @articleTypeFilter, default: '9', translate: true, class: 'medium' }
{ name: 'internal', display: 'Visibility', tag: 'select', null: true, options: { true: 'internal', false: 'public' }, class: 'medium', item_class: '', default: false }
]
new App.ControllerForm(
el: @$('#form-ticket-bulk-typeVisibility')
model:
configure_attributes: @confirm_attributes
className: 'create'
labelClass: 'input-group-addon'
noFieldset: true
)
articleTypeFilter: (items) ->
for item in items
if item.name is 'note'
return [item]
items
confirm: =>
@$('.js-action-step').addClass('hide')
@$('.js-confirm-step').removeClass('hide')
@makeSpaceForTableRows()
# need a delay because of the click event
setTimeout ( => @$('.textarea.form-group textarea').focus() ), 0
reset: =>
@cancel()
if @visible
@makeSpaceForTableRows()
cancel: =>
@$('.js-action-step').removeClass('hide')
@$('.js-confirm-step').addClass('hide')
show: =>
@el.removeClass('hide')
@visible = true
@makeSpaceForTableRows()
hide: =>
@el.addClass('hide')
@visible = false
@removeSpaceForTableRows()
makeSpaceForTableRows: =>
height = @el.height()
scrollParent = @holder.scrollParent()
isScrolledToBottom = scrollParent.prop('scrollHeight') is scrollParent.scrollTop() + scrollParent.outerHeight()
@holder.css('margin-bottom', height)
if isScrolledToBottom
scrollParent.scrollTop scrollParent.prop('scrollHeight') - scrollParent.outerHeight()
removeSpaceForTableRows: =>
@holder.css('margin-bottom', 0)
ticketMergeParams: (params) ->
ticketUpdate = {}
for item of params
if params[item] != '' && params[item] != null
ticketUpdate[item] = params[item]
# in case if a group is selected, set also the selected owner (maybe nobody)
if params.group_id != '' && params.group_id != null
ticketUpdate.owner_id = params.owner_id
ticketUpdate
submit: (e) =>
e.preventDefault()
@bulkCount = @holder.find('.table-overview').find('[name="bulk"]:checked').length
if @bulkCount is 0
App.Event.trigger('notify', {
type: 'error'
msg: App.i18n.translateContent('At least one object must be selected.')
})
return
ticket_ids = []
@holder.find('.table-overview').find('[name="bulk"]:checked').each( (index, element) ->
ticket_id = $(element).val()
ticket_ids.push ticket_id
)
params = @formParam(e.target)
for ticket_id in ticket_ids
ticket = App.Ticket.find(ticket_id)
ticketUpdate = @ticketMergeParams(params)
ticket.load(ticketUpdate)
# if title is empty - ticket can't processed, set ?
if _.isEmpty(ticket.title)
ticket.title = '-'
# validate ticket
errors = ticket.validate(
screen: 'edit'
)
if errors
@log 'error', 'update', errors
errorString = ''
for key, error of errors
errorString += "#{key}: #{error}"
@formValidate(
form: e.target
errors: errors
screen: 'edit'
)
App.Event.trigger('notify', {
type: 'error'
msg: App.i18n.translateContent('Bulk action stopped %s!', errorString)
})
@cancel()
return
@bulkCountIndex = 0
for ticket_id in ticket_ids
ticket = App.Ticket.find(ticket_id)
# update ticket
ticketUpdate = @ticketMergeParams(params)
# validate article
if params['body']
article = new App.TicketArticle
params.from = @Session.get().displayName()
params.ticket_id = ticket.id
params.form_id = @form_id
sender = App.TicketArticleSender.findByAttribute('name', 'Agent')
type = App.TicketArticleType.find(params['type_id'])
params.sender_id = sender.id
if !params['internal']
params['internal'] = false
@log 'notice', 'update article', params, sender
article.load(params)
errors = article.validate()
if errors
@log 'error', 'update article', errors
@formEnable(e)
return
ticket.load(ticketUpdate)
# if title is empty - ticket can't processed, set ?
if _.isEmpty(ticket.title)
ticket.title = '-'
@saveTicketArticle(ticket, article)
@holder.find('.table-overview').find('[name="bulk"]:checked').prop('checked', false)
App.Event.trigger('notify', {
type: 'success'
msg: App.i18n.translateContent('Bulk action executed!')
})
saveTicketArticle: (ticket, article) =>
ticket.save(
done: (r) =>
@bulkCountIndex++
# reset form after save
if article
article.save(
fail: (r) =>
@log 'error', 'update article', r
)
# refresh view after all tickets are proceeded
if @bulkCountIndex == @bulkCount
@render()
@hide()
# fetch overview data again
App.Event.trigger('overview:fetch')
fail: (r) =>
@bulkCountIndex++
@log 'error', 'update ticket', r
App.Event.trigger 'notify', {
type: 'error'
msg: App.i18n.translateContent('Can\'t update Ticket %s!', ticket.number)
}
)
class App.OverviewSettings extends App.ControllerModal
buttonClose: true

View File

@ -0,0 +1,278 @@
class App.TicketBulkForm extends App.Controller
className: 'bulkAction hide'
events:
'submit form': 'submit'
'click .js-submit': 'submit'
'click .js-confirm': 'confirm'
'click .js-cancel': 'reset'
@include App.ValidUsersForTicketSelectionMethods
constructor: ->
super
@configure_attributes_ticket = []
used_attributes = ['state_id', 'pending_time', 'priority_id', 'group_id', 'owner_id']
attributesClean = App.Ticket.attributesGet('edit')
for attributeName, attribute of attributesClean
if _.contains(used_attributes, attributeName)
localAttribute = clone(attribute)
localAttribute.nulloption = true
localAttribute.default = ''
localAttribute.null = true
@configure_attributes_ticket.push localAttribute
time_attribute = _.findWhere(@configure_attributes_ticket, {'name': 'pending_time'})
if time_attribute
time_attribute.orientation = 'top'
time_attribute.disableScroll = true
@holder = @options.holder
@visible = false
load = (data) =>
App.Collection.loadAssets(data.assets)
@formMeta = data.form_meta
@render()
@bindId = App.TicketCreateCollection.bind(load)
release: =>
App.TicketCreateCollection.unbind(@bindId)
render: ->
@el.css('right', App.Utils.getScrollBarWidth())
@el.addClass('no-sidebar') if @noSidebar
@html(App.view('agent_ticket_view/bulk')())
handlers = @Config.get('TicketZoomFormHandler')
for attribute in @configure_attributes_ticket
continue if attribute.name != 'owner_id'
{users, groups} = @validUsersForTicketSelection()
options = _.map(users, (user) -> {value: user.id, name: user.displayName()} )
attribute.possible_groups_owners = options
new App.ControllerForm(
el: @$('#form-ticket-bulk')
model:
configure_attributes: @configure_attributes_ticket
className: 'create'
labelClass: 'input-group-addon'
handlersConfig: handlers
params: {}
filter: @formMeta.filter
formMeta: @formMeta
noFieldset: true
)
new App.ControllerForm(
el: @$('#form-ticket-bulk-comment')
model:
configure_attributes: [{ name: 'body', display: 'Comment', tag: 'textarea', rows: 4, null: true, upload: false, item_class: 'flex' }]
className: 'create'
labelClass: 'input-group-addon'
noFieldset: true
)
@confirm_attributes = [
{ name: 'type_id', display: 'Type', tag: 'select', multiple: false, null: true, relation: 'TicketArticleType', filter: @articleTypeFilter, default: '9', translate: true, class: 'medium' }
{ name: 'internal', display: 'Visibility', tag: 'select', null: true, options: { true: 'internal', false: 'public' }, class: 'medium', item_class: '', default: false }
]
new App.ControllerForm(
el: @$('#form-ticket-bulk-typeVisibility')
model:
configure_attributes: @confirm_attributes
className: 'create'
labelClass: 'input-group-addon'
noFieldset: true
)
articleTypeFilter: (items) ->
for item in items
if item.name is 'note'
return [item]
items
confirm: =>
@$('.js-action-step').addClass('hide')
@$('.js-confirm-step').removeClass('hide')
@makeSpaceForTableRows()
# need a delay because of the click event
setTimeout ( => @$('.textarea.form-group textarea').focus() ), 0
reset: =>
@cancel()
if @visible
@makeSpaceForTableRows()
cancel: =>
@$('.js-action-step').removeClass('hide')
@$('.js-confirm-step').addClass('hide')
show: =>
@el.removeClass('hide')
@visible = true
@makeSpaceForTableRows()
hide: =>
@el.addClass('hide')
@visible = false
@removeSpaceForTableRows()
makeSpaceForTableRows: =>
height = @el.height()
scrollParent = @holder.scrollParent()
isScrolledToBottom = scrollParent.prop('scrollHeight') is scrollParent.scrollTop() + scrollParent.outerHeight()
@holder.css('margin-bottom', height)
if isScrolledToBottom
scrollParent.scrollTop scrollParent.prop('scrollHeight') - scrollParent.outerHeight()
removeSpaceForTableRows: =>
@holder.css('margin-bottom', 0)
ticketMergeParams: (params) ->
ticketUpdate = {}
for item of params
if params[item] != '' && params[item] != null
ticketUpdate[item] = params[item]
# in case if a group is selected, set also the selected owner (maybe nobody)
if params.group_id != '' && params.group_id != null
ticketUpdate.owner_id = params.owner_id
ticketUpdate
submit: (e) =>
e.preventDefault()
@bulkCount = @holder.find('.table').find('[name="bulk"]:checked').length
if @bulkCount is 0
App.Event.trigger('notify', {
type: 'error'
msg: App.i18n.translateContent('At least one object must be selected.')
})
return
ticket_ids = []
@holder.find('.table').find('[name="bulk"]:checked').each( (index, element) ->
ticket_id = $(element).val()
ticket_ids.push ticket_id
)
params = @formParam(e.target)
for ticket_id in ticket_ids
ticket = App.Ticket.find(ticket_id)
ticketUpdate = @ticketMergeParams(params)
ticket.load(ticketUpdate)
# if title is empty - ticket can't processed, set ?
if _.isEmpty(ticket.title)
ticket.title = '-'
# validate ticket
errors = ticket.validate(
screen: 'edit'
)
if errors
@log 'error', 'update', errors
errorString = ''
for key, error of errors
errorString += "#{key}: #{error}"
@formValidate(
form: e.target
errors: errors
screen: 'edit'
)
App.Event.trigger('notify', {
type: 'error'
msg: App.i18n.translateContent('Bulk action stopped %s!', errorString)
})
@cancel()
return
@bulkCountIndex = 0
for ticket_id in ticket_ids
ticket = App.Ticket.find(ticket_id)
# update ticket
ticketUpdate = @ticketMergeParams(params)
# validate article
if params['body']
article = new App.TicketArticle
params.from = @Session.get().displayName()
params.ticket_id = ticket.id
params.form_id = @form_id
sender = App.TicketArticleSender.findByAttribute('name', 'Agent')
type = App.TicketArticleType.find(params['type_id'])
params.sender_id = sender.id
if !params['internal']
params['internal'] = false
@log 'notice', 'update article', params, sender
article.load(params)
errors = article.validate()
if errors
@log 'error', 'update article', errors
@formEnable(e)
return
ticket.load(ticketUpdate)
# if title is empty - ticket can't processed, set ?
if _.isEmpty(ticket.title)
ticket.title = '-'
@saveTicketArticle(ticket, article)
@holder.find('.table').find('[name="bulk"]:checked').prop('checked', false)
App.Event.trigger('notify', {
type: 'success'
msg: App.i18n.translateContent('Bulk action executed!')
})
saveTicketArticle: (ticket, article) =>
ticket.save(
done: (r) =>
@bulkCountIndex++
# reset form after save
if article
article.save(
fail: (r) =>
@log 'error', 'update article', r
)
# refresh view after all tickets are proceeded
if @bulkCountIndex == @bulkCount
@render()
@hide()
# fetch overview data again
App.Event.trigger('overview:fetch')
fail: (r) =>
@bulkCountIndex++
@log 'error', 'update ticket', r
App.Event.trigger 'notify', {
type: 'error'
msg: App.i18n.translateContent('Can\'t update Ticket %s!', ticket.number)
}
)

View File

@ -117,11 +117,13 @@ class App.TicketList extends App.Controller
overview: @columns || [ 'number', 'title', 'customer', 'group', 'created_at' ]
model: App.Ticket
objects: list
checkbox: @checkbox
#bindRow:
# events:
# 'click': openTicket
callbackHeader: callbackHeader
callbackAttributes: callbackAttributes
bindCheckbox: @bindCheckbox
radio: @radio
)

View File

@ -11,7 +11,7 @@ class App.GlobalSearch extends App.Controller
query = params.query
# use cache for search result
currentTime = new Date
if @searchResultCache[query] && @searchResultCache[query].time > currentTime.setSeconds(currentTime.getSeconds() - 20)
if !params.force && @searchResultCache[query] && @searchResultCache[query].time > currentTime.setSeconds(currentTime.getSeconds() - 20)
if @ajaxRequestId
App.Ajax.abort(@ajaxRequestId)
@ajaxStart(params)

View File

@ -0,0 +1,43 @@
App.ValidUsersForTicketSelectionMethods =
validUsersForTicketSelection: ->
items = $('.content.active .table-overview .table').find('[name="bulk"]:checked')
# we want to display all users for which we can assign the tickets directly
# for this we need to get the groups of all selected tickets
# after we got those we need to check which users are available in all groups
# users that are not in all groups can't get the tickets assigned
ticket_ids = _.map(items, (el) -> $(el).val() )
ticket_group_ids = _.map(App.Ticket.findAll(ticket_ids), (ticket) -> ticket.group_id)
users = @usersInGroups(ticket_group_ids)
# get the list of possible groups for the current user
# from the TicketCreateCollection
# (filled for e.g. the TicketCreation or TicketZoom assignment)
# and order them by name
group_ids = _.keys(@formMeta?.dependencies?.group_id)
groups = App.Group.findAll(group_ids)
groups_sorted = _.sortBy(groups, (group) -> group.name)
# get the number of visible users per group
# from the TicketCreateCollection
# (filled for e.g. the TicketCreation or TicketZoom assignment)
for group in groups
group.valid_users_count = @formMeta?.dependencies?.group_id?[group.id]?.owner_id.length || 0
{
users: users
groups: groups_sorted
}
usersInGroups: (group_ids) ->
ids_by_group = _.chain(@formMeta?.dependencies?.group_id)
.pick(group_ids)
.values()
.map( (e) -> e.owner_id)
.value()
# Underscore's intersection doesn't work when chained
ids_in_all_groups = _.intersection(ids_by_group...)
users = App.User.findAll(ids_in_all_groups)
_.sortBy(users, (user) -> user.firstname)

View File

@ -3835,6 +3835,15 @@ footer {
min-width: $minWidth - $sidebarWidth;
}
&.no-sidebar {
@include bidi-style(left, $navigationWidth, right, 0);
min-width: $minWidth - $navigationWidth;
@include small-desktop {
min-width: $minWidth;
}
}
@include phone {
@include bidi-style(left, $mobileNavigationWidth, right, 0);
min-width: 0;

View File

@ -2,7 +2,12 @@
require 'rails_helper'
RSpec.describe 'Search', type: :system, searchindex: true do
RSpec.describe 'Search', type: :system, authenticated: true, searchindex: true do
let(:users_group) { Group.find_by(name: 'Users') }
let(:ticket_1) { create(:ticket, title: 'Testing Ticket 1', group: users_group) }
let(:ticket_2) { create(:ticket, title: 'Testing Ticket 2', group: users_group) }
let(:note) { 'Test note' }
before do
configure_elasticsearch(required: true, rebuild: true)
end
@ -13,7 +18,107 @@ RSpec.describe 'Search', type: :system, searchindex: true do
click_on 'Show Search Details'
within '#navigation .tasks a[data-key=Search]' do
expect(page).to have_text '"Welcome"'
expect(page).to have_content '"Welcome"'
end
end
context 'with ticket search result' do
before do
ticket_1 && ticket_2 && rebuild_searchindex
fill_in id: 'global-search', with: 'Testing'
click_on 'Show Search Details'
find('[data-tab-content=Ticket]').click
end
context 'checkbox' do
it 'has checkbox for each ticket records' do
within '.detail-search table.table' do
expect(page).to have_xpath(".//td[contains(@class, 'js-checkbox-field')]//input[@type='checkbox']", visible: :all, minimum: 2)
end
end
it 'has select all checkbox' do
within '.detail-search table.table' do
expect(page).to have_xpath(".//th//input[@type='checkbox' and @name='bulk_all']", visible: :all, count: 1)
end
end
it 'shows bulkform when checkbox is checked' do
within '.detail-search table.table' do
find("tr[data-id='#{ticket_1.id}']").check('bulk', allow_label_click: true)
end
expect(page).to have_selector('.bulkAction.no-sidebar')
.and have_no_selector('.bulkAction.no-sidebar.hide', visible: :all)
end
it 'shows bulkform when all checkbox is checked' do
within '.detail-search table.table' do
find('th.table-checkbox').check('bulk_all', allow_label_click: true)
end
expect(page).to have_selector('.bulkAction.no-sidebar')
.and have_no_selector('.bulkAction.no-sidebar.hide', visible: :all)
end
it 'hides bulkform when checkbox is unchecked' do
within '.detail-search table.table' do
find('th.table-checkbox').check('bulk_all', allow_label_click: true)
all('.js-tableBody tr.item').each { |row| row.uncheck('bulk', allow_label_click: true) }
end
expect(page).to have_selector('.bulkAction.no-sidebar.hide', visible: :hide)
end
end
context 'with bulkform activated' do
before do
find('th.table-checkbox').check('bulk_all', allow_label_click: true)
end
it 'has group label' do
within '.bulkAction .bulkAction-form' do
expect(page).to have_content 'GROUP'
end
end
it 'has owner label' do
within '.bulkAction .bulkAction-form' do
expect(page).to have_content 'OWNER'
end
end
it 'has state label' do
within '.bulkAction .bulkAction-form' do
expect(page).to have_content 'STATE'
end
end
it 'has priority label' do
within '.bulkAction .bulkAction-form' do
expect(page).to have_content 'PRIORITY'
end
end
end
context 'bulk note' do
before { current_window.resize_to(1300, 1040) }
it 'adds note to selected ticket' do
within :active_content do
find("tr[data-id='#{ticket_1.id}']").check('bulk', allow_label_click: true)
click '.js-confirm'
find('.js-confirm-step textarea').fill_in with: note
click '.js-submit'
end
expect do
wait(10, interval: 0.1).until { ticket_1.articles.last&.body == note }
end.not_to raise_error
end
end
end