From f5fbf254f80ad572f1c7a3960ca8b345236bf606 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Tue, 12 Jan 2021 10:15:11 +0100
Subject: [PATCH] wcs: add card identifier on Card Info cell (#50001)

---
 combo/apps/wcs/forms.py                       |  2 +-
 .../apps/wcs/migrations/0023_card_info_id.py  | 19 ++++++++++++++
 combo/apps/wcs/models.py                      | 24 +++++++++++++++---
 tests/test_wcs.py                             | 25 +++++++++++++++++++
 4 files changed, 65 insertions(+), 5 deletions(-)
 create mode 100644 combo/apps/wcs/migrations/0023_card_info_id.py

diff --git a/combo/apps/wcs/forms.py b/combo/apps/wcs/forms.py
index d20c9d58..25b03d49 100644
--- a/combo/apps/wcs/forms.py
+++ b/combo/apps/wcs/forms.py
@@ -51,7 +51,7 @@ class WcsCardsCellForm(forms.ModelForm):
 class WcsCardInfoCellForm(forms.ModelForm):
     class Meta:
         model = WcsCardInfosCell
-        fields = ('carddef_reference',)
+        fields = ('carddef_reference', 'card_id')
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
diff --git a/combo/apps/wcs/migrations/0023_card_info_id.py b/combo/apps/wcs/migrations/0023_card_info_id.py
new file mode 100644
index 00000000..146373a0
--- /dev/null
+++ b/combo/apps/wcs/migrations/0023_card_info_id.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('wcs', '0022_cards_user'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='wcscardinfoscell',
+            name='card_id',
+            field=models.CharField(blank=True, max_length=150, verbose_name='Card Identifier'),
+        ),
+    ]
diff --git a/combo/apps/wcs/models.py b/combo/apps/wcs/models.py
index ffe0a0ff..013fecb9 100644
--- a/combo/apps/wcs/models.py
+++ b/combo/apps/wcs/models.py
@@ -31,6 +31,7 @@ from requests.exceptions import RequestException
 
 from combo.data.models import CellBase, Page
 from combo.data.library import register_cell_class
+from combo import utils
 from combo.utils import requests
 
 from .utils import get_wcs_json, is_wcs_enabled, get_wcs_services
@@ -836,6 +837,7 @@ class WcsCardsCell(CardMixin, WcsBlurpMixin, CellBase):
 @register_cell_class
 class WcsCardInfosCell(CardMixin, CellBase):
     carddef_reference = models.CharField(_('Card Model'), max_length=150)
+    card_id = models.CharField(_('Card Identifier'), max_length=150, blank=True)
 
     cached_title = models.CharField(_('Title'), max_length=150)
     cached_json = JSONField(blank=True)
@@ -881,16 +883,30 @@ class WcsCardInfosCell(CardMixin, CellBase):
 
         populate_cache()
 
+    def get_card_id(self, context):
+        if self.card_id:
+            try:
+                card_id = utils.get_templated_url('{%% load wcs %%}%s' % self.card_id, context)
+            except utils.TemplateError:
+                return None
+            else:
+                if card_id:
+                    return card_id
+
+        card_slug = self.carddef_reference.split(':')[1]
+        card_id = '%s_id' % card_slug
+        return context.get(card_id) or None
+
     def get_cell_extra_context(self, context):
         extra_context = super().get_cell_extra_context(context)
         extra_context['title'] = self.cached_title
         extra_context['schema'] = self.cached_json
 
-        card_slug = self.carddef_reference.split(':')[1]
-        card_id = '%s_id' % card_slug
-        if not context.get(card_id):
+        card_id = self.get_card_id(context)
+        if not card_id:
             return extra_context
-        api_url = 'api/cards/%s/%s/' % (card_slug, context.get(card_id))
+        card_slug = self.carddef_reference.split(':')[1]
+        api_url = 'api/cards/%s/%s/' % (card_slug, card_id)
 
         wcs_site = get_wcs_services().get(self.wcs_site)
 
diff --git a/tests/test_wcs.py b/tests/test_wcs.py
index 26e10b08..4ba57432 100644
--- a/tests/test_wcs.py
+++ b/tests/test_wcs.py
@@ -27,6 +27,7 @@ from combo.apps.wcs.models import (
     WcsFormsOfCategoryCell, WcsCurrentDraftsCell, WcsCategoryCell,
     TrackingCodeInputCell, BackofficeSubmissionCell, WcsCareFormsCell,
     WcsCardsCell, WcsCardInfosCell)
+from combo.apps.wcs.context_processors import Cards
 
 from combo.apps.search.models import SearchCell
 from combo.apps.search.utils import index_site, search_site
@@ -1372,6 +1373,7 @@ def test_card_cell_render(mock_send, context):
         result = cell.render(context)
     assert '<p>Unknown Card</p>' in result
 
+    mock_send.reset_mock()
     result = cell.render(context)
     assert '<h2>Card Model 1 - aa</h2>' in result
     assert '<span class="label">Field A</span>\n    \n    <span class="value">a</span>' in result
@@ -1381,6 +1383,29 @@ def test_card_cell_render(mock_send, context):
     assert 'related_raw' not in result
     assert 'related_structured' not in result
 
+    # check url called
+    assert '/api/cards/card_model_1/11/' in mock_send.call_args_list[0][0][0].url
+
+    # with identifier
+    cell.card_id = '42'
+    cell.save()
+    mock_send.reset_mock()
+    result = cell.render(context)
+    assert '/api/cards/card_model_1/42/' in mock_send.call_args_list[0][0][0].url
+
+    context['cards'] = Cards()
+    cell.card_id = '{% cards|objects:"card_model_1"|last|get:"id" %}'  # syntax error
+    cell.save()
+    mock_send.reset_mock()
+    result = cell.render(context)
+    assert mock_send.call_args_list == []
+
+    cell.card_id = '{{ cards|objects:"card_model_1"|last|get:"id" }}'
+    cell.save()
+    result = cell.render(context)
+    assert '/api/cards/card_model_1/list' in mock_send.call_args_list[0][0][0].url
+    assert '/api/cards/card_model_1/13/' in mock_send.call_args_list[1][0][0].url
+
 
 def test_tracking_code_cell(app, nocache):
     page = Page(title='One', slug='index', template_name='standard')
-- 
2.29.2

