From 9f7f438a944faca36c71cba7b755763f9e1c134e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Thu, 2 Sep 2021 17:04:57 +0200
Subject: [PATCH] wcs: card cell title can be empty (#56584)

---
 combo/apps/wcs/forms.py                       |  2 +-
 .../wcs/migrations/0037_card_title_type.py    | 25 ++++++++++++++++
 .../wcs/migrations/0038_card_title_type.py    | 19 ++++++++++++
 combo/apps/wcs/models.py                      | 30 ++++++++++++++-----
 combo/apps/wcs/templates/combo/wcs/card.html  |  2 +-
 .../wcs/manager/card-infos-cell-form.html     | 12 ++++++++
 tests/test_wcs.py                             | 16 ++++++++--
 7 files changed, 94 insertions(+), 12 deletions(-)
 create mode 100644 combo/apps/wcs/migrations/0037_card_title_type.py
 create mode 100644 combo/apps/wcs/migrations/0038_card_title_type.py

diff --git a/combo/apps/wcs/forms.py b/combo/apps/wcs/forms.py
index aad9ae54..9cef5228 100644
--- a/combo/apps/wcs/forms.py
+++ b/combo/apps/wcs/forms.py
@@ -74,7 +74,7 @@ class WcsCardInfoCellForm(forms.ModelForm):
 
     class Meta:
         model = WcsCardInfosCell
-        fields = ('carddef_reference', 'custom_title', 'card_id', 'custom_schema')
+        fields = ('carddef_reference', 'title_type', 'custom_title', 'card_id', 'custom_schema')
         widgets = {
             'custom_schema': forms.HiddenInput(),
         }
diff --git a/combo/apps/wcs/migrations/0037_card_title_type.py b/combo/apps/wcs/migrations/0037_card_title_type.py
new file mode 100644
index 00000000..1e731356
--- /dev/null
+++ b/combo/apps/wcs/migrations/0037_card_title_type.py
@@ -0,0 +1,25 @@
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('wcs', '0036_remove_wcscurrentformscell_include_forms_user_can_access'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='wcscardinfoscell',
+            name='title_type',
+            field=models.CharField(
+                choices=[
+                    ('auto', 'Default Title (Card Label)'),
+                    ('manual', 'Custom Title'),
+                    ('empty', 'No Title'),
+                ],
+                default='auto',
+                max_length=20,
+                verbose_name='Title',
+            ),
+        ),
+    ]
diff --git a/combo/apps/wcs/migrations/0038_card_title_type.py b/combo/apps/wcs/migrations/0038_card_title_type.py
new file mode 100644
index 00000000..2641c34e
--- /dev/null
+++ b/combo/apps/wcs/migrations/0038_card_title_type.py
@@ -0,0 +1,19 @@
+from django.db import migrations
+
+
+def update_title_type(apps, schema_editor):
+    WcsCardInfosCell = apps.get_model('wcs', 'WcsCardInfosCell')
+    for cell in WcsCardInfosCell.objects.exclude(custom_title=''):
+        cell.title_type = 'manual'
+        cell.save()
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('wcs', '0037_card_title_type'),
+    ]
+
+    operations = [
+        migrations.RunPython(update_title_type, migrations.RunPython.noop),
+    ]
diff --git a/combo/apps/wcs/models.py b/combo/apps/wcs/models.py
index 8dcf4590..043e1fc4 100644
--- a/combo/apps/wcs/models.py
+++ b/combo/apps/wcs/models.py
@@ -911,8 +911,20 @@ class WcsCardInfosCell(CardMixin, CellBase):
     without_user = models.BooleanField(_('Ignore the logged-in user'), default=False)
     custom_schema = JSONField(blank=True, default=dict)
 
-    cached_title = models.CharField(_('Title'), max_length=150)
+    title_type = models.CharField(
+        _('Title'),
+        max_length=20,
+        default='auto',
+        blank=False,
+        choices=[
+            ('auto', _('Default Title (Card Label)')),
+            ('manual', _('Custom Title')),
+            ('empty', _('No Title')),
+        ],
+    )
     custom_title = models.CharField(_('Custom Title'), max_length=150, blank=True)
+
+    cached_title = models.CharField(_('Title'), max_length=150)
     cached_json = JSONField(blank=True, default=dict)
 
     is_enabled = classmethod(is_wcs_enabled)
@@ -982,7 +994,8 @@ class WcsCardInfosCell(CardMixin, CellBase):
         extra_context = super().get_cell_extra_context(context)
         extra_context['schema'] = self.cached_json
         # default value used if card is not found
-        extra_context['title'] = self.cached_title
+        if self.title_type in ['auto', 'manual']:
+            extra_context['title'] = self.cached_title
 
         card_id = self.get_card_id(context)
         if not card_id:
@@ -1008,12 +1021,13 @@ class WcsCardInfosCell(CardMixin, CellBase):
 
         if response.status_code == 200:
             extra_context['card'] = response.json()
-            try:
-                extra_context['title'] = Template(self.custom_title).render(Context(extra_context))
-            except (VariableDoesNotExist, TemplateSyntaxError):
-                extra_context['title'] = ''
-            # custom_title gives an empty title, use default value + card text
-            if not extra_context['title']:
+            if self.title_type == 'manual':
+                try:
+                    extra_context['title'] = Template(self.custom_title).render(Context(extra_context))
+                except (VariableDoesNotExist, TemplateSyntaxError):
+                    extra_context['title'] = ''
+            # auto title or custom_title gives an empty title, use default value + card text
+            if self.title_type == 'auto' or self.title_type == 'manual' and not extra_context['title']:
                 extra_context['title'] = '%s - %s' % (self.cached_title, extra_context['card'].get('text'))
 
         return extra_context
diff --git a/combo/apps/wcs/templates/combo/wcs/card.html b/combo/apps/wcs/templates/combo/wcs/card.html
index 05baefe0..428653ee 100644
--- a/combo/apps/wcs/templates/combo/wcs/card.html
+++ b/combo/apps/wcs/templates/combo/wcs/card.html
@@ -4,7 +4,7 @@
 
 <div class="card">
 {% block cell-header %}
-<h2>{{ title }}</h2>
+{% if title %}<h2>{{ title }}</h2>{% endif %}
 {% include "combo/asset_picture_fragment.html" %}
 {% endblock %}
 
diff --git a/combo/apps/wcs/templates/combo/wcs/manager/card-infos-cell-form.html b/combo/apps/wcs/templates/combo/wcs/manager/card-infos-cell-form.html
index 9492d5fb..adaeab53 100644
--- a/combo/apps/wcs/templates/combo/wcs/manager/card-infos-cell-form.html
+++ b/combo/apps/wcs/templates/combo/wcs/manager/card-infos-cell-form.html
@@ -80,4 +80,16 @@
 </script>
 
 {% endif %}
+
+{# display/hide custom_title field #}
+<script>
+  $('#id_cwcs_wcscardinfoscell-{{ cell.pk }}-title_type').on('change', function() {
+    if ($(this).val() == 'manual') {
+      $('#id_cwcs_wcscardinfoscell-{{ cell.pk }}-custom_title').parent().show();
+    } else {
+      $('#id_cwcs_wcscardinfoscell-{{ cell.pk }}-custom_title').parent().hide();
+    }
+  });
+  $('#id_cwcs_wcscardinfoscell-{{ cell.pk }}-title_type').change();
+</script>
 {% endblock %}
diff --git a/tests/test_wcs.py b/tests/test_wcs.py
index dc03af6a..7e998d5e 100644
--- a/tests/test_wcs.py
+++ b/tests/test_wcs.py
@@ -1755,6 +1755,7 @@ def test_card_cell_render(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.title_type = 'manual'
     cell.custom_title = 'Foo bar {{ card.fields.title }}'
     cell.save()
 
@@ -1786,11 +1787,12 @@ def test_card_cell_render(mock_send, context):
     assert '<h2>Card Model 1</h2>' in result  # default value
     assert '<p>Unknown Card</p>' in result
 
-    cell.custom_title = ''
+    context.pop('title')
+    cell.title_type = 'auto'
     cell.save()
     mock_send.reset_mock()
     result = cell.render(context)
-    assert '<h2>Card Model 1 - aa</h2>' in result  # custom_title not defined, default value
+    assert '<h2>Card Model 1 - aa</h2>' in result
     assert PyQuery(result).find('span.label:contains("Field A") + span').text() == 'a'
     assert PyQuery(result).find('span.label:contains("Field B") + span').text() == 'yes'
     assert PyQuery(result).find('span.label:contains("Field C") + span').text() == 'Sept. 28, 2020'
@@ -1799,21 +1801,31 @@ def test_card_cell_render(mock_send, context):
     assert 'related_structured' not in result
     assert 'Field D' not in result
 
+    context.pop('title')
+    cell.title_type = 'manual'
     cell.custom_title = 'Foo bar {{ card.fields.fielda }}'
     cell.save()
     result = cell.render(context)
     assert '<h2>Foo bar a</h2>' in result
 
+    context.pop('title')
     cell.custom_title = '{{ foobar }}'
     cell.save()
     result = cell.render(context)
     assert '<h2>Card Model 1 - aa</h2>' in result  # empty value from template, default value
 
+    context.pop('title')
     cell.custom_title = '{% if %}'
     cell.save()
     result = cell.render(context)
     assert '<h2>Card Model 1 - aa</h2>' in result  # template error, default value
 
+    context.pop('title')
+    cell.title_type = 'empty'
+    cell.save()
+    result = cell.render(context)
+    assert '<h2>' not in result
+
 
 @mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
 def test_card_cell_render_identifier(mock_send, context, nocache):
-- 
2.30.2

