cells: json cell params (repeat, make_global, template_string) (#54236)
gitea-wip/combo/pipeline/head Build started... Details
gitea/combo/pipeline/head Build started... Details

This commit is contained in:
Frédéric Péters 2021-05-24 10:33:30 +02:00 committed by Lauréline Guérin
parent 6b2b381a54
commit 07a81ad81d
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
4 changed files with 209 additions and 3 deletions

View File

@ -1671,6 +1671,7 @@ class JsonCellBase(CellBase):
force_async = False
log_errors = True
timeout = None
make_global = False
actions = {}
additional_data = None
# [
@ -1827,6 +1828,16 @@ class JsonCellBase(CellBase):
return extra_context
def modify_global_context(self, context, request):
if self.make_global:
synchronous = context.get('synchronous')
context['synchronous'] = True
try:
preloaded_data = self.get_cell_extra_context(context)
context[self.make_global] = preloaded_data.get(self.first_data_key)
finally:
context['synchronous'] = synchronous
@property
def template_name(self):
json_content = self._json_content
@ -1979,6 +1990,14 @@ class ConfigJsonCell(JsonCellBase):
def ajax_refresh(self):
return settings.JSON_CELL_TYPES[self.key].get('auto_refresh', None)
@property
def make_global(self):
return settings.JSON_CELL_TYPES[self.key].get('make_global', False)
@property
def repeat(self):
return settings.JSON_CELL_TYPES[self.key].get('repeat')
@property
def url(self):
return settings.JSON_CELL_TYPES[self.key]['url']
@ -2035,6 +2054,11 @@ class ConfigJsonCell(JsonCellBase):
context['parameters'] = self.parameters
return context
def render(self, context):
if 'template_string' in self.parameters:
self.template_string = self.parameters['template_string']
return super().render(context)
@receiver(pre_save, sender=Page)
def create_redirects(sender, instance, raw, **kwargs):

View File

@ -10,7 +10,9 @@
data-ajax-cell-loading-message="{{ cell.loading_message }}"
data-ajax-cell-error-message="{% trans "Loading error" %}"
{% if cell.ajax_refresh %}data-ajax-cell-refresh="{{ cell.ajax_refresh }}"{% endif %}
{% if request.extra_context_data %}data-extra-context="{{ request.extra_context_data|signed|urlencode }}"{% endif %}
{% with cell|extra_context:request as extra_context %}
{% if extra_context %}data-extra-context="{{ extra_context|signed|urlencode }}"{% endif %}
{% endwith %}
><div>{% render_cell cell %}</div></div>
{% endfor %}
{% endif %}

View File

@ -16,6 +16,7 @@
from __future__ import absolute_import
import copy
import datetime
import json
import math
@ -39,7 +40,7 @@ try:
except ImportError:
from django.template.base import TOKEN_BLOCK, TOKEN_VAR, TOKEN_COMMENT
from django.template import defaultfilters
from django.template import Template, TemplateSyntaxError, defaultfilters
from django.template.defaultfilters import stringfilter
from django.utils import dateparse, six
from django.utils.encoding import force_text
@ -107,6 +108,28 @@ def placeholder(context, placeholder_name, **options):
context['skeleton'] = skeleton_text(context, placeholder_name)
else:
context['skeleton'] = ''
if not context.get('placeholder_search_mode'):
for cell in [x for x in context['cells'] if hasattr(x, 'repeat')]:
repeat_template = cell.repeat
if not repeat_template:
continue
try:
repeat = int(Template(repeat_template).render(context))
except (ValueError, TemplateSyntaxError, VariableDoesNotExist):
continue
cell_idx = context['cells'].index(cell)
context['cells'].remove(cell)
if repeat == 0:
continue
repeated_cells = []
for i in range(repeat):
new_cell = copy.copy(cell)
new_cell.repeat_index = i
repeated_cells.append(new_cell)
context['cells'][cell_idx:cell_idx] = repeated_cells
return context
@ -311,7 +334,10 @@ def get(obj, key):
try:
return obj.get(key)
except AttributeError:
return None
try:
return obj[key]
except (IndexError, KeyError, TypeError):
return None
@register.filter
@ -672,3 +698,11 @@ def phonenumber_fr(value, separator=' '):
# unknown
return value
@register.filter
def extra_context(cell, request):
ctx = copy.copy(getattr(request, 'extra_context_data', {}) or {})
if hasattr(cell, 'repeat_index'):
ctx['repeat_index'] = cell.repeat_index
return ctx

View File

@ -1,6 +1,7 @@
import datetime
import json
import os
import re
import mock
import pytest
@ -794,6 +795,151 @@ def test_config_json_cell_with_param_in_url(app):
assert requests_get.call_args[-1]['timeout'] == 42
def test_config_json_cell_with_template_string(settings, context):
settings.JSON_CELL_TYPES = {
'test-config-json-cell': {
'name': 'Foobar',
'url': 'http://foo',
'form': [
{"varname": "identifier", "type": "string", "label": "Identifier"},
{"varname": "template_string", "type": "text", "label": "Template"},
],
},
}
page = Page.objects.create(title='example page', slug='example-page')
cell = ConfigJsonCell.objects.create(
page=page,
placeholder='content',
order=1,
key='test-config-json-cell',
parameters={'identifier': 'plop', 'template_string': 'Foo Bar {{ identifier }}'},
)
with mock.patch('combo.utils.requests.get') as requests_get:
data = {'data': []}
requests_get.return_value = mock_json_response(content=json.dumps(data), status_code=200)
assert cell.render({}) == 'Foo Bar plop'
def test_config_json_cell_with_global(settings, app):
settings.JSON_CELL_TYPES = {
'test-config-json-cell': {
'name': 'Foobar',
'url': 'http://foo',
'make_global': 'new_global_context',
'form': [
{"varname": "template_string", "type": "text", "label": "Template"},
],
},
'test-config-json-cell-2': {
'name': 'Foobar 2',
'url': 'http://foo',
'form': [
{"varname": "template_string", "type": "text", "label": "Template"},
],
},
}
page = Page.objects.create(title='example page', slug='example-page')
cell1 = ConfigJsonCell.objects.create(
page=page,
placeholder='content',
order=1,
key='test-config-json-cell',
parameters={'template_string': 'Foo Bar'},
)
cell2 = ConfigJsonCell.objects.create(
page=page,
placeholder='content',
order=2,
key='test-config-json-cell-2',
parameters={'template_string': 'Foo Bar'},
)
with mock.patch('combo.utils.requests.get') as requests_get:
data = {'data': []}
requests_get.return_value = mock_json_response(content=json.dumps(data), status_code=200)
url = reverse(
'combo-public-ajax-page-cell',
kwargs={'page_pk': page.pk, 'cell_reference': cell1.get_reference()},
)
resp = app.get(url)
assert resp.context['new_global_context'] == data
url = reverse(
'combo-public-ajax-page-cell',
kwargs={'page_pk': page.pk, 'cell_reference': cell2.get_reference()},
)
resp = app.get(url)
assert resp.context['new_global_context'] == data
def test_config_json_cell_with_repeat(settings, app):
settings.JSON_CELL_TYPES = {
'test-config-json-cell': {
'name': 'Foobar',
'url': 'http://foo',
'form': [
{"varname": "template_string", "type": "text", "label": "Template"},
],
},
'test-config-json-cell-2': {
'name': 'Foobar 2',
'url': 'http://foo',
'repeat': '3',
'form': [
{"varname": "template_string", "type": "text", "label": "Template"},
],
},
}
page = Page.objects.create(title='example page', slug='example-page')
cell1 = ConfigJsonCell.objects.create(
page=page,
placeholder='content',
order=1,
key='test-config-json-cell',
parameters={'template_string': 'Foo Bar'},
)
cell2 = ConfigJsonCell.objects.create(
page=page,
placeholder='content',
order=2,
key='test-config-json-cell-2',
parameters={'template_string': 'Foo Bar {{ repeat_index }}'},
)
with mock.patch('combo.utils.requests.get') as requests_get:
data = {'data': []}
requests_get.return_value = mock_json_response(content=json.dumps(data), status_code=200)
resp = app.get(page.get_online_url())
assert len(resp.context['cells']) == 4
assert resp.context['cells'][0].pk == cell1.pk
extra_ctx = re.findall(r'data-extra-context="(.*)"', resp.text)
cell_url = reverse(
'combo-public-ajax-page-cell',
kwargs={'page_pk': page.pk, 'cell_reference': cell2.get_reference()},
)
for i in range(0, 3):
assert resp.context['cells'][i + 1].pk == cell2.pk
assert resp.context['cells'][i + 1].repeat_index == i
cell_resp = app.get(cell_url + '?ctx=' + extra_ctx[i + 1])
assert cell_resp.context['repeat_index'] == i
assert cell_resp.text == 'Foo Bar %s' % i
# repeat: not an int
settings.JSON_CELL_TYPES['test-config-json-cell-2']['repeat'] = 'foo'
with mock.patch('combo.utils.requests.get') as requests_get:
data = {'data': []}
requests_get.return_value = mock_json_response(content=json.dumps(data), status_code=200)
resp = app.get(page.get_online_url())
assert len(resp.context['cells']) == 2
# repeat: template error
settings.JSON_CELL_TYPES['test-config-json-cell-2']['repeat'] = '{% foo %}'
with mock.patch('combo.utils.requests.get') as requests_get:
data = {'data': []}
requests_get.return_value = mock_json_response(content=json.dumps(data), status_code=200)
resp = app.get(page.get_online_url())
assert len(resp.context['cells']) == 2
def test_config_json_cell_validity(settings, context):
settings.JSON_CELL_TYPES = {
'test-config-json-cell': {