search: configure target page for card engine (#68606)
This commit is contained in:
parent
d051059544
commit
b7b73533b7
|
@ -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')
|
||||
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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'])
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 = {}
|
||||
|
|
Loading…
Reference in New Issue