diff --git a/api/app/account/routes.py b/api/app/account/routes.py
index d19c0b5..f26b9b4 100644
--- a/api/app/account/routes.py
+++ b/api/app/account/routes.py
@@ -1,12 +1,10 @@
from uuid import UUID
-
-from fastapi import APIRouter, HTTPException, Depends, Query
-from sqlmodel import Field, Session, SQLModel, create_engine, select
+from fastapi import APIRouter, HTTPException, Depends
from fastapi_pagination import Page
from fastapi_pagination.ext.sqlmodel import paginate
-from .models import Account, AccountCreate, AccountRead, AccountUpdate
+from account.models import Account, AccountCreate, AccountRead, AccountUpdate
from db import SessionDep
from user.manager import get_current_user
diff --git a/api/app/category/models.py b/api/app/category/models.py
index d46f165..7a8edaa 100644
--- a/api/app/category/models.py
+++ b/api/app/category/models.py
@@ -1,6 +1,8 @@
from uuid import UUID, uuid4
from enum import Enum
+from typing import Optional
+from fastapi_filter.contrib.sqlalchemy import Filter
from sqlmodel import Field, SQLModel, select
class CategoryBase(SQLModel):
@@ -21,8 +23,8 @@ class Category(CategoryRead, table=True):
return category_db
@classmethod
- def list(cls):
- return select(Category)
+ def list(cls, filters):
+ return filters.filter(select(cls))
@classmethod
def get(cls, session, category_id):
@@ -49,3 +51,10 @@ class CategoryCreate(CategoryWrite):
class CategoryUpdate(CategoryWrite):
pass
+
+class CategoryFilters(Filter):
+ name__like: Optional[str] = None
+
+ class Constants(Filter.Constants):
+ model = Category
+ search_model_fields = ["name"]
diff --git a/api/app/category/routes.py b/api/app/category/routes.py
index be52781..e5aff90 100644
--- a/api/app/category/routes.py
+++ b/api/app/category/routes.py
@@ -1,11 +1,12 @@
from uuid import UUID
-
from fastapi import APIRouter, HTTPException, Depends
+from fastapi_filter import FilterDepends
from fastapi_pagination import Page
from fastapi_pagination.ext.sqlmodel import paginate
+from pydantic import BaseModel
-from category.models import Category, CategoryCreate, CategoryRead, CategoryUpdate
+from category.models import Category, CategoryCreate, CategoryRead, CategoryUpdate, CategoryFilters
from db import SessionDep
from user.manager import get_current_user
@@ -17,8 +18,10 @@ def create_category(category: CategoryCreate, session: SessionDep, current_user=
return category
@router.get("")
-def read_categories(session: SessionDep, current_user=Depends(get_current_user)) -> Page[CategoryRead]:
- return paginate(session, Category.list())
+def read_categories(session: SessionDep,
+ filters: CategoryFilters = FilterDepends(CategoryFilters),
+ current_user=Depends(get_current_user)) -> Page[CategoryRead]:
+ return paginate(session, Category.list(filters))
@router.get("/{category_id}")
def read_category(category_id: UUID, session: SessionDep, current_user=Depends(get_current_user)) -> CategoryRead:
diff --git a/api/app/requirements.txt b/api/app/requirements.txt
index 7b42cc8..4ed1615 100644
--- a/api/app/requirements.txt
+++ b/api/app/requirements.txt
@@ -5,3 +5,4 @@ fastapi
fastapi-pagination
fastapi-users[sqlmodel]
fastapi-users-db-sqlmodel
+fastapi-filter[sqlalchemy]
diff --git a/gui/app/src/common/crud/widgets/crud-text-widget.tsx b/gui/app/src/common/crud/widgets/crud-text-widget.tsx
index 094ce65..1aaaf4c 100644
--- a/gui/app/src/common/crud/widgets/crud-text-widget.tsx
+++ b/gui/app/src/common/crud/widgets/crud-text-widget.tsx
@@ -10,6 +10,6 @@ export default function CrudTextWidget);
}else {
- return ();
+ return ();
}
-}
\ No newline at end of file
+}
diff --git a/gui/app/src/common/crud/widgets/foreign-key.tsx b/gui/app/src/common/crud/widgets/foreign-key.tsx
index 756ebc3..7da4c3e 100644
--- a/gui/app/src/common/crud/widgets/foreign-key.tsx
+++ b/gui/app/src/common/crud/widgets/foreign-key.tsx
@@ -11,38 +11,24 @@ import {useList} from "@refinedev/core";
export const ForeignKeyWidget = (props: WidgetProps) => {
const [inputValue, setInputValue] = useState("");
const [selectedValue, setSelectedValue] = useState(null);
+ const [debouncedInputValue, setDebouncedInputValue] = useState(inputValue);
const resource = props.schema.foreign_key.reference.resource
+ useEffect(() => {
+ const handler = setTimeout(() => setDebouncedInputValue(inputValue), 300); // Adjust debounce delay as needed
+ return () => clearTimeout(handler);
+ }, [inputValue]);
+
const { data, isLoading } = useList({
resource: resource,
pagination: { current: 1, pageSize: 10 },
+ filters: [{ field: "name", operator: "contains", value: debouncedInputValue }],
sorters: [{ field: "name", order: "asc" }],
- filters: [{ field: "name", operator: "contains", value: "input" }],
});
const options = data?.data || [];
- // const fetchOptions = async (input: string) => {
- // try {
- //
- // } catch (error) {
- // console.error("Error fetching options:", error);
- // }
- // };
-
- // // Debounced version of the fetch function
- // const debouncedFetch = useCallback(debounce(fetchOptions, 300), []);
- // // Trigger fetch whenever the inputValue changes
- // useEffect(() => {
- // if (inputValue) {
- // debouncedFetch(inputValue);
- // } else {
- // setOptions([]); // Clear options when input is empty
- // }
- // }, [inputValue, debouncedFetch]);
-
-
return (
0) {
filters.forEach((filter) => {
- if ("field" in filter && filter.operator === "eq") {
- // Our fake API supports "eq" operator by simply appending the field name and value to the query string.
- params.append(filter.field, filter.value);
+ if ("field" in filter && filter.value.length > 0 && filter.operator === "contains") {
+ params.append(filter.field + "__like", "%" + filter.value + "%");
}
});
}