Fixes #3559 - mentioned KB entries with the same title in different categories can not distinguished.
This commit is contained in:
parent
205c717f4d
commit
328845c283
11 changed files with 108 additions and 14 deletions
|
@ -90,9 +90,17 @@ class App.SearchableSelect extends Spine.Controller
|
|||
renderOptions: (options) ->
|
||||
html = ''
|
||||
for option in options
|
||||
classes = 'u-textTruncate'
|
||||
if option.children
|
||||
classes += ' js-enter'
|
||||
else
|
||||
classes += ' js-option'
|
||||
if option.category
|
||||
classes += ' with-category'
|
||||
|
||||
html += App.view('generic/searchable_select_option')
|
||||
option: option
|
||||
class: if option.children then 'js-enter' else 'js-option'
|
||||
class: classes
|
||||
html
|
||||
|
||||
renderAllOptions: (parentName, options, level) ->
|
||||
|
|
|
@ -78,10 +78,15 @@ class App.SearchableAjaxSelect extends App.SearchableSelect
|
|||
renderResponseItemAjax: (elem, data) ->
|
||||
result = _.find(data.details, (detailElem) -> detailElem.type == elem.type and detailElem.id == elem.id)
|
||||
|
||||
category = undefined
|
||||
if result.type is 'KnowledgeBase::Answer::Translation' && result.subtitle
|
||||
category = result.subtitle
|
||||
|
||||
if result
|
||||
{
|
||||
name: result.title
|
||||
value: elem.id
|
||||
category: category
|
||||
name: result.title
|
||||
value: elem.id
|
||||
}
|
||||
|
||||
renderResponseItem: (elem) ->
|
||||
|
|
|
@ -577,7 +577,8 @@
|
|||
'flavor': 'agent',
|
||||
'index': 'KnowledgeBase::Answer::Translation',
|
||||
'url_type': 'agent',
|
||||
'highlight_enabled': false
|
||||
'highlight_enabled': false,
|
||||
'include_locale': true,
|
||||
}),
|
||||
processData: true,
|
||||
success: function(data, status, xhr) {
|
||||
|
@ -585,12 +586,13 @@
|
|||
|
||||
var items = data
|
||||
.result
|
||||
.map(function(elem){
|
||||
.map(function(elem) {
|
||||
if(result = _.find(data.details, function(detailElem) { return detailElem.type == elem.type && detailElem.id == elem.id })) {
|
||||
return {
|
||||
'name': result.title,
|
||||
'value': elem.id,
|
||||
'url': result.url
|
||||
'category': result.subtitle,
|
||||
'name': result.title,
|
||||
'value': elem.id,
|
||||
'url': result.url
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -599,8 +601,11 @@
|
|||
var element = $('<li>')
|
||||
.attr('data-id', elem.value)
|
||||
.attr('data-url', elem.url)
|
||||
.text(elem.name)
|
||||
.addClass('u-clickable u-textTruncate')
|
||||
.addClass('u-clickable u-textTruncate with-category')
|
||||
|
||||
element.append($('<small>').text(elem.category))
|
||||
element.append('<br>')
|
||||
element.append($('<span>').text(elem.name))
|
||||
|
||||
if (index == array.length-1) {
|
||||
element.addClass('is-active')
|
||||
|
|
|
@ -38,6 +38,22 @@ class App.KnowledgeBaseCategory extends App.Model
|
|||
memo.concat elem.categoriesForDropdown(nested: options.nested + 1, kb_locale: options.kb_locale)
|
||||
, initial
|
||||
|
||||
categoriesForSearch: (options = {}) ->
|
||||
result = [@guaranteedTitle(options.kb_locale.id)]
|
||||
|
||||
check = @
|
||||
while check.parent()
|
||||
result.push(check.parent().guaranteedTitle(options.kb_locale.id))
|
||||
check = check.parent()
|
||||
|
||||
if options.full || result.length <= 2
|
||||
result = result.reverse().join(' > ')
|
||||
else
|
||||
result = result.reverse()
|
||||
result = "#{result[0]} > .. > #{result[result.length - 1]}"
|
||||
|
||||
result
|
||||
|
||||
configure_attributes: (kb_locale = undefined) ->
|
||||
[
|
||||
{
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
<li role="presentation" class="<%= @class %>" data-value="<%= @option.value %>" title="<%= @option.name %><% if @detail: %><%= @detail %><% end %>">
|
||||
<% if @option.category: %><small><%= @option.category %></small><br><% end %>
|
||||
<span class="searchableSelect-option-text">
|
||||
<%= @option.name %><% if @detail: %><span class="dropdown-detail"><%= @detail %></span><% end %>
|
||||
</span>
|
||||
<% if @option.children: %>
|
||||
<%- @Icon('arrow-right', 'recipientList-arrow') %>
|
||||
<% end %>
|
||||
</li>
|
||||
</li>
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
-
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="column">
|
||||
<label><%- @T('Category') %></label>
|
||||
<a href="<%= @object.parent().category().uiUrl(App.KnowledgeBaseLocale.find(@object.kb_locale_id)) %>" title="<%= @object.parent().category().categoriesForSearch({ full: true, kb_locale: App.KnowledgeBaseLocale.find(@object.kb_locale_id) }) %>"><%= @object.parent().category().guaranteedTitle(@object.kb_locale_id) %></a>
|
||||
</div>
|
||||
<div class="column">
|
||||
<label><%- @T('Language') %></label>
|
||||
<%= App.KnowledgeBaseLocale.localeFor(@object).systemLocale().name %>
|
||||
|
|
|
@ -8371,6 +8371,16 @@ footer {
|
|||
}
|
||||
}
|
||||
|
||||
.dropdown li.with-category, .dropdown.dropdown--actions li.with-category {
|
||||
line-height: 19.5px;
|
||||
}
|
||||
|
||||
.dropdown.dropdown--actions li.with-category {
|
||||
height: 39px;
|
||||
padding: 0px 15px;
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
.dropdown li:not(:first-child) {
|
||||
box-shadow: 0 1px rgba(255,255,255,.13) inset;
|
||||
}
|
||||
|
@ -13023,4 +13033,3 @@ span.is-disabled {
|
|||
.text-modules-box {
|
||||
max-height: 40vh;
|
||||
}
|
||||
|
||||
|
|
|
@ -75,7 +75,13 @@ class KnowledgeBase::SearchController < ApplicationController
|
|||
|
||||
def public_item_details_answer(meta, object)
|
||||
category_translation = object.answer.category.translation_preferred(object.kb_locale)
|
||||
path = help_answer_path(category_translation, object, locale: object.kb_locale.system_locale.locale)
|
||||
path = help_answer_path(category_translation, object, locale: object.kb_locale.system_locale.locale)
|
||||
subtitle = object.answer.category.self_with_parents.map { |c| strip_tags(c.translation_preferred(object.kb_locale).title) }.reverse
|
||||
subtitle = if subtitle.count <= 2
|
||||
subtitle.join(' > ')
|
||||
else
|
||||
subtitle.values_at(0, -1).join(' > .. > ')
|
||||
end
|
||||
|
||||
url = case url_type
|
||||
when :public
|
||||
|
@ -91,7 +97,7 @@ class KnowledgeBase::SearchController < ApplicationController
|
|||
date: object.updated_at,
|
||||
url: url,
|
||||
title: meta.dig(:highlight, 'title')&.first || object.title,
|
||||
subtitle: strip_tags(category_translation.title),
|
||||
subtitle: subtitle,
|
||||
body: meta.dig(:highlight, 'content.body')&.first || strip_tags(object.content.body).truncate(100)
|
||||
}
|
||||
end
|
||||
|
|
|
@ -61,6 +61,18 @@ class KnowledgeBase::Category < ApplicationModel
|
|||
[self] + children.map(&:self_with_children).flatten
|
||||
end
|
||||
|
||||
def self_with_parents
|
||||
result = [self]
|
||||
|
||||
check = self
|
||||
while check.parent.present?
|
||||
result << check.parent
|
||||
check = check.parent
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
def self_with_children_answers
|
||||
KnowledgeBase::Answer.where(category_id: self_with_children_ids)
|
||||
end
|
||||
|
|
|
@ -40,6 +40,10 @@ RSpec.describe KnowledgeBase::Category, type: :model, current_user_id: 1 do
|
|||
expect(kb_category_with_tree.self_with_children.count).to eq 7
|
||||
end
|
||||
|
||||
it 'fetches all parents' do
|
||||
expect(grandchild_category.self_with_parents.count).to eq 3
|
||||
end
|
||||
|
||||
it 'root category has no parent' do
|
||||
expect(kb_category_with_tree.parent).to be_blank
|
||||
end
|
||||
|
|
|
@ -61,4 +61,28 @@ RSpec.describe 'Knowledge Base search with details', type: :request, searchindex
|
|||
expect(json_response['details'][0]['subtitle']).to eq category.translation_to(primary_locale).title
|
||||
end
|
||||
end
|
||||
|
||||
context 'when answer tree is long' do
|
||||
let(:category1) { create('knowledge_base/category') }
|
||||
let(:category2) { create('knowledge_base/category', parent: category1) }
|
||||
let(:category3) { create('knowledge_base/category', parent: category2) }
|
||||
let(:answer_cut_tree) { create(:knowledge_base_answer, :published, :with_attachment, category: category3) }
|
||||
let(:category4) { create('knowledge_base/category') }
|
||||
let(:category5) { create('knowledge_base/category', parent: category4) }
|
||||
let(:answer_full_tree) { create(:knowledge_base_answer, :published, :with_attachment, category: category5) }
|
||||
|
||||
before do
|
||||
answer_cut_tree && answer_full_tree && rebuild_searchindex
|
||||
end
|
||||
|
||||
it 'returns category with cut tree', authenticated_as: -> { create(:admin) } do
|
||||
post endpoint, params: { query: answer_cut_tree.translations.first.title }
|
||||
expect(json_response['details'][0]['subtitle']).to eq("#{category1.translations.first.title} > .. > #{category3.translations.first.title}")
|
||||
end
|
||||
|
||||
it 'returns category with full tree', authenticated_as: -> { create(:admin) } do
|
||||
post endpoint, params: { query: answer_full_tree.translations.first.title }
|
||||
expect(json_response['details'][0]['subtitle']).to eq("#{category4.translations.first.title} > #{category5.translations.first.title}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue