Skip to content
Merged
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
2 changes: 2 additions & 0 deletions goosebit/ui/bff/common/columns.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,14 @@ class DeviceColumns:
title="Update Mode",
data="update_mode",
name="update_mode",
searchable=True,
orderable=True,
)
last_state = DTColumnDescription(
title="State",
data="last_state",
name="last_state",
searchable=True,
orderable=True,
)
force_update = DTColumnDescription(
Expand Down
23 changes: 22 additions & 1 deletion goosebit/ui/bff/devices/responses.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
from __future__ import annotations

from enum import IntEnum
from typing import Any, Callable

from pydantic import BaseModel, Field
from tortoise.expressions import Q
from tortoise.queryset import QuerySet

from goosebit.db.models import UpdateModeEnum, UpdateStateEnum
from goosebit.schema.devices import DeviceSchema
from goosebit.ui.bff.common.requests import DataTableRequest

# Integer-enum columns displayed as text: search the term against the enum names, not the column.
ENUM_SEARCH_COLUMNS: dict[str, type[IntEnum]] = {
"last_state": UpdateStateEnum,
"update_mode": UpdateModeEnum,
}


def _enum_search_query(name: str, enum_cls: type[IntEnum], value: str) -> Q:
# Substring match on enum display names ("err" -> ERROR); no match -> empty __in -> no rows.
value = value.casefold()
matches = [int(member) for member in enum_cls if value in str(member).casefold()]
return Q(**{f"{name}__in": matches})


class BFFDeviceResponse(BaseModel):
data: list[DeviceSchema]
Expand All @@ -24,7 +40,12 @@ async def convert(
query = query.filter(search_filter(dt_query.search.value))

for column in dt_query.columns:
query = query.filter(column.query)
enum_cls = ENUM_SEARCH_COLUMNS.get(column.name)
if enum_cls is not None and column.search.value is not None:
column_query = _enum_search_query(column.name, enum_cls, column.search.value)
else:
column_query = column.query
query = query.filter(column_query)

filtered_records = await query.count()

Expand Down
Loading