🐛 fix(store.py): change filter_by_user parameter name to liked to improve semantics and clarity

✨ feat(store.py): add support for filtering components by liked status to get_components function
🐛 fix(store.py): remove in_user_collection attribute from ListComponentResponse schema as it is not used
🐛 fix(service.py): change _get method signature to accept Optional parameters and add type hints
✨ feat(service.py): add build_tags_filter method to build the tags filter for get_components function
🐛 fix(service.py): remove filter_by_user parameter from count_components function and adjust logic accordingly
✨ feat(service.py): add liked parameter to get_components function to filter components by liked status
🐛 fix(service.py): change get_components_in_users_collection method parameter type from List[UUID] to List[str]
🐛 fix(service.py): change download method parameter type from str to UUID
🐛 fix(utils.py): change update_components_with_user_data function parameter type from List["ListComponentResponse"] to List[ListComponentResponse]
This commit is contained in:
Gabriel Luiz Freitas Almeida 2023-11-14 14:47:02 -03:00
commit bd4e88273b
4 changed files with 32 additions and 34 deletions

View file

@ -4,7 +4,6 @@ from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException, Query from fastapi import APIRouter, Depends, HTTPException, Query
from httpx import HTTPStatusError from httpx import HTTPStatusError
from langflow.services.auth import utils as auth_utils from langflow.services.auth import utils as auth_utils
from langflow.services.database.models.user.user import User from langflow.services.database.models.user.user import User
from langflow.services.deps import get_settings_service, get_store_service from langflow.services.deps import get_settings_service, get_store_service
@ -80,7 +79,7 @@ def get_components(
is_component: Annotated[Optional[bool], Query()] = None, is_component: Annotated[Optional[bool], Query()] = None,
tags: Annotated[Optional[list[str]], Query()] = None, tags: Annotated[Optional[list[str]], Query()] = None,
sort: Annotated[Union[list[str], None], Query()] = None, sort: Annotated[Union[list[str], None], Query()] = None,
filter_by_user: Annotated[bool, Query()] = False, liked: Annotated[bool, Query()] = False,
page: int = 1, page: int = 1,
limit: int = 10, limit: int = 10,
store_service: StoreService = Depends(get_store_service), store_service: StoreService = Depends(get_store_service),
@ -96,7 +95,7 @@ def get_components(
api_key=store_api_Key, api_key=store_api_Key,
page=page, page=page,
limit=limit, limit=limit,
filter_by_user=filter_by_user, liked=liked,
is_component=is_component, is_component=is_component,
search=search, search=search,
status=status, status=status,
@ -111,7 +110,6 @@ def get_components(
if len(result) >= limit: if len(result) >= limit:
comp_count = store_service.count_components( comp_count = store_service.count_components(
api_key=store_api_Key, api_key=store_api_Key,
filter_by_user=filter_by_user,
filter_conditions=filter_conditions, filter_conditions=filter_conditions,
) )
else: else:

View file

@ -45,7 +45,6 @@ class ListComponentResponse(BaseModel):
description: Optional[str] description: Optional[str]
liked_by_count: Optional[int] liked_by_count: Optional[int]
liked_by_user: Optional[bool] liked_by_user: Optional[bool]
in_user_collection: Optional[bool]
is_component: Optional[bool] is_component: Optional[bool]
metadata: Optional[dict] metadata: Optional[dict]
user_created: Optional[dict] user_created: Optional[dict]

View file

@ -5,7 +5,6 @@ from uuid import UUID
import httpx import httpx
from httpx import HTTPError, HTTPStatusError from httpx import HTTPError, HTTPStatusError
from langflow.services.base import Service from langflow.services.base import Service
from langflow.services.store.schema import ( from langflow.services.store.schema import (
ComponentResponse, ComponentResponse,
@ -73,7 +72,9 @@ class StoreService(Service):
# will make a property return that data # will make a property return that data
# Without making the request multiple times # Without making the request multiple times
def _get(self, url: str, api_key: str, params: Dict[str, Any] = None) -> List[Dict[str, Any]]: def _get(
self, url: str, api_key: Optional[str] = None, params: Optional[Dict[str, Any]] = None
) -> List[Dict[str, Any]]:
"""Utility method to perform GET requests.""" """Utility method to perform GET requests."""
if api_key: if api_key:
headers = {"Authorization": f"Bearer {api_key}"} headers = {"Authorization": f"Bearer {api_key}"}
@ -127,7 +128,7 @@ class StoreService(Service):
"limit": limit, "limit": limit,
} }
filter_conditions = [] filter_conditions: List[Dict[str, Any]] = []
if status: if status:
filter_conditions.append({"status": {"_eq": status}}) filter_conditions.append({"status": {"_eq": status}})
@ -136,9 +137,7 @@ class StoreService(Service):
filter_conditions.append({"is_component": {"_eq": is_component}}) filter_conditions.append({"is_component": {"_eq": is_component}})
if tags: if tags:
tags_filter = {"tags": {"_and": []}} tags_filter = self.build_tags_filter(tags)
for tag in tags:
tags_filter["tags"]["_and"].append({"_some": {"tags_id": {"name": {"_eq": tag}}}})
filter_conditions.append(tags_filter) filter_conditions.append(tags_filter)
if date_from: if date_from:
@ -167,19 +166,18 @@ class StoreService(Service):
results = self._get(self.components_url, api_key, params) results = self._get(self.components_url, api_key, params)
return [ComponentResponse(**component) for component in results] return [ComponentResponse(**component) for component in results]
def build_tags_filter(self, tags: List[str]):
tags_filter = {"tags": {"_and": []}}
for tag in tags:
tags_filter["tags"]["_and"].append({"_some": {"tags_id": {"name": {"_eq": tag}}}})
return tags_filter
def count_components( def count_components(
self, self,
filter_conditions: List[Dict[str, Any]],
api_key: Optional[str] = None, api_key: Optional[str] = None,
filter_by_user: bool = False,
filter_conditions: Optional[List[Dict[str, Any]]] = None,
) -> int: ) -> int:
params = {"aggregate": json.dumps({"count": "*"})} params = {"aggregate": json.dumps({"count": "*"})}
filter_conditions = [] if filter_conditions is None else filter_conditions
if filter_by_user:
params["deep"] = json.dumps({"components": {"_filter": {"user_created": {"token": {"_eq": api_key}}}}})
else:
filter_conditions.append({"status": {"_in": ["public", "Public"]}})
if filter_conditions: if filter_conditions:
params["filter"] = json.dumps({"_and": filter_conditions}) params["filter"] = json.dumps({"_and": filter_conditions})
@ -207,7 +205,7 @@ class StoreService(Service):
limit: int = 15, limit: int = 15,
fields: Optional[List[str]] = None, fields: Optional[List[str]] = None,
is_component: Optional[bool] = None, is_component: Optional[bool] = None,
filter_by_user: bool = False, liked: bool = False,
) -> Tuple[List[ListComponentResponse], List[Dict[str, Any]]]: ) -> Tuple[List[ListComponentResponse], List[Dict[str, Any]]]:
params = {"page": page, "limit": limit} params = {"page": page, "limit": limit}
# ?aggregate[count]=likes # ?aggregate[count]=likes
@ -239,15 +237,15 @@ class StoreService(Service):
# Only public components or the ones created by the user # Only public components or the ones created by the user
# check for "public" or "Public" # check for "public" or "Public"
if filter_by_user and not api_key: if liked and not api_key:
raise ValueError("No API key provided") raise ValueError("No API key provided")
if filter_by_user and api_key: if liked and api_key:
user_data = user_data_var.get() user_data = user_data_var.get()
# params["filter"] = json.dumps({"user_created": {"_eq": user_data["id"]}}) # params["filter"] = json.dumps({"user_created": {"_eq": user_data["id"]}})
if not user_data: if not user_data:
raise ValueError("No user data") raise ValueError("No user data")
filter_conditions.append({"user_created": {"_eq": user_data["id"]}}) filter_conditions.append({"liked_by": {"_eq": user_data["id"]}})
else: else:
filter_conditions.append({"status": {"_in": ["public", "Public"]}}) filter_conditions.append({"status": {"_in": ["public", "Public"]}})
@ -284,7 +282,7 @@ class StoreService(Service):
return [result["id"] for result in results] return [result["id"] for result in results]
# Which of the components is parent of the user's components # Which of the components is parent of the user's components
def get_components_in_users_collection(self, component_ids: List[UUID], api_key: str): def get_components_in_users_collection(self, component_ids: List[str], api_key: str):
user_data = user_data_var.get() user_data = user_data_var.get()
if not user_data: if not user_data:
raise ValueError("No user data") raise ValueError("No user data")
@ -302,7 +300,7 @@ class StoreService(Service):
results = self._get(self.components_url, api_key, params) results = self._get(self.components_url, api_key, params)
return [result["id"] for result in results] return [result["id"] for result in results]
def download(self, api_key: str, component_id: str) -> DownloadComponentResponse: def download(self, api_key: str, component_id: UUID) -> DownloadComponentResponse:
url = f"{self.components_url}/{component_id}" url = f"{self.components_url}/{component_id}"
params = {"fields": ",".join(["id", "name", "description", "data", "is_component"])} params = {"fields": ",".join(["id", "name", "description", "data", "is_component"])}

View file

@ -16,20 +16,23 @@ def update_components_with_user_data(
components: List["ListComponentResponse"], components: List["ListComponentResponse"],
store_service: "StoreService", store_service: "StoreService",
store_api_Key: str, store_api_Key: str,
liked: bool,
): ):
""" """
Updates the components with the user data (liked_by_user and in_users_collection) Updates the components with the user data (liked_by_user and in_users_collection)
""" """
liked_by_user_ids = store_service.get_liked_by_user_components( component_ids = [str(component.id) for component in components]
component_ids=[str(component.id) for component in components], if liked:
api_key=store_api_Key, # If liked is True, this means all we got were liked_by_user components
) # So we can set liked_by_user to True for all components
in_users_collection_ids = store_service.get_components_in_users_collection( liked_by_user_ids = component_ids
component_ids=[str(component.id) for component in components], else:
api_key=store_api_Key, liked_by_user_ids = store_service.get_liked_by_user_components(
) component_ids=component_ids,
api_key=store_api_Key,
)
# Now we need to set the liked_by_user attribute # Now we need to set the liked_by_user attribute
for component in components: for component in components:
component.liked_by_user = str(component.id) in liked_by_user_ids component.liked_by_user = str(component.id) in liked_by_user_ids
component.in_user_collection = str(component.id) in in_users_collection_ids
return components return components