Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 109 additions & 1 deletion backend/chainlit/input_widget.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from abc import abstractmethod
from typing import Any, Dict, List, Optional
from datetime import date
from typing import Any, Dict, List, Literal, Optional

from pydantic import Field
from pydantic.dataclasses import dataclass
Expand Down Expand Up @@ -314,3 +315,110 @@ def to_dict(self) -> dict[str, Any]:
"label": self.label,
"inputs": [input.to_dict() for input in self.inputs],
}


@dataclass
class DatePicker(InputWidget):
"""
Datepicker input widget.
Supports both single date and date range selection.
"""

type: InputWidgetType = "datepicker"
mode: Literal["single", "range"] = "single"
initial: str | date | tuple[str | date, str | date] | None = None
min_date: str | date | None = None
max_date: str | date | None = None
format: str | None = None
"""date-fns format string"""
placeholder: str | None = None
"""Placeholder to use when no date is selected"""

def __post_init__(self) -> None:
super().__post_init__()

if self.mode not in ("single", "range"):
raise ValueError("mode must be 'single' or 'range'")

if (
self.mode == "range"
and self.initial is not None
and not isinstance(self.initial, tuple)
):
raise ValueError("'initial' must be a tuple for range mode")

(initial_start, initial_end), min_date, max_date = (
[
DatePicker._validate_iso_format(date, "initial")
for date in (
self.initial
if isinstance(self.initial, tuple)
else [self.initial, None]
)
],
DatePicker._validate_iso_format(self.min_date, "min_date"),
DatePicker._validate_iso_format(self.max_date, "max_date"),
)

if self.mode == "range":
self._validate_range(initial_start, initial_end, "initial")
self._validate_range(min_date, max_date, "[min_date, max_date]")

# Validate that initial value(s) are within min_date and max_date bounds
for d in [initial_start, initial_end]:
if d is not None and (
(min_date is not None and d < min_date)
or (max_date is not None and d > max_date)
):
raise ValueError(
"'initial' must be within 'min_date' and 'max_date' bounds"
)

@staticmethod
def _validate_range(
start: date | None,
end: date | None,
field_name: str,
) -> None:
if start is not None and end is not None and start > end:
raise ValueError(
f"'{field_name}' range is invalid, start must be before end."
)

@staticmethod
def _validate_iso_format(
date_value: str | date | None, field_name: str
) -> date | None:
if isinstance(date_value, str):
try:
return date.fromisoformat(date_value)
except ValueError as e:
raise ValueError(f"'{field_name}' must be in ISO format") from e

return date_value

@staticmethod
def _format_date(date_value: str | date | None) -> str | None:
if isinstance(date_value, date):
return date_value.isoformat()
return date_value

def to_dict(self) -> dict[str, Any]:
return {
"type": self.type,
"id": self.id,
"label": self.label,
"tooltip": self.tooltip,
"description": self.description,
"mode": self.mode,
"initial": (
self._format_date(self.initial[0]),
self._format_date(self.initial[1]),
)
if isinstance(self.initial, tuple)
else DatePicker._format_date(self.initial),
"min_date": DatePicker._format_date(self.min_date),
"max_date": DatePicker._format_date(self.max_date),
"format": self.format,
"placeholder": self.placeholder,
}
6 changes: 6 additions & 0 deletions backend/chainlit/translations/bn.json
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,12 @@
"components": {
"MultiSelectInput": {
"placeholder": "বেছে নিন..."
},
"DatePickerInput": {
"placeholder": {
"single": "একটি তারিখ বেছে নিন",
"range": "তারিখের পরিসীমা বেছে নিন"
}
}
}
}
6 changes: 6 additions & 0 deletions backend/chainlit/translations/el-GR.json
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,12 @@
"components": {
"MultiSelectInput": {
"placeholder": "Επιλέξτε..."
},
"DatePickerInput": {
"placeholder": {
"single": "Επιλέξτε ημερομηνία",
"range": "Επιλέξτε εύρος ημερομηνιών"
}
}
}
}
6 changes: 6 additions & 0 deletions backend/chainlit/translations/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,12 @@
"components": {
"MultiSelectInput": {
"placeholder": "Select..."
},
"DatePickerInput": {
"placeholder": {
"single": "Pick a date",
"range": "Pick a date range"
}
}
}
}
6 changes: 6 additions & 0 deletions backend/chainlit/translations/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,12 @@
"components": {
"MultiSelectInput": {
"placeholder": "Seleccionar..."
},
"DatePickerInput": {
"placeholder": {
"single": "Elige una fecha",
"range": "Elige un rango de fechas"
}
}
}
}
6 changes: 6 additions & 0 deletions backend/chainlit/translations/fr-FR.json
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,12 @@
"components": {
"MultiSelectInput": {
"placeholder": "Sélectionner..."
},
"DatePickerInput": {
"placeholder": {
"single": "Choisir une date",
"range": "Choisir une plage de dates"
}
}
}
}
6 changes: 6 additions & 0 deletions backend/chainlit/translations/gu.json
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,12 @@
"components": {
"MultiSelectInput": {
"placeholder": "બેંચી લો..."
},
"DatePickerInput": {
"placeholder": {
"single": "તારીખ પસંદ કરો",
"range": "તારીખની શ્રેણી પસંદ કરો"
}
}
}
}
6 changes: 6 additions & 0 deletions backend/chainlit/translations/he-IL.json
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,12 @@
"components": {
"MultiSelectInput": {
"placeholder": "בחר..."
},
"DatePickerInput": {
"placeholder": {
"single": "בחר תאריך",
"range": "בחר טווח תאריכים"
}
}
}
}
6 changes: 6 additions & 0 deletions backend/chainlit/translations/hi.json
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,12 @@
"components": {
"MultiSelectInput": {
"placeholder": "चुनें..."
},
"DatePickerInput": {
"placeholder": {
"single": "एक तारीख चुनें",
"range": "तारीख सीमा चुनें"
}
}
}
}
6 changes: 6 additions & 0 deletions backend/chainlit/translations/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,12 @@
"components": {
"MultiSelectInput": {
"placeholder": "選択..."
},
"DatePickerInput": {
"placeholder": {
"single": "日付を選択",
"range": "日付範囲を選択"
}
}
}
}
6 changes: 6 additions & 0 deletions backend/chainlit/translations/kn.json
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,12 @@
"components": {
"MultiSelectInput": {
"placeholder": "ಚುನಾಯಿಸಿ..."
},
"DatePickerInput": {
"placeholder": {
"single": "ದಿನಾಂಕವನ್ನು ಆಯ್ಕೆಮಾಡಿ",
"range": "ದಿನಾಂಕ ಶ್ರೇಣಿಯನ್ನು ಆಯ್ಕೆಮಾಡಿ"
}
}
}
}
6 changes: 6 additions & 0 deletions backend/chainlit/translations/ml.json
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,12 @@
"components": {
"MultiSelectInput": {
"placeholder": "ചൂണ്ടിക്കാണിക്കുക..."
},
"DatePickerInput": {
"placeholder": {
"single": "തീയതി തിരഞ്ഞെടുക്കുക",
"range": "തീയതി ശ്രേണി തിരഞ്ഞെടുക്കുക"
}
}
}
}
6 changes: 6 additions & 0 deletions backend/chainlit/translations/mr.json
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,12 @@
"components": {
"MultiSelectInput": {
"placeholder": "चुनें..."
},
"DatePickerInput": {
"placeholder": {
"single": "तारीख निवडा",
"range": "तारीख श्रेणी निवडा"
}
}
}
}
6 changes: 6 additions & 0 deletions backend/chainlit/translations/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,12 @@
"components": {
"MultiSelectInput": {
"placeholder": "Selecteer..."
},
"DatePickerInput": {
"placeholder": {
"single": "Kies een datum",
"range": "Kies een datumbereik"
}
}
}
}
6 changes: 6 additions & 0 deletions backend/chainlit/translations/ta.json
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,12 @@
"components": {
"MultiSelectInput": {
"placeholder": "தேர்ந்தெடுக்கவும்..."
},
"DatePickerInput": {
"placeholder": {
"single": "தேதியைத் தேர்ந்தெடுக்கவும்",
"range": "தேதி வரம்பைத் தேர்ந்தெடுக்கவும்"
}
}
}
}
6 changes: 6 additions & 0 deletions backend/chainlit/translations/te.json
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,12 @@
"components": {
"MultiSelectInput": {
"placeholder": "ఎంచుకోండి..."
},
"DatePickerInput": {
"placeholder": {
"single": "తేదీని ఎంచుకోండి",
"range": "తేదీ పరిధిని ఎంచుకోండి"
}
}
}
}
6 changes: 6 additions & 0 deletions backend/chainlit/translations/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,12 @@
"components": {
"MultiSelectInput": {
"placeholder": "选择..."
},
"DatePickerInput": {
"placeholder": {
"single": "选择日期",
"range": "选择日期范围"
}
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions backend/chainlit/translations/zh-TW.json
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,12 @@
"components": {
"MultiSelectInput": {
"placeholder": "選擇..."
},
"DatePickerInput": {
"placeholder": {
"single": "選擇日期",
"range": "選擇日期範圍"
}
}
}
}
1 change: 1 addition & 0 deletions backend/chainlit/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"multiselect",
"checkbox",
"radio",
"datepicker",
]
ToastType = Literal["info", "success", "warning", "error"]

Expand Down
2 changes: 2 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,15 @@
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "1.0.0",
"date-fns": "^4.1.0",
"embla-carousel-react": "^8.5.1",
"highlight.js": "^11.9.0",
"i18next": "^23.7.16",
"lodash": "^4.17.21",
"lucide-react": "^0.468.0",
"plotly.js": "^2.27.0",
"react": "^18.3.1",
"react-day-picker": "^9.11.1",
"react-dom": "^18.3.1",
"react-dropzone": "^14.2.3",
"react-file-icon": "^1.3.0",
Expand Down
Loading
Loading