mirror of
https://github.com/eitchtee/WYGIWYH.git
synced 2026-04-22 16:48:36 +02:00
feat(app): allow changing date and datetime format as a user setting
This commit is contained in:
@@ -4,7 +4,11 @@ from django.forms import widgets
|
||||
from django.utils import formats, translation, dates
|
||||
from django.utils.formats import get_format
|
||||
|
||||
from apps.common.utils.django import django_to_python_datetime
|
||||
from apps.common.utils.django import (
|
||||
django_to_python_datetime,
|
||||
django_to_airdatepicker_datetime,
|
||||
django_to_airdatepicker_datetime_separated,
|
||||
)
|
||||
|
||||
|
||||
class AirDatePickerInput(widgets.DateInput):
|
||||
@@ -14,104 +18,56 @@ class AirDatePickerInput(widgets.DateInput):
|
||||
format=None,
|
||||
clear_button=True,
|
||||
auto_close=True,
|
||||
user=None,
|
||||
*args,
|
||||
**kwargs,
|
||||
):
|
||||
attrs = attrs or {}
|
||||
|
||||
self.user = user
|
||||
super().__init__(attrs=attrs, format=format, *args, **kwargs)
|
||||
|
||||
self.clear_button = clear_button
|
||||
self.auto_close = auto_close
|
||||
|
||||
def _get_current_language(self):
|
||||
@staticmethod
|
||||
def _get_current_language():
|
||||
"""Get current language code in format compatible with AirDatepicker"""
|
||||
lang_code = translation.get_language()
|
||||
# AirDatepicker uses simple language codes
|
||||
return lang_code.split("-")[0]
|
||||
|
||||
def _get_format(self):
|
||||
"""Get the format string based on user settings or default"""
|
||||
if self.format:
|
||||
return self.format
|
||||
|
||||
if self.user and hasattr(self.user, "settings"):
|
||||
user_format = self.user.settings.date_format
|
||||
print(user_format)
|
||||
if user_format == "SHORT_DATE_FORMAT":
|
||||
return get_format("SHORT_DATE_FORMAT", use_l10n=True)
|
||||
return user_format
|
||||
|
||||
return get_format("SHORT_DATE_FORMAT", use_l10n=True)
|
||||
|
||||
def build_attrs(self, base_attrs, extra_attrs=None):
|
||||
attrs = super().build_attrs(base_attrs, extra_attrs)
|
||||
|
||||
# Add data attributes for AirDatepicker configuration
|
||||
attrs["data-auto-close"] = str(self.auto_close).lower()
|
||||
attrs["data-clear-button"] = str(self.clear_button).lower()
|
||||
attrs["data-language"] = self._get_current_language()
|
||||
attrs["data-date-format"] = self.format or get_format(
|
||||
"SHORT_DATE_FORMAT", use_l10n=True
|
||||
)
|
||||
attrs["data-date-format"] = django_to_airdatepicker_datetime(self._get_format())
|
||||
|
||||
return attrs
|
||||
|
||||
def format_value(self, value):
|
||||
"""Format the value for display in the widget."""
|
||||
if value:
|
||||
self.attrs["data-value"] = (
|
||||
value # We use this to dynamically select the initial date on AirDatePicker
|
||||
)
|
||||
self.attrs["data-value"] = value
|
||||
|
||||
if value is None:
|
||||
return ""
|
||||
if isinstance(value, (datetime.date, datetime.datetime)):
|
||||
return formats.date_format(
|
||||
value, format=self.format or "SHORT_DATE_FORMAT", use_l10n=True
|
||||
)
|
||||
|
||||
return str(value)
|
||||
|
||||
|
||||
class AirDateTimePickerInput(widgets.DateTimeInput):
|
||||
def __init__(
|
||||
self,
|
||||
attrs=None,
|
||||
format=None,
|
||||
timepicker=True,
|
||||
clear_button=True,
|
||||
auto_close=True,
|
||||
*args,
|
||||
**kwargs,
|
||||
):
|
||||
attrs = attrs or {}
|
||||
|
||||
super().__init__(attrs=attrs, format=format, *args, **kwargs)
|
||||
|
||||
self.timepicker = timepicker
|
||||
self.clear_button = clear_button
|
||||
self.auto_close = auto_close
|
||||
|
||||
def _get_current_language(self):
|
||||
"""Get current language code in format compatible with AirDatepicker"""
|
||||
lang_code = translation.get_language()
|
||||
# AirDatepicker uses simple language codes
|
||||
return lang_code.split("-")[0]
|
||||
|
||||
def build_attrs(self, base_attrs, extra_attrs=None):
|
||||
attrs = super().build_attrs(base_attrs, extra_attrs)
|
||||
|
||||
# Add data attributes for AirDatepicker configuration
|
||||
attrs["data-timepicker"] = str(self.timepicker).lower()
|
||||
attrs["data-auto-close"] = str(self.auto_close).lower()
|
||||
attrs["data-clear-button"] = str(self.clear_button).lower()
|
||||
attrs["data-language"] = self._get_current_language()
|
||||
attrs["data-date-format"] = self.format or get_format(
|
||||
"SHORT_DATETIME_FORMAT", use_l10n=True
|
||||
)
|
||||
|
||||
return attrs
|
||||
|
||||
def format_value(self, value):
|
||||
"""Format the value for display in the widget."""
|
||||
if value:
|
||||
self.attrs["data-value"] = (
|
||||
value # We use this to dynamically select the initial date on AirDatePicker
|
||||
)
|
||||
|
||||
if value is None:
|
||||
return ""
|
||||
if isinstance(value, (datetime.date, datetime.datetime)):
|
||||
return formats.date_format(
|
||||
value, format=self.format or "SHORT_DATETIME_FORMAT", use_l10n=True
|
||||
)
|
||||
return formats.date_format(value, format=self._get_format(), use_l10n=True)
|
||||
|
||||
return str(value)
|
||||
|
||||
@@ -123,8 +79,95 @@ class AirDateTimePickerInput(widgets.DateTimeInput):
|
||||
# This does it's best to convert Django's PHP-Style date format to a datetime format and reformat the
|
||||
# value to be read by Django. Probably could be improved
|
||||
return datetime.datetime.strptime(
|
||||
value,
|
||||
self.format
|
||||
value.strip(),
|
||||
django_to_python_datetime(self._get_format())
|
||||
or django_to_python_datetime(get_format("SHORT_DATETIME_FORMAT")),
|
||||
).strftime("%Y-%m-%d")
|
||||
except (ValueError, TypeError) as e:
|
||||
return value
|
||||
return None
|
||||
|
||||
|
||||
class AirDateTimePickerInput(widgets.DateTimeInput):
|
||||
def __init__(
|
||||
self,
|
||||
attrs=None,
|
||||
format=None,
|
||||
timepicker=True,
|
||||
clear_button=True,
|
||||
auto_close=True,
|
||||
user=None,
|
||||
*args,
|
||||
**kwargs,
|
||||
):
|
||||
attrs = attrs or {}
|
||||
self.user = user
|
||||
super().__init__(attrs=attrs, format=format, *args, **kwargs)
|
||||
self.timepicker = timepicker
|
||||
self.clear_button = clear_button
|
||||
self.auto_close = auto_close
|
||||
|
||||
@staticmethod
|
||||
def _get_current_language():
|
||||
"""Get current language code in format compatible with AirDatepicker"""
|
||||
lang_code = translation.get_language()
|
||||
# AirDatepicker uses simple language codes
|
||||
return lang_code.split("-")[0]
|
||||
|
||||
def _get_format(self):
|
||||
"""Get the format string based on user settings or default"""
|
||||
if self.format:
|
||||
return self.format
|
||||
|
||||
if self.user and hasattr(self.user, "settings"):
|
||||
user_format = self.user.settings.datetime_format
|
||||
if user_format == "SHORT_DATETIME_FORMAT":
|
||||
return get_format("SHORT_DATETIME_FORMAT", use_l10n=True)
|
||||
return user_format
|
||||
|
||||
return get_format("SHORT_DATETIME_FORMAT", use_l10n=True)
|
||||
|
||||
def build_attrs(self, base_attrs, extra_attrs=None):
|
||||
attrs = super().build_attrs(base_attrs, extra_attrs)
|
||||
|
||||
date_format, time_format = django_to_airdatepicker_datetime_separated(
|
||||
self._get_format()
|
||||
)
|
||||
|
||||
# Add data attributes for AirDatepicker configuration
|
||||
attrs["data-timepicker"] = str(self.timepicker).lower()
|
||||
attrs["data-auto-close"] = str(self.auto_close).lower()
|
||||
attrs["data-clear-button"] = str(self.clear_button).lower()
|
||||
attrs["data-language"] = self._get_current_language()
|
||||
attrs["data-date-format"] = date_format
|
||||
attrs["data-time-format"] = time_format
|
||||
|
||||
return attrs
|
||||
|
||||
def format_value(self, value):
|
||||
"""Format the value for display in the widget."""
|
||||
if value:
|
||||
self.attrs["data-value"] = datetime.datetime.strftime(
|
||||
value, "%Y-%m-%d %H:%M:00"
|
||||
)
|
||||
|
||||
if value is None:
|
||||
return ""
|
||||
if isinstance(value, (datetime.date, datetime.datetime)):
|
||||
return formats.date_format(value, format=self._get_format(), use_l10n=True)
|
||||
|
||||
return str(value)
|
||||
|
||||
def value_from_datadict(self, data, files, name):
|
||||
"""Parse the datetime string from the form data."""
|
||||
value = super().value_from_datadict(data, files, name)
|
||||
if value:
|
||||
try:
|
||||
# This does it's best to convert Django's PHP-Style date format to a datetime format and reformat the
|
||||
# value to be read by Django. Probably could be improved
|
||||
return datetime.datetime.strptime(
|
||||
value.strip(),
|
||||
django_to_python_datetime(self._get_format())
|
||||
or django_to_python_datetime(get_format("SHORT_DATETIME_FORMAT")),
|
||||
).strftime("%Y-%m-%d %H:%M:%S")
|
||||
except (ValueError, TypeError) as e:
|
||||
@@ -140,7 +183,8 @@ class AirMonthYearPickerInput(AirDatePickerInput):
|
||||
# Store the Python format for internal use
|
||||
self.python_format = "%B %Y"
|
||||
|
||||
def _get_month_names(self):
|
||||
@staticmethod
|
||||
def _get_month_names():
|
||||
"""Get month names using Django's date translation"""
|
||||
return {dates.MONTHS[i]: i for i in range(1, 13)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user