wcs: render card cell with table mode (#68063)
This commit is contained in:
parent
fed5465f98
commit
7716113a51
|
@ -34,7 +34,7 @@ from requests.exceptions import RequestException
|
|||
|
||||
from combo.data.library import register_cell_class
|
||||
from combo.data.models import CellBase, Page
|
||||
from combo.utils import requests
|
||||
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
|
||||
|
@ -979,7 +979,6 @@ class WcsCardInfosCell(CardMixin, CellBase):
|
|||
|
||||
is_enabled = classmethod(is_wcs_enabled)
|
||||
|
||||
default_template_name = 'combo/wcs/card.html'
|
||||
manager_appearance_template = 'combo/wcs/manager/card-infos-cell-form-appearance.html'
|
||||
|
||||
class Meta:
|
||||
|
@ -1035,16 +1034,28 @@ class WcsCardInfosCell(CardMixin, CellBase):
|
|||
|
||||
self.mark_as_valid()
|
||||
|
||||
@property
|
||||
def default_template_name(self):
|
||||
if self.display_mode == 'table':
|
||||
return 'combo/wcs/cards.html'
|
||||
return 'combo/wcs/card.html'
|
||||
|
||||
@property
|
||||
def global_context_key(self):
|
||||
return '%s-card-ids' % self.get_reference()
|
||||
|
||||
def modify_global_context(self, context, request):
|
||||
if self.display_mode == 'table' and not context.get('synchronous'):
|
||||
# don't call wcs on page loading
|
||||
return
|
||||
if self.carddef_reference and self.global_context_key not in context:
|
||||
card_ids = self.get_card_ids(context, request)
|
||||
context[self.global_context_key] = card_ids
|
||||
|
||||
def get_repeat_template(self, context):
|
||||
if self.display_mode == 'table':
|
||||
# don't repeat cell if table display mode
|
||||
return []
|
||||
return len(context.get(self.global_context_key) or [])
|
||||
|
||||
def get_related_card_path(self):
|
||||
|
@ -1406,6 +1417,9 @@ class WcsCardInfosCell(CardMixin, CellBase):
|
|||
return self.filter_card_ids(card_ids, original_context)
|
||||
|
||||
if self.must_get_all():
|
||||
if self.display_mode == 'table':
|
||||
# don't call wcs if table mode with all cards
|
||||
return []
|
||||
# get all cards
|
||||
return [c['id'] for c in self.get_cards_from_ids([], original_context, synchronous=True)]
|
||||
|
||||
|
@ -1442,13 +1456,44 @@ class WcsCardInfosCell(CardMixin, CellBase):
|
|||
|
||||
def get_cell_extra_context(self, context):
|
||||
extra_context = super().get_cell_extra_context(context)
|
||||
if self.title_type in ['auto', 'manual']:
|
||||
# card mode: default value used if card is not found
|
||||
extra_context['title'] = self.cached_title
|
||||
return getattr(self, 'get_cell_extra_context_%s_mode' % self.display_mode)(context, extra_context)
|
||||
|
||||
def get_cell_extra_context_table_mode(self, context, extra_context):
|
||||
if not context.get('synchronous'):
|
||||
raise NothingInCacheException()
|
||||
|
||||
extra_context['paginate_by'] = self.limit or 10
|
||||
if self.title_type == 'manual':
|
||||
extra_context['title'] = self.custom_title or extra_context['title']
|
||||
if not self.carddef_reference:
|
||||
# not configured
|
||||
return extra_context
|
||||
|
||||
pages_with_sub_slug = Page.objects.exclude(sub_slug='')
|
||||
card_id = '%s_id' % self.carddef_reference.split(':')[1]
|
||||
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 matching_pages:
|
||||
card_page = matching_pages[0]
|
||||
extra_context['card_page_base_url'] = card_page.get_online_url()
|
||||
|
||||
card_ids = context.get(self.global_context_key)
|
||||
if not card_ids and self.related_card_path != '__all__':
|
||||
extra_context['card_objects'] = []
|
||||
else:
|
||||
extra_context['card_objects'] = self.get_cards_from_ids(card_ids, context)
|
||||
|
||||
return extra_context
|
||||
|
||||
def get_cell_extra_context_card_mode(self, context, extra_context):
|
||||
extra_context['schema'] = self.cached_json
|
||||
extra_context['fields_by_varnames'] = {
|
||||
i['varname']: i for i in (self.cached_json.get('fields') or []) if i.get('varname')
|
||||
}
|
||||
# default value used if card is not found
|
||||
if self.title_type in ['auto', 'manual']:
|
||||
extra_context['title'] = self.cached_title
|
||||
|
||||
card_id = self.get_card_id(context)
|
||||
if not card_id:
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
{% block cell-content %}
|
||||
|
||||
{% block cell-header %}
|
||||
<h2>{{ title }}</h2>
|
||||
{% if title %}<h2>{{ title|force_escape }}</h2>{% endif %}
|
||||
{% include "combo/asset_picture_fragment.html" %}
|
||||
{% endblock %}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ from combo.data.models import Page, TextCell, ValidityInfo
|
|||
from tests.test_manager import login
|
||||
from tests.utils import manager_submit_cell
|
||||
|
||||
from .utils import WCS_CARDS_DATA, MockUser, MockUserWithNameId, mocked_requests_send
|
||||
from .utils import WCS_CARDS_DATA, MockedRequestResponse, MockUser, MockUserWithNameId, mocked_requests_send
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
||||
|
@ -633,6 +633,271 @@ def test_card_cell_load(mock_send):
|
|||
assert cell.cached_title == 'Card Model 1'
|
||||
|
||||
|
||||
@mock.patch('requests.Session.send', side_effect=mocked_requests_send)
|
||||
def test_card_cell_table_mode_render(mock_send, context, app):
|
||||
page = Page.objects.create(title='xxx', template_name='standard')
|
||||
cell = WcsCardInfosCell.objects.create(
|
||||
page=page,
|
||||
placeholder='content',
|
||||
order=0,
|
||||
display_mode='table',
|
||||
carddef_reference='default:card_model_1',
|
||||
)
|
||||
|
||||
context['card_model_1_id'] = 11
|
||||
request = RequestFactory().get('/')
|
||||
context['synchronous'] = True # to get fresh content
|
||||
cell.modify_global_context(context, request)
|
||||
|
||||
result = cell.render(context)
|
||||
assert '<h2>Card Model 1</h2>' in result
|
||||
assert 'cards-card_model_1' in result
|
||||
assert (
|
||||
'<a href="http://127.0.0.1:8999/backoffice/data/card_model_1/11/"><span class="card-title">aa</span></a>'
|
||||
in result
|
||||
)
|
||||
assert (
|
||||
'<a href="http://127.0.0.1:8999/backoffice/data/card_model_1/12/"><span class="card-title">bb</span></a>'
|
||||
in result
|
||||
)
|
||||
assert (
|
||||
'<a href="http://127.0.0.1:8999/backoffice/data/card_model_1/13/"><span class="card-title">cc</span></a>'
|
||||
in result
|
||||
)
|
||||
assert 'data-paginate-by="10"' in result
|
||||
|
||||
# create a page with the correct subslug
|
||||
page = Page.objects.create(slug='foo', title='Foo', sub_slug='(?P<card_model_1_id>[a-z0-9]+)')
|
||||
|
||||
result = cell.render(context)
|
||||
assert '<h2>Card Model 1</h2>' in result
|
||||
assert '<a href="/foo/11"><span class="card-title">aa</span></a>' in result
|
||||
assert '<a href="/foo/12"><span class="card-title">bb</span></a>' in result
|
||||
assert '<a href="/foo/13"><span class="card-title">cc</span></a>' in result
|
||||
|
||||
cell.carddef_reference = 'default:card_model_1:foo'
|
||||
cell.limit = 42
|
||||
cell.save()
|
||||
page.sub_slug = 'card_model_1_id'
|
||||
page.save()
|
||||
|
||||
result = cell.render(context)
|
||||
assert '<h2>Card Model 1</h2>' in result
|
||||
assert '<a href="/foo/11"><span class="card-title">aa</span></a>' in result
|
||||
assert '<a href="/foo/12"><span class="card-title">bb</span></a>' in result
|
||||
assert '<a href="/foo/13"><span class="card-title">cc</span></a>' not in result
|
||||
assert 'data-paginate-by="42"' in result
|
||||
|
||||
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
|
||||
requests_get.return_value = MockedRequestResponse(content=json.dumps({'data': []}))
|
||||
cell.render(context)
|
||||
assert len(requests_get.call_args_list) == 1
|
||||
assert (
|
||||
requests_get.call_args_list[0][0][0]
|
||||
== '/api/cards/card_model_1/list/foo?full=on&filter-internal-id=11'
|
||||
)
|
||||
assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/'
|
||||
|
||||
|
||||
@mock.patch('requests.Session.send', side_effect=mocked_requests_send)
|
||||
def test_card_cell_table_mode_render_all_cards(mock_send, nocache, app):
|
||||
page = Page.objects.create(title='xxx', slug='foo', template_name='standard')
|
||||
cell = WcsCardInfosCell.objects.create(
|
||||
page=page,
|
||||
placeholder='content',
|
||||
order=0,
|
||||
display_mode='table',
|
||||
carddef_reference='default:card_model_1',
|
||||
related_card_path='__all__',
|
||||
)
|
||||
|
||||
cell_url = reverse(
|
||||
'combo-public-ajax-page-cell',
|
||||
kwargs={'page_pk': page.pk, 'cell_reference': cell.get_reference()},
|
||||
)
|
||||
|
||||
# check url called
|
||||
mock_send.reset_mock()
|
||||
resp = app.get(page.get_online_url())
|
||||
assert len(resp.context['cells']) == 1
|
||||
extra_ctx = re.findall(r'data-extra-context="(.*)"', resp.text)
|
||||
app.get(cell_url + '?ctx=' + extra_ctx[0])
|
||||
assert len(mock_send.call_args_list) == 1
|
||||
# cell rendering
|
||||
assert '/api/cards/card_model_1/list' in mock_send.call_args_list[0][0][0].url
|
||||
assert 'filter-internal-id' not in mock_send.call_args_list[0][0][0].url
|
||||
|
||||
|
||||
@mock.patch('requests.Session.send', side_effect=mocked_requests_send)
|
||||
def test_card_cell_table_mode_render_identifier(mock_send, nocache, app):
|
||||
page = Page.objects.create(
|
||||
title='xxx', slug='foo', template_name='standard', sub_slug='(?P<card_model_1_id>[a-z0-9]+)'
|
||||
)
|
||||
cell = WcsCardInfosCell.objects.create(
|
||||
page=page,
|
||||
placeholder='content',
|
||||
order=0,
|
||||
display_mode='table',
|
||||
carddef_reference='default:card_model_1',
|
||||
)
|
||||
|
||||
cell_url = reverse(
|
||||
'combo-public-ajax-page-cell',
|
||||
kwargs={'page_pk': page.pk, 'cell_reference': cell.get_reference()},
|
||||
)
|
||||
|
||||
# check url called
|
||||
mock_send.reset_mock()
|
||||
resp = app.get(page.get_online_url() + '11/')
|
||||
assert len(resp.context['cells']) == 1
|
||||
extra_ctx = re.findall(r'data-extra-context="(.*)"', resp.text)
|
||||
cell_resp = app.get(cell_url + '?ctx=' + extra_ctx[0])
|
||||
assert len(mock_send.call_args_list) == 1
|
||||
assert '/api/cards/card_model_1/list' in mock_send.call_args_list[0][0][0].url
|
||||
assert '&filter-internal-id=11&' in mock_send.call_args_list[0][0][0].url
|
||||
|
||||
# with identifiers
|
||||
page.sub_slug = ''
|
||||
page.save()
|
||||
cell.card_ids = '42'
|
||||
cell.save()
|
||||
mock_send.reset_mock()
|
||||
resp = app.get(page.get_online_url())
|
||||
assert len(resp.context['cells']) == 1
|
||||
extra_ctx = re.findall(r'data-extra-context="(.*)"', resp.text)
|
||||
cell_resp = app.get(cell_url + '?ctx=' + extra_ctx[0])
|
||||
assert len(mock_send.call_args_list) == 1
|
||||
assert '/api/cards/card_model_1/list' in mock_send.call_args_list[0][0][0].url
|
||||
assert '&filter-internal-id=42&' in mock_send.call_args_list[0][0][0].url
|
||||
|
||||
cell.card_ids = '42, , 35'
|
||||
cell.save()
|
||||
mock_send.reset_mock()
|
||||
resp = app.get(page.get_online_url())
|
||||
assert len(resp.context['cells']) == 1
|
||||
extra_ctx = re.findall(r'data-extra-context="(.*)"', resp.text)
|
||||
cell_resp = app.get(cell_url + '?ctx=' + extra_ctx[0])
|
||||
assert len(mock_send.call_args_list) == 1
|
||||
assert '/api/cards/card_model_1/list' in mock_send.call_args_list[0][0][0].url
|
||||
assert '&filter-internal-id=42&filter-internal-id=35&' in mock_send.call_args_list[0][0][0].url
|
||||
|
||||
cell.card_ids = '{% cards|objects:"card_model_1"|last|get:"id" %}' # syntax error
|
||||
cell.save()
|
||||
mock_send.reset_mock()
|
||||
resp = app.get(page.get_online_url())
|
||||
assert len(resp.context['cells']) == 1
|
||||
extra_ctx = re.findall(r'data-extra-context="(.*)"', resp.text)
|
||||
cell_resp = app.get(cell_url + '?ctx=' + extra_ctx[0])
|
||||
assert 'empty-message' in cell_resp
|
||||
|
||||
cell.card_ids = '{{ cards|objects:"card_model_1"|last|get:"id" }}'
|
||||
cell.save()
|
||||
mock_send.reset_mock()
|
||||
resp = app.get(page.get_online_url())
|
||||
assert len(resp.context['cells']) == 1
|
||||
extra_ctx = re.findall(r'data-extra-context="(.*)"', resp.text)
|
||||
cell_resp = app.get(cell_url + '?ctx=' + extra_ctx[0])
|
||||
assert len(mock_send.call_args_list) == 2
|
||||
# cell rendering
|
||||
assert '/api/cards/card_model_1/list' in mock_send.call_args_list[0][0][0].url
|
||||
assert '/api/cards/card_model_1/list' in mock_send.call_args_list[1][0][0].url
|
||||
assert '&filter-internal-id=13&' in mock_send.call_args_list[1][0][0].url
|
||||
|
||||
|
||||
@mock.patch('requests.Session.send', side_effect=mocked_requests_send)
|
||||
def test_card_cell_table_mode_render_identifier_from_related(mock_send, nocache, app):
|
||||
page = Page.objects.create(title='xxx', slug='foo', template_name='standard')
|
||||
WcsCardInfosCell.objects.create(
|
||||
page=page,
|
||||
placeholder='content',
|
||||
order=0,
|
||||
display_mode='table',
|
||||
slug='sluga',
|
||||
carddef_reference='default:card_a',
|
||||
card_ids='1',
|
||||
)
|
||||
cell2 = WcsCardInfosCell.objects.create(
|
||||
page=page, placeholder='content', order=1, slug='slugb', carddef_reference='default:card_b'
|
||||
)
|
||||
|
||||
cell2_url = reverse(
|
||||
'combo-public-ajax-page-cell',
|
||||
kwargs={'page_pk': page.pk, 'cell_reference': cell2.get_reference()},
|
||||
)
|
||||
|
||||
# just do a simple test to check url calls
|
||||
def check(urls):
|
||||
resp = app.get(page.get_online_url())
|
||||
assert len(resp.context['cells']) == 2
|
||||
extra_ctx = re.findall(r'data-extra-context="(.*)"', resp.text)
|
||||
mock_send.reset_mock()
|
||||
app.get(cell2_url + '?ctx=' + extra_ctx[1])
|
||||
assert len(mock_send.call_args_list) == len(urls)
|
||||
for j, url_parts in enumerate(urls):
|
||||
if not isinstance(url_parts, tuple):
|
||||
url_parts = (url_parts,)
|
||||
for url_part in url_parts:
|
||||
assert url_part in mock_send.call_args_list[j][0][0].url
|
||||
|
||||
# direct and single relation (item)
|
||||
cell2.related_card_path = 'sluga/cardb'
|
||||
cell2.save()
|
||||
urls = [
|
||||
# get first cell data
|
||||
'/api/cards/card_a/1/',
|
||||
# and follow cardb relation
|
||||
'/api/cards/card_b/1/', # get card
|
||||
]
|
||||
check(urls)
|
||||
|
||||
# direct and multiple relation (items)
|
||||
cell2.carddef_reference = 'default:card_b' # reset
|
||||
cell2.related_card_path = 'sluga/cardsb'
|
||||
cell2.save()
|
||||
urls = [
|
||||
# get first cell data
|
||||
'/api/cards/card_a/1/',
|
||||
# and follow cardb relation
|
||||
('/api/cards/card_b/list', '&filter-internal-id=2&filter-internal-id=3&'), # get cards
|
||||
]
|
||||
check(urls)
|
||||
|
||||
|
||||
@mock.patch('requests.Session.send', side_effect=mocked_requests_send)
|
||||
def test_card_cell_table_mode_render_title(mock_send, context):
|
||||
page = Page.objects.create(title='xxx', template_name='standard')
|
||||
cell = WcsCardInfosCell.objects.create(
|
||||
page=page,
|
||||
placeholder='content',
|
||||
order=0,
|
||||
display_mode='table',
|
||||
carddef_reference='default:card_model_1',
|
||||
title_type='auto',
|
||||
)
|
||||
|
||||
context['synchronous'] = True # to get fresh content
|
||||
|
||||
result = cell.render(context)
|
||||
assert '<h2>Card Model 1</h2>' in result
|
||||
|
||||
context.pop('title')
|
||||
cell.title_type = 'empty'
|
||||
cell.save()
|
||||
result = cell.render(context)
|
||||
assert '<h2>' not in result
|
||||
|
||||
cell.title_type = 'manual'
|
||||
cell.save()
|
||||
result = cell.render(context)
|
||||
assert '<h2>Card Model 1</h2>' in result
|
||||
|
||||
context.pop('title')
|
||||
cell.custom_title = 'Foo bar !'
|
||||
cell.save()
|
||||
result = cell.render(context)
|
||||
assert '<h2>Foo bar !</h2>' in result
|
||||
|
||||
|
||||
@mock.patch('requests.Session.send', side_effect=mocked_requests_send)
|
||||
def test_card_cell_card_mode_render(mock_send, context, app):
|
||||
page = Page.objects.create(title='xxx', template_name='standard')
|
||||
|
|
Loading…
Reference in New Issue