Skip to content

Commit ad02fd0

Browse files
authored
Merge pull request #26 from simoneanam/2.3
Merge fork simone 2.3
2 parents 349ae2c + f8769dc commit ad02fd0

File tree

4 files changed

+86
-2
lines changed

4 files changed

+86
-2
lines changed

backend/ozon/core/ModelData.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Copyright INRIM (https://www.inrim.eu)
22
# See LICENSE file for full licensing details.
33
import pydantic
4+
from pydantic.v1.fields import ModelField
45

56
from .BaseClass import PluginBase
67
from .QueryEngine import QueryEngine, DateTimeEncoder
@@ -165,6 +166,74 @@ async def component_by_type(self, model_type):
165166
async def component_distinct_model(self):
166167
return await search_distinct(Component)
167168

169+
def _decode_mongo_query(self, query: Any, model_cls: Type[ModelType]):
170+
DT_OPS = {
171+
"$eq", "$ne", "$gt", "$gte", "$lt", "$lte",
172+
"$in", "$nin",
173+
}
174+
175+
LOGICAL_OPS = {"$and", "$or", "$nor"}
176+
177+
def parse_dt(v: str) -> datetime | str:
178+
# parse ISO-ish strings; keep original if not parseable
179+
s = v.strip()
180+
if s.endswith("Z"):
181+
s = s[:-1] + "+00:00"
182+
try:
183+
return datetime.fromisoformat(s)
184+
except ValueError:
185+
return v
186+
187+
def is_datetime_field(field: ModelField | None) -> bool:
188+
# Pydantic v1: Optional[datetime] still has type_ == datetime
189+
return bool(field and field.type_ is datetime)
190+
191+
fields = model_cls.__fields__
192+
193+
def walk(node: Any, *, force_dt: bool = False) -> Any:
194+
# force_dt means: we are inside a datetime field filter subtree
195+
if isinstance(node, dict):
196+
out: dict[str, Any] = {}
197+
for k, v in node.items():
198+
# logical operators contain subfilters
199+
if k in LOGICAL_OPS and isinstance(v, list):
200+
out[k] = [walk(item, force_dt=False) for item in v]
201+
continue
202+
203+
# Mongo operators (when inside a datetime field)
204+
if force_dt and k in DT_OPS:
205+
if isinstance(v, str):
206+
out[k] = parse_dt(v)
207+
elif isinstance(v, list):
208+
out[k] = [parse_dt(x) if isinstance(x, str) else x for x in v]
209+
else:
210+
out[k] = v
211+
continue
212+
213+
# Normal field at root / nested document style
214+
field = fields.get(k)
215+
if is_datetime_field(field):
216+
# Under a datetime field: parse direct strings, and also operator dict values
217+
if isinstance(v, str):
218+
out[k] = parse_dt(v)
219+
else:
220+
out[k] = walk(v, force_dt=True)
221+
else:
222+
out[k] = walk(v, force_dt=False)
223+
return out
224+
225+
if isinstance(node, list):
226+
return [walk(x, force_dt=force_dt) for x in node]
227+
228+
# primitives
229+
if force_dt and isinstance(node, str):
230+
return parse_dt(node)
231+
return node
232+
233+
res = walk(query, force_dt=False)
234+
logger.debug(f"[_decode_mongo_query]: {res}]")
235+
return res
236+
168237
async def search_base(
169238
self,
170239
data_model: Type[ModelType],
@@ -185,6 +254,9 @@ async def search_base(
185254
#
186255
sort = [("list_order", ASCENDING), ("rec_name", DESCENDING)]
187256

257+
if query:
258+
query = self._decode_mongo_query(query, data_model)
259+
188260
if use_aggregate:
189261
list_data = await aggregate(
190262
data_model, query, sort=sort, limit=limit, skip=skip
@@ -248,6 +320,10 @@ async def count_by_filter(
248320
model = data_model
249321
if not isinstance(data_model, str):
250322
model = data_model.str_name()
323+
324+
if query:
325+
query = self._decode_mongo_query(query, data_model)
326+
251327
return await count_by_filter(model, domain=query)
252328

253329
async def search(

web-client/core/main/custom_components.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,8 +1099,6 @@ def __init__(self, raw, builder, **kwargs):
10991099
)
11001100
self.isodate_regex = self.dte.isodate_regex
11011101

1102-
self.size = 12
1103-
11041102
def parse_date(self, val):
11051103
if not self.is_time:
11061104
value_date = self.dte.server_datetime_to_ui_date_str(val)

web-client/core/themes/italia/static/css/project.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,4 +138,11 @@ body, html, table, button {
138138
flex: 0 0 auto !important;
139139
width: auto !important;
140140
max-width: 100% !important;
141+
}
142+
143+
.it-datepicker-wrapper small.form-text {
144+
position: absolute;
145+
padding: .25rem .5rem;
146+
font-size: .777rem;
147+
margin-top: -3rem;
141148
}

web-client/core/themes/italia/templates/components/datetime/form_date_time.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@
3838
</div>
3939
{% endif %}
4040
</div>
41+
{% if desc %}
42+
<small class="form-text text-muted">{{ desc | safe }}</small>
43+
{% endif %}
4144
</div>
4245

4346
</div>

0 commit comments

Comments
 (0)