From 7a9696f93af20916da8b520fb554871f98a5246e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Fri, 12 Aug 2022 11:00:54 +0200
Subject: [PATCH 1/5] wcs: add new card cell model (#68140)

---
 .../apps/wcs/migrations/0051_new_card_cell.py | 108 ++++++++++++++++++
 combo/apps/wcs/models.py                      |  41 +++++++
 tests/test_manager.py                         |   8 +-
 tests/test_search.py                          |   2 +-
 4 files changed, 154 insertions(+), 5 deletions(-)
 create mode 100644 combo/apps/wcs/migrations/0051_new_card_cell.py

diff --git a/combo/apps/wcs/migrations/0051_new_card_cell.py b/combo/apps/wcs/migrations/0051_new_card_cell.py
new file mode 100644
index 00000000..0b7738df
--- /dev/null
+++ b/combo/apps/wcs/migrations/0051_new_card_cell.py
@@ -0,0 +1,108 @@
+import django.contrib.postgres.fields.jsonb
+import django.db.models.deletion
+from django.db import migrations, models
+
+import combo.apps.wcs.models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('auth', '0011_update_proxy_permissions'),
+        ('data', '0057_pagesnapshot_label'),
+        ('wcs', '0050_card_display_mode'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='WcsCardCell',
+            fields=[
+                (
+                    'id',
+                    models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+                ),
+                ('placeholder', models.CharField(max_length=20)),
+                ('order', models.PositiveIntegerField()),
+                ('slug', models.SlugField(blank=True, verbose_name='Slug')),
+                (
+                    'extra_css_class',
+                    models.CharField(
+                        blank=True, max_length=100, verbose_name='Extra classes for CSS styling'
+                    ),
+                ),
+                (
+                    'template_name',
+                    models.CharField(blank=True, max_length=50, null=True, verbose_name='Cell Template'),
+                ),
+                (
+                    'condition',
+                    models.CharField(
+                        blank=True, max_length=1000, null=True, verbose_name='Display condition'
+                    ),
+                ),
+                ('public', models.BooleanField(default=True, verbose_name='Public')),
+                (
+                    'restricted_to_unlogged',
+                    models.BooleanField(default=False, verbose_name='Restrict to unlogged users'),
+                ),
+                ('last_update_timestamp', models.DateTimeField(auto_now=True)),
+                ('carddef_reference', models.CharField(max_length=150, verbose_name='Card Model')),
+                (
+                    'related_card_path',
+                    models.CharField(blank=True, max_length=1000, verbose_name='Card Identifier'),
+                ),
+                (
+                    'card_ids',
+                    models.CharField(blank=True, max_length=1000, verbose_name='Other Card Identifiers'),
+                ),
+                (
+                    'only_for_user',
+                    models.BooleanField(
+                        default=False, verbose_name='Limit to cards linked to the logged-in user'
+                    ),
+                ),
+                (
+                    'without_user',
+                    models.BooleanField(default=False, verbose_name='Ignore the logged-in user'),
+                ),
+                (
+                    'limit',
+                    models.PositiveSmallIntegerField(
+                        blank=True, null=True, verbose_name='Number of cards per page (default 10)'
+                    ),
+                ),
+                ('custom_schema', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict)),
+                (
+                    'display_mode',
+                    models.CharField(
+                        choices=[('card', 'Card'), ('table', 'Table')],
+                        default='card',
+                        max_length=10,
+                        verbose_name='Display mode',
+                    ),
+                ),
+                (
+                    'title_type',
+                    models.CharField(
+                        choices=[
+                            ('auto', 'Default Title (Card Label)'),
+                            ('manual', 'Custom Title'),
+                            ('empty', 'No Title'),
+                        ],
+                        default='auto',
+                        max_length=20,
+                        verbose_name='Title',
+                    ),
+                ),
+                ('custom_title', models.CharField(blank=True, max_length=150, verbose_name='Custom Title')),
+                ('cached_title', models.CharField(max_length=150, verbose_name='Title')),
+                ('cached_json', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict)),
+                ('groups', models.ManyToManyField(blank=True, to='auth.Group', verbose_name='Groups')),
+                ('page', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='data.Page')),
+            ],
+            options={
+                'verbose_name': 'Card(s)',
+            },
+            bases=(combo.apps.wcs.models.CardMixin, models.Model),
+        ),
+    ]
diff --git a/combo/apps/wcs/models.py b/combo/apps/wcs/models.py
index 6ca75d28..7f26fca2 100644
--- a/combo/apps/wcs/models.py
+++ b/combo/apps/wcs/models.py
@@ -935,6 +935,47 @@ class WcsCardsCell(CardMixin, WcsBlurpMixin, CellBase):
         return ''
 
 
+@register_cell_class
+class WcsCardCell(CardMixin, CellBase):
+    carddef_reference = models.CharField(_('Card Model'), max_length=150)
+    related_card_path = models.CharField(_('Card Identifier'), max_length=1000, blank=True)
+    card_ids = models.CharField(_('Other Card Identifiers'), max_length=1000, blank=True)
+    only_for_user = models.BooleanField(_('Limit to cards linked to the logged-in user'), default=False)
+    without_user = models.BooleanField(_('Ignore the logged-in user'), default=False)
+    limit = models.PositiveSmallIntegerField(
+        _('Number of cards per page (default 10)'), null=True, blank=True
+    )
+    custom_schema = JSONField(blank=True, default=dict)
+    display_mode = models.CharField(
+        _('Display mode'),
+        max_length=10,
+        default='card',
+        choices=[
+            ('card', _('Card')),
+            ('table', _('Table')),
+        ],
+    )
+
+    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)
+
+    class Meta:
+        verbose_name = _('Card(s)')
+
+
 @register_cell_class
 class WcsCardInfosCell(CardMixin, CellBase):
     carddef_reference = models.CharField(_('Card Model'), max_length=150)
diff --git a/tests/test_manager.py b/tests/test_manager.py
index 7dc7f68b..d5ce7d50 100644
--- a/tests/test_manager.py
+++ b/tests/test_manager.py
@@ -1040,7 +1040,7 @@ def test_site_export_import_json(app, admin_user):
     resp.form['site_file'] = Upload('site-export.json', site_export, 'application/json')
     with CaptureQueriesContext(connection) as ctx:
         resp = resp.form.submit()
-        assert len(ctx.captured_queries) in [309, 310]
+        assert len(ctx.captured_queries) in [314, 315]
     assert Page.objects.count() == 4
     assert PageSnapshot.objects.all().count() == 4
 
@@ -1051,7 +1051,7 @@ def test_site_export_import_json(app, admin_user):
     resp.form['site_file'] = Upload('site-export.json', site_export, 'application/json')
     with CaptureQueriesContext(connection) as ctx:
         resp = resp.form.submit()
-        assert len(ctx.captured_queries) == 278
+        assert len(ctx.captured_queries) == 282
     assert set(Page.objects.get(slug='one').related_cells['cell_types']) == {'data_textcell', 'data_linkcell'}
     assert Page.objects.count() == 4
     assert LinkCell.objects.count() == 2
@@ -2447,7 +2447,7 @@ def test_page_versionning(app, admin_user):
 
     with CaptureQueriesContext(connection) as ctx:
         resp2 = resp.click('view', index=1)
-        assert len(ctx.captured_queries) == 71
+        assert len(ctx.captured_queries) == 72
     assert Page.snapshots.latest('pk').related_cells == {'cell_types': ['data_textcell']}
     assert resp2.text.index('Hello world') < resp2.text.index('Foobar3')
 
@@ -2508,7 +2508,7 @@ def test_page_versionning(app, admin_user):
     resp = resp.click('restore', index=6)
     with CaptureQueriesContext(connection) as ctx:
         resp = resp.form.submit().follow()
-        assert len(ctx.captured_queries) == 155
+        assert len(ctx.captured_queries) == 157
 
     resp2 = resp.click('See online')
     assert resp2.text.index('Foobar1') < resp2.text.index('Foobar2') < resp2.text.index('Foobar3')
diff --git a/tests/test_search.py b/tests/test_search.py
index 164cbcf9..bcd1cc5e 100644
--- a/tests/test_search.py
+++ b/tests/test_search.py
@@ -1432,7 +1432,7 @@ def test_index_site_num_queries(settings, app):
     assert IndexedCell.objects.count() == 50
     with CaptureQueriesContext(connection) as ctx:
         index_site()
-        assert len(ctx.captured_queries) in (175, 225)  # (3.2, 2.2)
+        assert len(ctx.captured_queries) in (176, 226)  # (3.2, 2.2)
 
     SearchCell.objects.create(
         page=page, placeholder='content', order=0, _search_services={'data': ['search1']}
-- 
2.35.1

