From 65b1919f9fbec7dfc46bdc8cd37cabac2fae117d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpeters@entrouvert.com>
Date: Tue, 7 Sep 2021 14:56:15 +0200
Subject: [PATCH] wcs: format text fields content like wcs (#56422)

---
 .../templates/combo/wcs/card-field-value.html |  8 ++++-
 combo/apps/wcs/templates/combo/wcs/card.html  | 12 +++----
 combo/apps/wcs/templatetags/wcs.py            |  9 +++++
 tests/test_wcs.py                             | 34 +++++++++++++++++++
 4 files changed, 55 insertions(+), 8 deletions(-)

diff --git a/combo/apps/wcs/templates/combo/wcs/card-field-value.html b/combo/apps/wcs/templates/combo/wcs/card-field-value.html
index 64632790..7c446c80 100644
--- a/combo/apps/wcs/templates/combo/wcs/card-field-value.html
+++ b/combo/apps/wcs/templates/combo/wcs/card-field-value.html
@@ -1,4 +1,8 @@
-{% spaceless %}
+{% load wcs %}{% spaceless %}
+{% if field.type == "text" and mode != 'inline' and value %}
+<div class="value">{{ field|format_text:value }}</div>
+{% else %}
+{% if not mode == 'inline' %}<span class="value">{% endif %}
 {% if field.type == "date" %}
   {{ value|date }}
 {% elif field.type == "bool" and value is not None %}
@@ -6,4 +10,6 @@
 {% else %}
   {{ value|default:"" }}
 {% endif %}
+{% if not mode == 'inline' %}</span>{% endif %}
+{% endif %}
 {% endspaceless %}
diff --git a/combo/apps/wcs/templates/combo/wcs/card.html b/combo/apps/wcs/templates/combo/wcs/card.html
index 6ad4ee9c..e433c54e 100644
--- a/combo/apps/wcs/templates/combo/wcs/card.html
+++ b/combo/apps/wcs/templates/combo/wcs/card.html
@@ -18,15 +18,13 @@
           {% if field.varname == item.varname %}
           {% with card.fields|get:item.varname as value %}
             {% if item.display_mode == "title" %}
-              <h3>{% include "combo/wcs/card-field-value.html" %}</h3>
+              <h3>{% include "combo/wcs/card-field-value.html" with mode="inline" %}</h3>
             {% endif %}
             {% if item.display_mode == "label" or item.display_mode == "label-and-value" %}
               <p class="label">{{ field.label }}</p>
             {% endif %}
             {% if item.display_mode == "value" or item.display_mode == "label-and-value" %}
-              <p class="value">
-                {% include "combo/wcs/card-field-value.html" %}
-              </p>
+              {% include "combo/wcs/card-field-value.html" %}
             {% endif %}
           {% endwith %}
           {% endif %}
@@ -39,10 +37,10 @@
 {% for field in schema.fields %}
   {% if 'varname' in field and field.varname and field.type != 'file' %}
   {% with card.fields|get:field.varname as value %}
-  <p>
+  <div class="card--auto-field">
     <span class="label">{{ field.label }}</span>
-    <span class="value">{% include "combo/wcs/card-field-value.html" %}</span>
-  </p>
+    {% include "combo/wcs/card-field-value.html" %}
+  </div>
   {% endwith %}
   {% endif %}
 {% endfor %}
diff --git a/combo/apps/wcs/templatetags/wcs.py b/combo/apps/wcs/templatetags/wcs.py
index 4b4b1e46..a7eb7700 100644
--- a/combo/apps/wcs/templatetags/wcs.py
+++ b/combo/apps/wcs/templatetags/wcs.py
@@ -15,6 +15,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 from django import template
+from django.utils.html import escape
+from django.utils.safestring import mark_safe
 
 register = template.Library()
 
@@ -62,3 +64,10 @@ def filter_by_user(queryset, user):
 @register.filter
 def filter_by_status(queryset, status):
     return queryset.filter_by_status(status)
+
+
+@register.filter
+def format_text(field, value):
+    if field.get('pre'):
+        return mark_safe('<pre>%s</pre>' % escape(value))
+    return mark_safe('<p>' + '\n'.join([(escape(x) or '</p><p>') for x in value.splitlines()]) + '</p>')
diff --git a/tests/test_wcs.py b/tests/test_wcs.py
index dc03af6a..be492d86 100644
--- a/tests/test_wcs.py
+++ b/tests/test_wcs.py
@@ -182,6 +182,8 @@ WCS_CARDDEF_SCHEMA = {
         {'label': 'Field B', 'varname': 'fieldb', 'type': 'bool'},
         {'label': 'Field C', 'varname': 'fieldc', 'type': 'date'},
         {'label': 'Field D', 'varname': 'fieldd', 'type': 'file'},
+        {'label': 'Field E', 'varname': 'fielde', 'type': 'text'},
+        {'label': 'Field F', 'varname': 'fieldf', 'type': 'text', 'pre': True},
         {'label': 'Related', 'varname': 'related', 'type': 'item'},
         {'label': 'Page', 'type': 'page'},
         {'label': 'Comment', 'type': 'comment'},
@@ -203,6 +205,8 @@ WCS_CARD_DATA = {
         'fieldb': True,
         'fieldc': '2020-09-28',
         'fieldd': {'filename': 'file.pdf', 'url': 'http://some-url.com/download?f=42'},
+        'fielde': 'lorem<strong>ipsum\n\nhello world',
+        'fieldf': 'lorem<strong>ipsum\n\nhello world',
         'related': 'Foo Bar',
         'related_raw': 42,
         'related_structured': {'id': 42, 'text': 'blah'},
@@ -1815,6 +1819,36 @@ def test_card_cell_render(mock_send, context):
     assert '<h2>Card Model 1 - aa</h2>' in result  # template error, default value
 
 
+@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
+def test_card_cell_render_text_field(mock_send, context):
+    page = Page.objects.create(title='xxx', template_name='standard')
+    cell = WcsCardInfosCell(page=page, placeholder='content', order=0)
+    cell.carddef_reference = 'default:card_model_1'
+    cell.custom_title = 'Foo bar {{ card.fields.title }}'
+    cell.save()
+
+    context['card_model_1_id'] = 11
+    context['synchronous'] = True  # to get fresh content
+
+    result = cell.render(context)
+
+    # field E is split in paragraphs
+    assert (
+        PyQuery(result).find('span.label:contains("Field E") + div.value p:first-child').text().strip()
+        == 'lorem<strong>ipsum'
+    )
+    assert (
+        PyQuery(result).find('span.label:contains("Field E") + div.value p:last-child').text().strip()
+        == 'hello world'
+    )
+
+    # field F is put in a <pre>
+    assert (
+        PyQuery(result).find('span.label:contains("Field F") + div.value pre').text()
+        == 'lorem<strong>ipsum hello world'
+    )
+
+
 @mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
 def test_card_cell_render_identifier(mock_send, context, nocache):
     page = Page.objects.create(title='xxx', template_name='standard')
-- 
2.33.0

