Improving the Work Item rendering.
This commit is contained in:
parent
244f0945bb
commit
16d5f2ab98
6 changed files with 115 additions and 20 deletions
|
|
@ -5,4 +5,5 @@ from .utils import (
|
|||
deep_diff,
|
||||
diff_to_patch,
|
||||
filter_to_columns,
|
||||
to_jsonable,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ from sqlalchemy.orm.attributes import InstrumentedAttribute
|
|||
from sqlalchemy.sql import operators
|
||||
from sqlalchemy.sql.elements import UnaryExpression, ColumnElement
|
||||
|
||||
from crudkit.core import deep_diff, diff_to_patch, filter_to_columns, normalize_payload
|
||||
from crudkit.core import to_jsonable, deep_diff, diff_to_patch, filter_to_columns, normalize_payload
|
||||
from crudkit.core.base import Version
|
||||
from crudkit.core.spec import CRUDSpec
|
||||
from crudkit.core.types import OrderSpec, SeekWindow
|
||||
|
|
@ -731,19 +731,23 @@ class CRUDService(Generic[T]):
|
|||
|
||||
def _log_version(self, change_type: str, obj: T, actor=None, metadata: dict | None = None):
|
||||
session = self.session
|
||||
snapshot = {}
|
||||
try:
|
||||
snapshot = obj.as_dict()
|
||||
except Exception:
|
||||
snapshot = {"error": "serialize failed"}
|
||||
snapshot = {}
|
||||
try:
|
||||
snapshot = obj.as_dict()
|
||||
except Exception:
|
||||
snapshot = {"error": "serialize failed"}
|
||||
|
||||
version = Version(
|
||||
model_name=self.model.__name__,
|
||||
object_id=obj.id,
|
||||
change_type=change_type,
|
||||
data=snapshot,
|
||||
actor=str(actor) if actor else None,
|
||||
meta=metadata or None,
|
||||
)
|
||||
session.add(version)
|
||||
session.commit()
|
||||
version = Version(
|
||||
model_name=self.model.__name__,
|
||||
object_id=obj.id,
|
||||
change_type=change_type,
|
||||
data=to_jsonable(snapshot),
|
||||
actor=str(actor) if actor else None,
|
||||
meta=to_jsonable(metadata) if metadata else None,
|
||||
)
|
||||
session.add(version)
|
||||
session.commit()
|
||||
except Exception as e:
|
||||
log.warning(f"Version logging failed for {self.model.__name__} id={getattr(obj, "id", "?")}: {str(e)}")
|
||||
session.rollback()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
from __future__ import annotations
|
||||
from datetime import datetime, date
|
||||
from decimal import Decimal
|
||||
from enum import Enum
|
||||
from typing import Any, Dict, Optional, Callable
|
||||
from sqlalchemy import inspect
|
||||
|
||||
|
|
@ -8,6 +10,32 @@ ISO_DT_FORMATS = ("%Y-%m-%dT%H:%M:%S.%f",
|
|||
"%Y-%m-%d %H:%M",
|
||||
"%Y-%m-%d")
|
||||
|
||||
def to_jsonable(obj: Any):
|
||||
"""Recursively convert values into JSON-serializable forms."""
|
||||
if obj is None or isinstance(obj, (str, int, float, bool)):
|
||||
return obj
|
||||
|
||||
if isinstance(obj, (datetime, date)):
|
||||
return obj.isoformat()
|
||||
|
||||
if isinstance(obj, Decimal):
|
||||
return float(obj)
|
||||
|
||||
if isinstance(obj, Enum):
|
||||
return obj.value
|
||||
|
||||
if isinstance(obj, dict):
|
||||
return {str(k): to_jsonable(v) for k, v in obj.items()}
|
||||
|
||||
if isinstance(obj, (list, tuple, set)):
|
||||
return [to_jsonable(v) for v in obj]
|
||||
|
||||
# fallback: strin-ify weird objects (UUID, ORM instances, etc.)
|
||||
try:
|
||||
return str(obj)
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
def filter_to_columns(data: dict, model_cls):
|
||||
cols = {c.key for c in inspect(model_cls).mapper.columns}
|
||||
return {k: v for k, v in data.items() if k in cols}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue