From fde2cbce0eb0fb415c32c0e5ca9e436bd2356689 Mon Sep 17 00:00:00 2001
From: Serghei Mihai <smihai@entrouvert.com>
Date: Thu, 7 May 2020 15:06:33 +0200
Subject: [PATCH] widgets: use "date" input for dates (#41605)

---
 src/authentic2/attribute_kinds.py |  3 +++
 src/authentic2/forms/widgets.py   | 34 ++++++++++++++++++++++++++++---
 2 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/src/authentic2/attribute_kinds.py b/src/authentic2/attribute_kinds.py
index b35320c3..a1b126ec 100644
--- a/src/authentic2/attribute_kinds.py
+++ b/src/authentic2/attribute_kinds.py
@@ -82,9 +82,12 @@ class DateRestField(serializers.DateField):
 
 class BirthdateWidget(DateWidget):
     def __init__(self, *args, **kwargs):
+        attrs = kwargs.setdefault('attrs', {})
         options = kwargs.setdefault('options', {})
         options['endDate'] = '-1d'
         options['startDate'] = '1900-01-01'
+        attrs['min'] = '1900-01-01'
+        attrs['max'] = (datetime.date.today() - datetime.timedelta(days=1)).isoformat()
         super(BirthdateWidget, self).__init__(*args, **kwargs)
 
 
diff --git a/src/authentic2/forms/widgets.py b/src/authentic2/forms/widgets.py
index 99c64d5e..56da8784 100644
--- a/src/authentic2/forms/widgets.py
+++ b/src/authentic2/forms/widgets.py
@@ -26,6 +26,7 @@
 import json
 import re
 import uuid
+import datetime
 
 import django
 from django.forms.widgets import DateTimeInput, DateInput, TimeInput, ClearableFileInput
@@ -34,6 +35,7 @@ from django.forms.widgets import TextInput
 from django.utils.formats import get_language, get_format
 from django.utils.safestring import mark_safe
 from django.utils.translation import ugettext_lazy as _
+from django.utils.encoding import force_text
 
 from gadjo.templatetags.gadjo import xstatic
 
@@ -79,6 +81,22 @@ BOOTSTRAP_INPUT_TEMPLATE = """
        </script>
        """
 
+BOOTSTRAP_DATE_INPUT_TEMPLATE = """
+      %(rendered_widget)s
+      %(clear_button)s
+      <span class="add-on"><i class="icon-th"></i></span>
+      <span class="%(id)s helptext">%(help_text)s</span>
+       <script type="text/javascript">
+           if ($("#%(id)s").attr('type') != "date") {
+               $("#%(id)s").datetimepicker({%(options)s});
+               var date = new Date($("#%(id)s").val());
+               $("#%(id)s").val(date.toLocaleDateString('%(language)s'));
+           } else {
+               $(".%(id)s.helptext").hide();
+           }
+       </script>
+       """
+
 CLEAR_BTN_TEMPLATE = """<span class="add-on"><i class="icon-remove"></i></span>"""
 
 
@@ -98,6 +116,8 @@ class PickerWidgetMixin(object):
     glyphicon = None
     help_text = None
 
+    render_template = BOOTSTRAP_INPUT_TEMPLATE
+
     def __init__(self, attrs=None, options=None, usel10n=None):
 
         if attrs is None:
@@ -145,11 +165,12 @@ class PickerWidgetMixin(object):
         if not help_text:
             help_text = u'%s %s' % (_('Format:'), self.options['format'])
 
-        return mark_safe(BOOTSTRAP_INPUT_TEMPLATE % dict(
+        return mark_safe(self.render_template % dict(
             id=id,
             rendered_widget=rendered_widget,
             clear_button=CLEAR_BTN_TEMPLATE if self.options.get('clearBtn') else '',
             glyphicon=self.glyphicon,
+            language=get_language(),
             options=js_options,
             help_text=help_text))
 
@@ -179,9 +200,10 @@ class DateWidget(PickerWidgetMixin, DateInput):
     DateWidget is the corresponding widget for Date field, it renders only the date section of
     datetime picker.
     """
-
     format_name = 'DATE_INPUT_FORMATS'
     glyphicon = 'glyphicon-calendar'
+    input_type = 'date'
+    render_template = BOOTSTRAP_DATE_INPUT_TEMPLATE
 
     def __init__(self, attrs=None, options=None, usel10n=None):
 
@@ -191,10 +213,16 @@ class DateWidget(PickerWidgetMixin, DateInput):
         # Set the default options to show only the datepicker object
         options['startView'] = options.get('startView', 2)
         options['minView'] = options.get('minView', 2)
-        options['format'] = options.get('format', self.get_format())
 
+        options['format'] = options.get('format', self.get_format())
         super(DateWidget, self).__init__(attrs, options, usel10n)
 
+    def format_value(self, value):
+        if value is not None:
+            if isinstance(value, datetime.datetime):
+                return force_text(value.isoformat())
+            return value
+
 
 class TimeWidget(PickerWidgetMixin, TimeInput):
     """
-- 
2.26.2

