Skip to content

Commit

Permalink
Fixes #4409 - Alphabetical listing of the user-defined object list do…
Browse files Browse the repository at this point in the history
…es not list the tickets correctly
  • Loading branch information
mantas committed Dec 1, 2023
1 parent 59aa481 commit cd8a11c
Show file tree
Hide file tree
Showing 3 changed files with 282 additions and 1 deletion.
Expand Up @@ -817,6 +817,56 @@ class App.ControllerTable extends App.Controller
console.log('Got empty object in order by with header _.sortBy')
return ''

if _.includes(['multiselect', 'select'], header.tag)
rawValue = item[header.name]

if !_.isArray(rawValue)
rawValue = [rawValue]

sortValue = if _.isArray(header.options)
rawValue
.map (elem) -> _.findIndex(header.options, (option) -> option.value == elem)
.sort()
else if _.isObject(header.options)
rawValue
.map (elem) ->
displayValue = header.options[elem]

if displayValue && header.translate
displayValue = App.i18n.translateInline(displayValue)

value = displayValue || elem

if typeof value is 'string'
value = value.toLocaleLowerCase()

value
.sort()
else if header.relation
rawValue
.map (elem) ->
relatedItem = App[header.relation].findNative(item[header.name])

return '' if !relatedItem

displayValue = relatedItem.displayName?() || relatedItem.name || ''

if displayValue && header.translate
displayValue = App.i18n.translateInline(displayValue)

value = displayValue || elem

if typeof value is 'string'
value = value.toLocaleLowerCase()

value
.sort()

else
rawValue

return sortValue

# if we need to sort translated col.
if header.translate
return App.i18n.translateInline(item[header.name])
Expand Down
25 changes: 24 additions & 1 deletion app/assets/javascripts/app/index.coffee
Expand Up @@ -74,8 +74,28 @@ class App extends Spine.Controller
hasMoreItems = true
items = items.slice(0, attributeConfig.display_limit)

sorted = if attributeConfig.tag is 'multiselect'
if _.isArray(attributeConfig.options)
_.sortBy(items, (elem) -> _.findIndex(attributeConfig.options, (option) -> option.value == elem))
else
_.sortBy(items, (elem) ->
displayValue = attributeConfig.options[elem]

if displayValue && attributeConfig.translate
displayValue = App.i18n.translateInline(displayValue)

value = displayValue || elem

if typeof value is 'string'
value = value.toLocaleLowerCase()

value
)
else
items.sort()

# lookup relation
for item in items.sort()
for item in sorted
resultLocal = item
if attributeConfig.relation || valueRef
if valueRef
Expand All @@ -100,6 +120,9 @@ class App extends Spine.Controller
else
resultLocal = item.label

if attributeConfig.translate
resultLocal = App.i18n.translateInline(resultLocal)

# execute callback on content
if attributeConfig.callback
resultLocal = attributeConfig.callback(resultLocal, attributeConfig)
Expand Down
208 changes: 208 additions & 0 deletions spec/system/overview_spec.rb
Expand Up @@ -415,4 +415,212 @@ def authenticate

# TODO: Add a test example for touch input once the tablet emulation mode starts working in the CI.
end

# https://github.com/zammad/zammad/issues/4409
context 'when sorting by display values', authenticated_as: :authenticate, db_strategy: :reset do
def authenticate
custom_field
ObjectManager::Attribute.migration_execute
true
end

let(:overview) { create(:overview, view: { 's'=>%w[number title overview_test] }) }
let(:custom_field) { create("object_manager_attribute_#{field_type}", name: :overview_test, data_option: data_option) }
let(:data_option) { { options: options_hash, translate: translate, default: '' } }
let(:translate) { false }
let(:group) { Group.first }

let(:options_hash) do
{
'key_1' => 'A value',
'key_2' => 'D value',
'key_3' => 'B value',
'key_4' => 'C value',
}
end

let(:custom_sorted_array) do
[
{ value: 'key_1', name: 'C value' },
{ value: 'key_3', name: 'A value' },
{ value: 'key_2', name: 'B value' },
{ value: 'key_4', name: 'D value' },
]
end

let(:translations_hash) do
{
'A value' => 'Pirma vertė',
'B value' => 'Antra vertė',
'C value' => 'Trečia vertė',
'D value' => 'Ketvirta vertė'
}
end

before do
Ticket.destroy_all

translations_hash.each { |key, value| create(:translation, locale: 'en-us', source: key, target: value) }

ticket_1 && ticket_2 && ticket_3 && ticket_4

visit "ticket/view/#{overview.link}"

find('[data-column-key=overview_test] .js-sort').click
end

context 'when field is select' do
let(:field_type) { 'select' }

let(:ticket_1) { create(:ticket, title: 'A ticket', overview_test: 'key_1', group: group) }
let(:ticket_2) { create(:ticket, title: 'B ticket', overview_test: 'key_2', group: group) }
let(:ticket_3) { create(:ticket, title: 'C ticket', overview_test: 'key_3', group: group) }
let(:ticket_4) { create(:ticket, title: 'D ticket', overview_test: 'key_4', group: group) }

context 'when custom sort is on' do
let(:data_option) { { options: custom_sorted_array, default: '', customsort: 'on' } }

it 'sorts tickets correctly' do
within '.js-tableBody' do
expect(page)
.to have_css('tr:nth-child(1)', text: ticket_1.title)
.and have_css('tr:nth-child(2)', text: ticket_3.title)
.and have_css('tr:nth-child(3)', text: ticket_2.title)
.and have_css('tr:nth-child(4)', text: ticket_4.title)
end
end
end

context 'when custom sort is off' do
it 'sorts tickets correctly' do
within '.js-tableBody' do
expect(page)
.to have_css('tr:nth-child(1)', text: ticket_1.title)
.and have_css('tr:nth-child(2)', text: ticket_3.title)
.and have_css('tr:nth-child(3)', text: ticket_4.title)
.and have_css('tr:nth-child(4)', text: ticket_2.title)
end
end
end

context 'when display values are translated' do
let(:translate) { true }

it 'sorts tickets correctly' do
within '.js-tableBody' do
expect(page)
.to have_css('tr:nth-child(1)', text: ticket_3.title)
.and have_css('tr:nth-child(2)', text: ticket_2.title)
.and have_css('tr:nth-child(3)', text: ticket_1.title)
.and have_css('tr:nth-child(4)', text: ticket_4.title)
end
end
end
end

context 'when field is multiselect' do
let(:field_type) { 'multiselect' }

let(:ticket_1) { create(:ticket, title: 'A ticket', overview_test: '{key_1}', group: group) }
let(:ticket_2) { create(:ticket, title: 'B ticket', overview_test: '{key_2,key_3}', group: group) }
let(:ticket_3) { create(:ticket, title: 'C ticket', overview_test: '{key_4,key_3,key_2}', group: group) }
let(:ticket_4) { create(:ticket, title: 'D ticket', overview_test: '{key_2}', group: group) }

context 'when custom sort is on' do
let(:data_option) { { options: custom_sorted_array, default: '', customsort: 'on' } }

it 'sorts tickets correctly' do
within '.js-tableBody' do
expect(page)
.to have_css('tr:nth-child(1)', text: ticket_1.title)
.and have_css('tr:nth-child(2)', text: ticket_2.title)
.and have_css('tr:nth-child(3)', text: ticket_3.title)
.and have_css('tr:nth-child(4)', text: ticket_4.title)
end
end
end

context 'when custom sort is off' do
it 'sorts tickets correctly' do
within '.js-tableBody' do
expect(page)
.to have_css('tr:nth-child(1)', text: ticket_1.title)
.and have_css('tr:nth-child(2)', text: ticket_3.title)
.and have_css('tr:nth-child(3)', text: ticket_2.title)
.and have_css('tr:nth-child(4)', text: ticket_4.title)
end
end
end

context 'when display values are translated' do
let(:translate) { true }

it 'sorts tickets correctly' do
within '.js-tableBody' do
expect(page)
.to have_css('tr:nth-child(1)', text: ticket_2.title)
.and have_css('tr:nth-child(2)', text: ticket_3.title)
.and have_css('tr:nth-child(3)', text: ticket_4.title)
.and have_css('tr:nth-child(4)', text: ticket_1.title)
end
end
end
end
end

# https://github.com/zammad/zammad/issues/4409
# Touched by above issue, but not directly related
context 'when sorting by select field without options' do
let(:overview) do
create(:overview, condition: {
'ticket.state_id' => {
operator: 'is',
value: Ticket::State.where(name: %w[new open closed]).pluck(:id),
},
})
end

let(:ticket_1) { create(:ticket, title: 'A ticket', state_name: 'open', group: group) }
let(:ticket_2) { create(:ticket, title: 'B ticket', state_name: 'closed', group: group) }
let(:ticket_3) { create(:ticket, title: 'C ticket', state_name: 'new', group: group) }
let(:group) { Group.first }

before do
if defined?(translations_hash)
translations_hash.each do |key, value|
Translation.find_or_create_by(locale: 'en-us', source: key).update!(target: value)
end
end

Ticket.destroy_all

ticket_1 && ticket_2 && ticket_3

visit "ticket/view/#{overview.link}"

find('[data-column-key=state_id] .js-sort').click
end

it 'sorts tickets correctly' do
within '.js-tableBody' do
expect(page)
.to have_css('tr:nth-child(1)', text: ticket_2.title)
.and have_css('tr:nth-child(2)', text: ticket_3.title)
.and have_css('tr:nth-child(3)', text: ticket_1.title)
end
end

context 'when states are translated' do
let(:translations_hash) { { 'closed' => 'zzz closed' } }

it 'sorts tickets correctly' do
within '.js-tableBody' do
expect(page)
.to have_css('tr:nth-child(1)', text: ticket_3.title)
.and have_css('tr:nth-child(2)', text: ticket_1.title)
.and have_css('tr:nth-child(3)', text: ticket_2.title)
end
end
end
end
end

0 comments on commit cd8a11c

Please sign in to comment.