BE+FE: change log

This commit is contained in:
jokob-sk
2026-07-05 22:38:29 +10:00
parent 35313feff4
commit e0449bed8e
44 changed files with 1346 additions and 542 deletions

View File

@@ -777,12 +777,12 @@ def api_devices_totals(payload=None):
@validate_request(
operation_id="get_device_history_filters",
summary="Get Device History Filter Values",
description="Return distinct changedBy and changedColumn values available in DevicesHistory. Optionally scope to a single device with ?devGuid=<guid>.",
description="Return distinct changedBy and changedColumn values available in DevicesHistory. Optionally scope to a single device with ?devGUID=<guid>.",
tags=["devices"],
auth_callable=is_authorized
)
def api_devices_history_filters(payload=None):
dev_guid = request.args.get("devGuid") or None
dev_guid = request.args.get("devGUID") or None
filters = DevicesHistoryInstance().get_available_filter_values(devGUID=dev_guid)
return jsonify({"success": True, "data": filters})

View File

@@ -33,6 +33,7 @@ from .graphql_helpers import ( # noqa: E402 [flake8 lint suppression]
apply_common_pagination,
apply_plugin_filters,
apply_events_filters,
extract_paging
)
from models.device_history_instance import DevicesHistoryInstance # noqa: E402
@@ -65,72 +66,98 @@ def _to_graphql_history(groups):
class Query(ObjectType):
# --- DEVICES ---
devices = Field(DeviceResult, options=PageQueryOptionsInput())
# --- DEVICE HISTORY ---
deviceHistoryGrouped = Field(
DeviceHistoryResult,
devGuid=String(required=True, description="Device GUID to fetch history for"),
devGUID=String(required=False, description="Device GUID to fetch history for"),
changedColumn=String(description="Filter to groups containing this field change"),
changedBy=String(description="Filter to a specific attribution source"),
limit=graphene.Int(description="Max grouped events to return (default 50)"),
offset=graphene.Int(description="Grouped-event offset for pagination (default 0)"),
options=PageQueryOptionsInput(description="Paging, sorting, filtering options"),
)
allDeviceHistoryGrouped = Field(
DeviceHistoryResult,
changedColumn=String(description="Filter to groups containing this field change"),
changedBy=String(description="Filter to a specific attribution source"),
limit=graphene.Int(description="Max grouped events to return (default 100)"),
offset=graphene.Int(description="Grouped-event offset for pagination (default 0)"),
)
def resolve_deviceHistoryGrouped(
self,
info,
devGUID=None,
changedColumn=None,
changedBy=None,
options=None):
"""
Return grouped device history.
def resolve_deviceHistoryGrouped(self, info, devGuid, changedColumn=None,
changedBy=None, limit=50, offset=0):
If `devGUID` is provided, results are restricted to a single device.
If omitted, history across all devices is returned.
This resolver supports:
- Optional filtering by device GUID, change column, and attribution source
- Pagination via `options` (page/limit/offset)
- Sorting at the grouped event level
- Full-text search across history fields (if enabled in backend)
Internally:
- Raw history rows are fetched from the database
- Rows are grouped in Python by (timestamp, changedBy, devGUID)
- Sorting is applied to grouped events
- Pagination is applied after grouping
Args:
info: GraphQL execution context
devGUID (str | None): Optional device GUID filter
changedColumn (str | None): Filter to only events containing this column
changedBy (str | None): Filter by attribution source
options (PageQueryOptionsInput | None): Paging, sorting, and search options
Returns:
DeviceHistoryResult: Grouped history events and total count
"""
try:
mylog("none", f"[HISTORY] unified resolver devGUID={devGUID} changedColumn={changedColumn} changedBy={changedBy}")
h = DevicesHistoryInstance()
groups = h.get_grouped_history(
devGUID=devGuid,
changedColumn=changedColumn,
changedBy=changedBy,
limit=limit,
offset=offset,
)
total = h.get_total_group_count(
devGUID=devGuid,
changedColumn=changedColumn,
changedBy=changedBy,
)
paging = extract_paging(options)
if devGUID:
groups = h.get_grouped_history(
devGUID=devGUID,
changedColumn=changedColumn,
changedBy=changedBy,
limit=paging["limit"],
offset=paging["offset"],
sort=paging["sort"],
search=paging["search"],
)
total = h.get_total_group_count(
devGUID=devGUID,
changedColumn=changedColumn,
changedBy=changedBy,
)
else:
groups = h.get_all_grouped_history(
changedColumn=changedColumn,
changedBy=changedBy,
limit=paging["limit"],
offset=paging["offset"],
sort=paging["sort"],
search=paging["search"],
)
total = h.get_total_group_count(
changedColumn=changedColumn,
changedBy=changedBy,
)
return DeviceHistoryResult(
history=_to_graphql_history(groups),
count=total,
)
except Exception as e:
mylog("none", f"[graphql] resolve_deviceHistoryGrouped error: {e}")
mylog("none", f"[graphql] unified resolver error: {e}")
return DeviceHistoryResult(history=[], count=0)
def resolve_allDeviceHistoryGrouped(self, info, changedColumn=None,
changedBy=None, limit=100, offset=0):
try:
h = DevicesHistoryInstance()
groups = h.get_all_grouped_history(
changedColumn=changedColumn,
changedBy=changedBy,
limit=limit,
offset=offset,
)
total = h.get_total_group_count(
changedColumn=changedColumn,
changedBy=changedBy,
)
return DeviceHistoryResult(
history=_to_graphql_history(groups),
count=total,
)
except Exception as e:
mylog("none", f"[graphql] resolve_allDeviceHistoryGrouped error: {e}")
return DeviceHistoryResult(history=[], count=0)
# --- DEVICES ---
devices = Field(DeviceResult, options=PageQueryOptionsInput())
def resolve_devices(self, info, options=None):
# mylog('none', f'[graphql_schema] resolve_devices: {self}')

View File

@@ -139,3 +139,29 @@ def apply_events_filters(data, options):
]
return data
def extract_paging(options):
if not options:
return {
"page": 1,
"limit": 50,
"offset": 0,
"sort": [],
"search": None
}
page = getattr(options, "page", 1) or 1
limit = getattr(options, "limit", 50) or 50
search = getattr(options, "search", None)
sort = getattr(options, "sort", []) or []
offset = (page - 1) * limit
return {
"page": page,
"limit": limit,
"offset": offset,
"sort": sort,
"search": search
}

View File

@@ -10,7 +10,7 @@ from graphene import (
class SortOptionsInput(InputObjectType):
field = String()
order = String()
order = String() # direction asc, desc
class FilterOptionsInput(InputObjectType):
@@ -20,8 +20,8 @@ class FilterOptionsInput(InputObjectType):
class PageQueryOptionsInput(InputObjectType):
page = Int()
limit = Int()
sort = List(SortOptionsInput)
limit = Int() # pageSize
sort = List(SortOptionsInput) # sorting
search = String()
status = String()
filters = List(FilterOptionsInput)