search: configure target page for card engine (#68606)

This commit is contained in:
Lauréline Guérin 2022-09-01 15:06:46 +02:00
parent d051059544
commit b7b73533b7
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
7 changed files with 170 additions and 49 deletions

View File

@ -17,6 +17,7 @@
from django import forms
from django.utils.translation import gettext_lazy as _
from combo.apps.wcs.utils import get_matching_pages_from_card_slug
from combo.data.models import Page
from combo.profile import default_description_template
@ -107,6 +108,10 @@ class TextEngineSettingsForm(TextEngineSettingsUpdateForm):
class CardsEngineSettingsUpdateForm(forms.ModelForm):
title = forms.CharField(label=_('Custom Title'), required=False)
target_page = forms.ModelChoiceField(
label=_('Target page'),
queryset=Page.objects.none(),
)
class Meta:
model = SearchCell
@ -120,6 +125,16 @@ class CardsEngineSettingsUpdateForm(forms.ModelForm):
)
super().__init__(*args, **kwargs)
matching_pages = get_matching_pages_from_card_slug(self.engine_slug.split(':')[2])
if len(matching_pages) < 2:
del self.fields['target_page']
return
pages_queryset = Page.objects.filter(pk__in=[p.pk for p in matching_pages])
pages_choices = [(x.pk, x.get_full_path_titles()) for x in matching_pages]
self.fields['target_page'].queryset = pages_queryset
self.fields['target_page'].choices = pages_choices
def get_title(self):
return _('Update "%s" engine') % self.engine.get('label')

View File

@ -34,6 +34,20 @@ from combo.manager.views import ManagedPageMixin
from combo.profile import default_description_template
def get_engine_options(form):
kwargs = {
'title': form.cleaned_data['title'],
}
if form.cleaned_data.get('description_template'):
kwargs['description_template'] = form.cleaned_data['description_template']
if form.cleaned_data.get('target_page'):
kwargs['target_page'] = form.cleaned_data['target_page'].pk
for key in ['without_user', 'with_description']:
if form.cleaned_data.get(key):
kwargs[key] = True
return kwargs
class PageSearchCellAddEngine(ManagedPageMixin, View):
def get(self, *args, **kwargs):
return self.post(*args, **kwargs)
@ -72,14 +86,7 @@ class PageSearchCellAddEngine(ManagedPageMixin, View):
if request.method == 'POST':
form = form_class(instance=cell, data=request.POST, engine_slug=engine_slug)
if form.is_valid():
kwargs = {
'title': form.cleaned_data['title'],
}
if form.cleaned_data.get('description_template'):
kwargs['description_template'] = form.cleaned_data['description_template']
for key in ['without_user', 'with_description']:
if form.cleaned_data.get(key):
kwargs[key] = True
kwargs = get_engine_options(form)
return add_slug(form.get_slug(), **kwargs)
else:
form = form_class(instance=cell, engine_slug=engine_slug)
@ -114,14 +121,7 @@ class PageSearchCellUpdateEngine(ManagedPageMixin, View):
if request.method == 'POST':
form = form_class(instance=cell, data=request.POST, engine_slug=engine_slug)
if form.is_valid():
kwargs = {
'title': form.cleaned_data['title'],
}
if form.cleaned_data.get('description_template'):
kwargs['description_template'] = form.cleaned_data['description_template']
for key in ['without_user', 'with_description']:
if form.cleaned_data.get(key):
kwargs[key] = True
kwargs = get_engine_options(form)
if not cell._search_services.get('options'):
cell._search_services['options'] = {}
@ -134,18 +134,13 @@ class PageSearchCellUpdateEngine(ManagedPageMixin, View):
% (reverse('combo-manager-page-view', kwargs={'pk': page_pk}), cell_reference)
)
else:
options = cell._search_services.get('options', {}).get(engine_slug, {})
initial = {
'title': cell._search_services.get('options', {}).get(engine_slug, {}).get('title'),
'without_user': cell._search_services.get('options', {})
.get(engine_slug, {})
.get('without_user'),
'with_description': cell._search_services.get('options', {})
.get(engine_slug, {})
.get('with_description'),
'description_template': cell._search_services.get('options', {})
.get(engine_slug, {})
.get('description_template')
or default_description_template,
'title': options.get('title'),
'without_user': options.get('without_user'),
'with_description': options.get('with_description'),
'description_template': options.get('description_template') or default_description_template,
'target_page': options.get('target_page'),
}
form = form_class(instance=cell, engine_slug=engine_slug, initial=initial)
context = {

View File

@ -258,11 +258,19 @@ class SearchCell(CellBase):
if service.get('data_key'):
results['data'] = results.get(service['data_key']) or []
hit_templates = {}
if service.get('hit_url_template'):
options = service.get('options') or {}
if options.get('target_page'):
try:
page = Page.objects.get(pk=options['target_page'])
page_base_url = page.get_online_url()
hit_templates['url'] = Template('%s{{ id }}/' % page_base_url)
except Page.DoesNotExist:
pass
if not hit_templates.get('url') and service.get('hit_url_template'):
hit_templates['url'] = Template(service['hit_url_template'])
if service.get('hit_label_template'):
hit_templates['text'] = Template(service['hit_label_template'])
if (service.get('options') or {}).get('description_template'):
if options.get('description_template'):
hit_templates['description'] = Template(service['options']['description_template'])
if not hit_templates.get('description') and service.get('hit_description_template'):
hit_templates['description'] = Template(service['hit_description_template'])

View File

@ -48,7 +48,7 @@ class AppConfig(django.apps.AppConfig):
def get_card_search_engines(self, wcs_services):
from combo.data.models import Page
from .utils import get_wcs_json
from .utils import get_matching_pages_from_card_slug, get_wcs_json
pages_with_sub_slug = Page.objects.exclude(sub_slug='')
if not pages_with_sub_slug:
@ -58,10 +58,7 @@ class AppConfig(django.apps.AppConfig):
for key, service in wcs_services.items():
card_models = get_wcs_json(service, 'api/cards/@list')
for card in card_models.get('data') or []:
card_id = '%s_id' % card['id']
matching_pages = [
p for p in pages_with_sub_slug if '<%s>' % card_id in p.sub_slug or p.sub_slug == card_id
]
matching_pages = get_matching_pages_from_card_slug(card['id'])
if not matching_pages:
continue
card_page = matching_pages[0]

View File

@ -38,7 +38,7 @@ from combo.data.models import CellBase, Page
from combo.utils import NothingInCacheException, requests
from combo.utils.misc import is_portal_agent
from .utils import get_wcs_json, get_wcs_services, is_wcs_enabled
from .utils import get_matching_pages_from_card_slug, get_wcs_json, get_wcs_services, is_wcs_enabled
invalid_reason_codes = {
'wcs_form_not_defined': _('No form set'),
@ -1365,18 +1365,7 @@ class WcsCardCell(CardMixin, CellBase):
return '%s card card-%s %s' % (super().css_class_names, self.display_mode, self.get_reference())
def get_matching_pages(self, order=True):
if order:
pages = Page.get_with_hierarchy_attributes().values()
pages_with_sub_slug = [p for p in pages if p.sub_slug]
else:
pages_with_sub_slug = Page.objects.exclude(sub_slug='')
card_id = '%s_id' % self.card_slug
matching_pages = [
p for p in pages_with_sub_slug if '<%s>' % card_id in p.sub_slug or p.sub_slug == card_id
]
if not order:
return matching_pages
return Page.get_as_reordered_flat_hierarchy(matching_pages)
return get_matching_pages_from_card_slug(self.card_slug, order=order)
def get_cell_extra_context(self, context):
extra_context = super().get_cell_extra_context(context)

View File

@ -85,3 +85,20 @@ def get_wcs_options(url, include_category_slug=False, include_custom_views=False
('%s:%s' % (reference, custom_view['id']), '%s - %s' % (label, custom_view['text']))
)
return references
def get_matching_pages_from_card_slug(card_slug, order=True):
from combo.data.models import Page
if order:
pages = Page.get_with_hierarchy_attributes().values()
pages_with_sub_slug = [p for p in pages if p.sub_slug]
else:
pages_with_sub_slug = Page.objects.exclude(sub_slug='')
card_id = '%s_id' % card_slug
matching_pages = [
p for p in pages_with_sub_slug if '<%s>' % card_id in p.sub_slug or p.sub_slug == card_id
]
if not order:
return matching_pages
return Page.get_as_reordered_flat_hierarchy(matching_pages)

View File

@ -958,7 +958,8 @@ def test_wcs_errors(settings, app):
def test_wcs_add_search_engines(mock_wcs, settings, app, admin_user):
settings.KNOWN_SERVICES = {'wcs': {'default': {'title': 'test', 'url': 'http://127.0.0.1:8999/'}}}
settings.TEMPLATE_VARS['is_portal_agent'] = True
Page.objects.create(slug='bar', title='Bar', sub_slug='card-bar_id')
root_page = Page.objects.create(title='Root', slug='root', template_name='standard')
card_page1 = Page.objects.create(slug='bar', title='Bar', sub_slug='card-bar_id', parent=root_page)
mock_wcs.return_value = {'data': [{'id': 'card-bar', 'text': 'Card Bar'}]}
page = Page.objects.create(title='One', slug='one', template_name='standard')
@ -984,6 +985,7 @@ def test_wcs_add_search_engines(mock_wcs, settings, app, admin_user):
resp = resp.click(href='.*/search_searchcell-%s/engine/cards:c21f969b:card-bar/add/' % cell.pk)
assert resp.context['form'].fields['selected_view'].choices == [(None, '- All cards -')]
assert 'target_page' not in resp.context['form'].fields
resp.form['title'] = 'Custom Title'
resp = resp.form.submit('submit')
assert resp.status_int == 302
@ -1033,6 +1035,7 @@ def test_wcs_add_search_engines(mock_wcs, settings, app, admin_user):
# edit engine
resp = resp.follow()
resp = resp.click(href='.*/search_searchcell-%s/engine/cards:c21f969b:card-bar/edit/' % cell.pk)
assert 'target_page' not in resp.context['form'].fields
resp.form['title'] = 'Custom Title Foo Bar'
resp = resp.form.submit('submit')
assert resp.status_int == 302
@ -1074,6 +1077,56 @@ def test_wcs_add_search_engines(mock_wcs, settings, app, admin_user):
'cards:c21f969b:card-bar__without-user__',
'cards:c21f969b:card-bar__without-user__:foo',
]
for key in cell._search_services['data']:
resp = resp.follow()
resp = resp.click(href='.*/search_searchcell-%s/engine/%s/delete/' % (cell.pk, key))
assert resp.status_int == 302
assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.pk, cell.get_reference()))
cell.refresh_from_db()
assert cell._search_services['data'] == []
# more than on page with matchin sub_slug
other_root_page = Page.objects.create(title='Other root', slug='other-root', template_name='standard')
card_page2 = Page.objects.create(
slug='bar-bis', title='Bar (bis)', sub_slug='card-bar_id', parent=other_root_page
)
resp = app.get('/manage/pages/%s/' % page.pk)
resp = resp.click(href='.*/search_searchcell-%s/engine/cards:c21f969b:card-bar/add/' % cell.pk)
assert resp.context['form'].fields['target_page'].choices == [
(card_page1.pk, 'Root / Bar'),
(card_page2.pk, 'Other root / Bar (bis)'),
]
resp.form['target_page'] = card_page2.pk
resp = resp.form.submit('submit')
assert resp.status_int == 302
assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.pk, cell.get_reference()))
cell.refresh_from_db()
assert cell._search_services['data'] == [
'cards:c21f969b:card-bar',
]
assert cell._search_services['options'] == {
'cards:c21f969b:card-bar': {'target_page': card_page2.pk, 'title': ''}
}
resp = resp.follow()
resp = resp.click(href='.*/search_searchcell-%s/engine/cards:c21f969b:card-bar/edit/' % cell.pk)
assert resp.form['target_page'].value == str(card_page2.pk)
resp = resp.form.submit('submit')
assert resp.status_int == 302
assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.pk, cell.get_reference()))
cell.refresh_from_db()
assert cell._search_services['options'] == {
'cards:c21f969b:card-bar': {'target_page': card_page2.pk, 'title': ''}
}
resp = resp.follow()
resp = resp.click(href='.*/search_searchcell-%s/engine/cards:c21f969b:card-bar/edit/' % cell.pk)
resp.form['target_page'] = card_page1.pk
resp = resp.form.submit('submit')
assert resp.status_int == 302
assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.pk, cell.get_reference()))
cell.refresh_from_db()
assert cell._search_services['options'] == {
'cards:c21f969b:card-bar': {'target_page': card_page1.pk, 'title': ''}
}
@mock.patch('combo.apps.wcs.utils.get_wcs_json')
@ -1081,7 +1134,14 @@ def test_wcs_add_search_engines(mock_wcs, settings, app, admin_user):
def test_wcs_search_cell(requests_get, mock_wcs, settings, app):
settings.KNOWN_SERVICES = {'wcs': {'default': {'title': 'test', 'url': 'http://127.0.0.1:8999/'}}}
settings.TEMPLATE_VARS['is_portal_agent'] = True
Page.objects.create(slug='bar', title='Bar', sub_slug='(?P<card-bar_id>[a-z0-9]+)')
root_page = Page.objects.create(title='Root', slug='root', template_name='standard')
card_page1 = Page.objects.create(
slug='bar', title='Bar', sub_slug='(?P<card-bar_id>[a-z0-9]+)', parent=root_page
)
other_root_page = Page.objects.create(title='Other root', slug='other-root', template_name='standard')
card_page2 = Page.objects.create(
slug='bar-bis', title='Bar (bis)', sub_slug='(?P<card-bar_id>[a-z0-9]+)', parent=other_root_page
)
mock_wcs.return_value = {
'data': [{'id': 'card-bar', 'text': 'Card Bar', 'custom_views': [{'id': 'foo', 'text': 'Foo'}]}]
}
@ -1158,6 +1218,46 @@ def test_wcs_search_cell(requests_get, mock_wcs, settings, app):
app.get('/ajax/search/%s/cards:c21f969b:card-bar/?q=foobar' % cell.pk)
assert requests_get.call_args_list == []
# test result urls
# no target_page specified in options
mock_wcs.return_value = {'data': [{'id': 'card-bar', 'text': 'Card Bar', 'custom_views': []}]}
requests_get.reset_mock()
response = {
'data': [
{
'id': 12,
'text': 'bar12',
}
],
}
mock_json = mock.Mock()
mock_json.json.return_value = response
requests_get.return_value = mock_json
resp = app.get('/ajax/search/%s/cards:c21f969b:card-bar/?q=foobar' % cell.pk)
assert (
requests_get.call_args_list[0][0][0]
== 'http://127.0.0.1:8999/api/cards/card-bar/list/?NameID=&q=foobar'
)
assert '/root/bar/12/' in resp
cell._search_services['options'] = {
'cards:c21f969b:card-bar': {'target_page': card_page1.pk, 'title': ''}
}
cell.save()
resp = app.get('/ajax/search/%s/cards:c21f969b:card-bar/?q=foobar' % cell.pk)
assert '/root/bar/12/' in resp
cell._search_services['options'] = {
'cards:c21f969b:card-bar': {'target_page': card_page2.pk, 'title': ''}
}
cell.save()
resp = app.get('/ajax/search/%s/cards:c21f969b:card-bar/?q=foobar' % cell.pk)
assert '/other-root/bar-bis/12/' in resp
cell._search_services['options'] = {
'cards:c21f969b:card-bar': {'target_page': 0, 'title': ''}
} # unknown page
cell.save()
resp = app.get('/ajax/search/%s/cards:c21f969b:card-bar/?q=foobar' % cell.pk)
assert '/root/bar/12/' in resp
def test_profile_search_engines(settings, app):
settings.KNOWN_SERVICES = {}