From 0c78d2d75c74d4f3c60e55d862974d9b3783cf16 Mon Sep 17 00:00:00 2001
From: Nicolas ROCHE <nroche@entrouvert.com>
Date: Wed, 8 Apr 2020 18:30:28 +0200
Subject: [PATCH] search: add a placeholder attribute to search input cell
 (#40993)

---
 combo/apps/search/forms.py                    |  2 +-
 .../0008_searchcell_input_placeholder.py      | 20 +++++++++++++++++++
 combo/apps/search/models.py                   |  1 +
 .../search/templates/combo/search-cell.html   |  2 +-
 tests/test_search.py                          |  6 ++++++
 5 files changed, 29 insertions(+), 2 deletions(-)
 create mode 100644 combo/apps/search/migrations/0008_searchcell_input_placeholder.py

diff --git a/combo/apps/search/forms.py b/combo/apps/search/forms.py
index 55b49974..2664dbf0 100644
--- a/combo/apps/search/forms.py
+++ b/combo/apps/search/forms.py
@@ -20,15 +20,15 @@ from combo.utils.forms import MultiSortWidget
 
 from . import engines
 from .models import SearchCell
 
 
 class SearchCellForm(forms.ModelForm):
     class Meta:
         model = SearchCell
-        fields = ('_search_services', 'autofocus')
+        fields = ('_search_services', 'autofocus', 'input_placeholder')
 
     def __init__(self, *args, **kwargs):
         super(SearchCellForm, self).__init__(*args, **kwargs)
         options = [(x, engines.get_engines()[x]['label']) for x in engines.get_engines().keys()]
         self.fields['_search_services'].widget = MultiSortWidget(choices=options,
                                                                  with_checkboxes=True)
diff --git a/combo/apps/search/migrations/0008_searchcell_input_placeholder.py b/combo/apps/search/migrations/0008_searchcell_input_placeholder.py
new file mode 100644
index 00000000..f03aca13
--- /dev/null
+++ b/combo/apps/search/migrations/0008_searchcell_input_placeholder.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.18 on 2020-04-08 17:22
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('search', '0007_french_fts'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='searchcell',
+            name='input_placeholder',
+            field=models.CharField(blank=True, default='', max_length=64, verbose_name='Placeholder'),
+        ),
+    ]
diff --git a/combo/apps/search/models.py b/combo/apps/search/models.py
index fb218167..3af855f7 100644
--- a/combo/apps/search/models.py
+++ b/combo/apps/search/models.py
@@ -39,16 +39,17 @@ from . import engines
 
 @register_cell_class
 class SearchCell(CellBase):
     template_name = 'combo/search-cell.html'
     manager_form_template = 'combo/manager/search-cell-form.html'
 
     _search_services = JSONField(_('Search Services'), default=dict, blank=True)
     autofocus = models.BooleanField(_('Autofocus'), default=False)
+    input_placeholder = models.CharField(_('Placeholder'), max_length=64, default="", blank=True)
 
     class Meta:
         verbose_name = _('Search')
 
     def is_visible(self, **kwargs):
         if not self.search_services:
             return False
         return super(SearchCell, self).is_visible(**kwargs)
diff --git a/combo/apps/search/templates/combo/search-cell.html b/combo/apps/search/templates/combo/search-cell.html
index 43ef9e96..ddf08298 100644
--- a/combo/apps/search/templates/combo/search-cell.html
+++ b/combo/apps/search/templates/combo/search-cell.html
@@ -1,14 +1,14 @@
 {% load i18n %}
 {% block cell-content %}
 
 {% block search-form %}
 <form id="combo-search-form-{{ cell.pk }}" class="combo-search-form">
-  <input type="search" name="q" autocomplete="off" id="combo-search-input-{{ cell.pk }}" class="combo-search-input" {% if cell.autofocus %}autofocus {% endif %}/>
+  <input type="search" name="q" autocomplete="off" id="combo-search-input-{{ cell.pk }}" class="combo-search-input" {% if cell.autofocus %}autofocus {% endif %}{% if cell.input_placeholder %}placeholder="{{ cell.input_placeholder }}" {% endif %}/>
   <button class="submit-button" aria-label="{% trans 'Search' %}">{% block submit-content %}{% trans 'Search' %}{% endblock %}</button>
 </form>
 {% endblock %}
 
 {% block search-results %}
 {% for search_service in cell.search_services %}
 <div id="combo-search-results-{{ cell.pk }}-{{ forloop.counter }}" class="combo-search-results combo-search-results-{{ search_service.slug }}"></div>
 {% endfor %}
diff --git a/tests/test_search.py b/tests/test_search.py
index fe251b69..324ddcac 100644
--- a/tests/test_search.py
+++ b/tests/test_search.py
@@ -56,22 +56,24 @@ class SearchServices(object):
 
 def test_search_cell(app):
     with SearchServices(SEARCH_SERVICES):
         page = Page(title='Search', slug='search_page', template_name='standard')
         page.save()
 
         cell = SearchCell(page=page, placeholder='content', order=0)
         cell._search_services = {'data': ['search1']}
+        cell.input_placeholder = 'my placeholder'
         cell.save()
 
         resp = cell.render({})
         assert 'input' in resp
         assert 'id="combo-search-input-%s"' % cell.pk in resp
         assert 'autofocus' not in resp
+        assert 'placeholder="my placeholder"' in resp
 
         cell.autofocus = True
         cell.save()
         resp = cell.render({})
         assert 'autofocus' in resp
 
         cell.slug = 'var-name'
         context = {'request': RequestFactory().get('/?q_var_name=searchme')}
@@ -370,25 +372,29 @@ def test_manager_search_cell(app, admin_user):
             assert len(resp.form['c%s-_search_services' % cells[0].get_reference()].options) == 4
             # simulate reordering of options
             resp.form['c%s-_search_services' % cells[0].get_reference()].options = [
                     (u'search_tmpl', False, u'Search with template'),
                     (u'search_alternate_key', False, u'Search with alternate key'),
                     (u'_text', False, u'Page Contents'),
                     (u'search1', False, u'Search 1')]
             resp.form['c%s-_search_services' % cells[0].get_reference()].value = ['search_tmpl', '_text']
+            resp.form['c%s-input_placeholder' % cells[0].get_reference()] = 'my placeholder'
             resp = resp.form.submit()
             assert resp.status_int == 302
 
             # check selected engines are selected and the first items of the list
             resp = app.get('/manage/pages/%s/' % page.id)
             assert set(resp.form['c%s-_search_services' % cells[0].get_reference()].value) == set(['search_tmpl', '_text'])
             assert resp.form['c%s-_search_services' % cells[0].get_reference()].options[0][0] == 'search_tmpl'
             assert resp.form['c%s-_search_services' % cells[0].get_reference()].options[1][0] == '_text'
 
+            # check placeholder
+            resp.form['c%s-input_placeholder' % cells[0].get_reference()] == 'my placeholder'
+
         # check there's no crash if search engines are removed from config
         resp = app.get('/manage/pages/%s/' % page.id)
         assert resp.form['c%s-_search_services' % cells[0].get_reference()].value == ['_text']
 
 
 def test_manager_waiting_index_message(app, admin_user):
     Page.objects.all().delete()
     page = Page(title='One', slug='one', template_name='standard')
-- 
2.25.1

