From d11b199ca485a9aacb6654e510efecd817cb799c Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 26 Oct 2023 10:15:35 -0300 Subject: [PATCH 01/14] =?UTF-8?q?=F0=9F=94=A7=20fix(store.py):=20update=20?= =?UTF-8?q?attribute=20name=20from=20"user=5Fcreated.name"=20to=20"user=5F?= =?UTF-8?q?created.first=5Fname"=20to=20reflect=20correct=20data=20structu?= =?UTF-8?q?re?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🔧 fix(store.py): remove unnecessary code and comments --- src/backend/langflow/api/v1/store.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/backend/langflow/api/v1/store.py b/src/backend/langflow/api/v1/store.py index bbd05f4aa..141e38c38 100644 --- a/src/backend/langflow/api/v1/store.py +++ b/src/backend/langflow/api/v1/store.py @@ -77,7 +77,7 @@ def list_components( "id", "name", "description", - "user_created.name", + "user_created.first_name", "is_component", "tags.tags_id.name", "tags.tags_id.id", @@ -171,3 +171,7 @@ def get_tags( return store_service.get_tags(store_api_Key) except Exception as exc: raise HTTPException(status_code=500, detail=str(exc)) + + +# urlencodedstr = https://api.langflow.store/items/components?page=0&limit=10000&fields=id%2Cname%2Cdescription%2Cuser_created.name%2Cis_component%2Ctags.tags_id.name%2Ctags.tags_id.id%2Ccount%28liked_by%29&filter=%7B%22status%22%3A%20%7B%22_in%22%3A%20%5B%22public%22%2C%20%22Public%22%5D%7D%7D' +# normalstr = https://api.langflow.store/items/components?page=0&limit=10000&fields=id,name,description,user_created.name,is_component,tags.tags_id.name,tags.tags_id.id,count(liked_by)&filter={"status": {"_in": ["public", "Public"]}}' From acc6cd6e4e2973105f1cfd08f432ad2c582a7a49 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 26 Oct 2023 11:31:35 -0300 Subject: [PATCH 02/14] =?UTF-8?q?=F0=9F=90=9B=20fix(service.py):=20handle?= =?UTF-8?q?=20JSONDecodeError=20when=20response=20does=20not=20contain=20d?= =?UTF-8?q?ata=20field=20to=20prevent=20server=20error=20=E2=9C=A8=20feat(?= =?UTF-8?q?service.py):=20return=20ComponentResponse=20with=20component=5F?= =?UTF-8?q?dict=20when=20response=20does=20not=20contain=20data=20field=20?= =?UTF-8?q?to=20provide=20consistent=20response=20format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/services/store/service.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/backend/langflow/services/store/service.py b/src/backend/langflow/services/store/service.py index 83a199445..8b0f5c53f 100644 --- a/src/backend/langflow/services/store/service.py +++ b/src/backend/langflow/services/store/service.py @@ -199,8 +199,13 @@ class StoreService(Service): self.components_url, headers=headers, json=component_dict ) response.raise_for_status() - component = response.json()["data"] - return ComponentResponse(**component) + # ! If the user does not have permission to a certain field + # the request returns 204 and no data + try: + component = response.json()["data"] + return ComponentResponse(**component) + except json.JSONDecodeError: + return ComponentResponse(**component_dict) except HTTPError as exc: if response: try: From 6615bf3b0309db68ec8334d3ff7e74dbcf3068c0 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 26 Oct 2023 11:46:42 -0300 Subject: [PATCH 03/14] =?UTF-8?q?=F0=9F=94=A7=20fix(store.py):=20import=20?= =?UTF-8?q?UsersLikesResponse=20in=20store.py=20to=20resolve=20import=20er?= =?UTF-8?q?ror=20=E2=9C=A8=20feat(store.py):=20add=20new=20endpoint=20to?= =?UTF-8?q?=20get=20list=20of=20components=20liked=20by=20a=20user=20?= =?UTF-8?q?=F0=9F=94=A7=20fix(schema.py):=20add=20UsersLikesResponse=20sch?= =?UTF-8?q?ema=20to=20define=20the=20response=20structure=20for=20the=20ne?= =?UTF-8?q?w=20endpoint=20=F0=9F=94=A7=20fix(service.py):=20add=20get=5Fus?= =?UTF-8?q?er=5Flikes=20method=20to=20retrieve=20the=20list=20of=20compone?= =?UTF-8?q?nts=20liked=20by=20a=20user=20from=20the=20store=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/api/v1/store.py | 12 ++++++++++-- src/backend/langflow/services/store/schema.py | 5 +++++ src/backend/langflow/services/store/service.py | 8 ++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/backend/langflow/api/v1/store.py b/src/backend/langflow/api/v1/store.py index 141e38c38..dd97a9e33 100644 --- a/src/backend/langflow/api/v1/store.py +++ b/src/backend/langflow/api/v1/store.py @@ -12,6 +12,7 @@ from langflow.services.store.schema import ( ListComponentResponse, StoreComponentCreate, TagResponse, + UsersLikesResponse, ) from fastapi import APIRouter, Depends, HTTPException, Query @@ -173,5 +174,12 @@ def get_tags( raise HTTPException(status_code=500, detail=str(exc)) -# urlencodedstr = https://api.langflow.store/items/components?page=0&limit=10000&fields=id%2Cname%2Cdescription%2Cuser_created.name%2Cis_component%2Ctags.tags_id.name%2Ctags.tags_id.id%2Ccount%28liked_by%29&filter=%7B%22status%22%3A%20%7B%22_in%22%3A%20%5B%22public%22%2C%20%22Public%22%5D%7D%7D' -# normalstr = https://api.langflow.store/items/components?page=0&limit=10000&fields=id,name,description,user_created.name,is_component,tags.tags_id.name,tags.tags_id.id,count(liked_by)&filter={"status": {"_in": ["public", "Public"]}}' +@router.get("/users/likes", response_model=List[UsersLikesResponse]) +def get_list_of_components_liked_by_user( + store_service: StoreService = Depends(get_store_service), + store_api_Key: str = Depends(get_user_store_api_key), +): + try: + return store_service.get_user_likes(store_api_Key) + except Exception as exc: + raise HTTPException(status_code=500, detail=str(exc)) diff --git a/src/backend/langflow/services/store/schema.py b/src/backend/langflow/services/store/schema.py index 259d341b2..339f55c9e 100644 --- a/src/backend/langflow/services/store/schema.py +++ b/src/backend/langflow/services/store/schema.py @@ -9,6 +9,11 @@ class TagResponse(BaseModel): name: Optional[str] +class UsersLikesResponse(BaseModel): + id: UUID + likes: Optional[List[UUID]] + + class ComponentResponse(BaseModel): id: UUID status: Optional[str] diff --git a/src/backend/langflow/services/store/service.py b/src/backend/langflow/services/store/service.py index 8b0f5c53f..28c47f3b3 100644 --- a/src/backend/langflow/services/store/service.py +++ b/src/backend/langflow/services/store/service.py @@ -221,3 +221,11 @@ class StoreService(Service): params = {"fields": ",".join(["id", "name"])} tags = self._get(url, api_key, params) return tags + + def get_user_likes(self, api_key: str) -> List[Dict[str, Any]]: + url = f"{self.base_url}/users/me" + params = { + "fields": ",".join(["id", "likes"]), + } + likes = self._get(url, api_key, params) + return likes From 5a8ba5f0db11b977be816cc06b4d3be422037c86 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 26 Oct 2023 14:45:49 -0300 Subject: [PATCH 04/14] =?UTF-8?q?=F0=9F=90=9B=20fix(service.py):=20remove?= =?UTF-8?q?=20unnecessary=20try-except=20block=20and=20return=20statement?= =?UTF-8?q?=20to=20improve=20code=20readability=20and=20maintainability?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/services/store/service.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/backend/langflow/services/store/service.py b/src/backend/langflow/services/store/service.py index 28c47f3b3..ba676eed7 100644 --- a/src/backend/langflow/services/store/service.py +++ b/src/backend/langflow/services/store/service.py @@ -199,13 +199,8 @@ class StoreService(Service): self.components_url, headers=headers, json=component_dict ) response.raise_for_status() - # ! If the user does not have permission to a certain field - # the request returns 204 and no data - try: - component = response.json()["data"] - return ComponentResponse(**component) - except json.JSONDecodeError: - return ComponentResponse(**component_dict) + component = response.json()["data"] + return ComponentResponse(**component) except HTTPError as exc: if response: try: From 4e62f0222641fcbbc5c8dfc3620c599dcb300eac Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 26 Oct 2023 15:13:22 -0300 Subject: [PATCH 05/14] =?UTF-8?q?=F0=9F=90=9B=20fix(service.py):=20fix=20t?= =?UTF-8?q?ypo=20in=20params["filter"]=20assignment=20=E2=9C=A8=20feat(ser?= =?UTF-8?q?vice.py):=20add=20support=20for=20filtering=20by=20user=5Fcreat?= =?UTF-8?q?ed=20field=20and=20limit=20the=20results=20to=20100=20=E2=9C=A8?= =?UTF-8?q?=20feat(service.py):=20add=20support=20for=20fetching=20additio?= =?UTF-8?q?nal=20fields=20in=20the=20response=20for=20better=20data=20retr?= =?UTF-8?q?ieval?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../langflow/services/store/service.py | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/backend/langflow/services/store/service.py b/src/backend/langflow/services/store/service.py index ba676eed7..3bedcb63e 100644 --- a/src/backend/langflow/services/store/service.py +++ b/src/backend/langflow/services/store/service.py @@ -159,13 +159,22 @@ class StoreService(Service): # check for "public" or "Public" if filter_by_user: - params["deep"] = json.dumps( - { - "components": { - "_filter": {"user_created": {"token": {"_eq": api_key}}} - } - } + user_data = self._get( + f"{self.base_url}/users/me", api_key, params={"fields": "id"} ) + params["filter"] = json.dumps({"user_created": {"_eq": user_data["id"]}}) + params["limit"] = 100 + params["fields"] = [ + "id", + "name", + "description", + "user_created.first_name", + "user_created.id", + "is_component", + "tags.tags_id.name", + "tags.tags_id.id", + "count(liked_by)", + ] else: params["filter"] = params["filter"] = json.dumps( {"status": {"_in": ["public", "Public"]}} From 2427bda690e7e7e9d2f61cef91d733e7c7e19dc0 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 26 Oct 2023 15:19:11 -0300 Subject: [PATCH 06/14] =?UTF-8?q?=F0=9F=94=84=20refactor(schema.py):=20cha?= =?UTF-8?q?nge=20liked=5Fby=5Fcount=20type=20from=20List[UUID]=20to=20int?= =?UTF-8?q?=20for=20better=20consistency=20and=20readability?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/services/store/schema.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/langflow/services/store/schema.py b/src/backend/langflow/services/store/schema.py index 339f55c9e..6127eb8f7 100644 --- a/src/backend/langflow/services/store/schema.py +++ b/src/backend/langflow/services/store/schema.py @@ -27,7 +27,7 @@ class ComponentResponse(BaseModel): description: Optional[str] data: Optional[dict] tags: Optional[List[int]] - liked_by_count: Optional[List[UUID]] + liked_by_count: Optional[int] parent: Optional[UUID] From b3a8be547f8d71ad0edffe7e908ce9823f1cf3f2 Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Thu, 26 Oct 2023 15:13:21 -0300 Subject: [PATCH 07/14] fix(StorePage/index.tsx): handle error when fetching saved components and display error message feat(StorePage/index.tsx): add error handling for API key fetch and display error message --- src/frontend/package-lock.json | 24 +++++++++++----------- src/frontend/src/pages/StorePage/index.tsx | 12 +++++++++-- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/frontend/package-lock.json b/src/frontend/package-lock.json index 0bf66bdca..c17d7de6c 100644 --- a/src/frontend/package-lock.json +++ b/src/frontend/package-lock.json @@ -3796,9 +3796,9 @@ "integrity": "sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==" }, "node_modules/@types/react": { - "version": "18.2.32", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.32.tgz", - "integrity": "sha512-F0FVIZQ1x5Gxy/VYJb7XcWvCcHR28Sjwt1dXLspdIatfPq1MVACfnBDwKe6ANLxQ64riIJooXClpUR6oxTiepg==", + "version": "18.2.33", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.33.tgz", + "integrity": "sha512-v+I7S+hu3PIBoVkKGpSYYpiBT1ijqEzWpzQD62/jm4K74hPpSP7FF9BnKG6+fg2+62weJYkkBWDJlZt5JO/9hg==", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -5237,9 +5237,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.566", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.566.tgz", - "integrity": "sha512-mv+fAy27uOmTVlUULy15U3DVJ+jg+8iyKH1bpwboCRhtDC69GKf1PPTZvEIhCyDr81RFqfxZJYrbgp933a1vtg==" + "version": "1.4.567", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.567.tgz", + "integrity": "sha512-8KR114CAYQ4/r5EIEsOmOMqQ9j0MRbJZR3aXD/KFA8RuKzyoUB4XrUCg+l8RUGqTVQgKNIgTpjaG8YHRPAbX2w==" }, "node_modules/emoji-regex": { "version": "8.0.0", @@ -13755,9 +13755,9 @@ "integrity": "sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==" }, "@types/react": { - "version": "18.2.32", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.32.tgz", - "integrity": "sha512-F0FVIZQ1x5Gxy/VYJb7XcWvCcHR28Sjwt1dXLspdIatfPq1MVACfnBDwKe6ANLxQ64riIJooXClpUR6oxTiepg==", + "version": "18.2.33", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.33.tgz", + "integrity": "sha512-v+I7S+hu3PIBoVkKGpSYYpiBT1ijqEzWpzQD62/jm4K74hPpSP7FF9BnKG6+fg2+62weJYkkBWDJlZt5JO/9hg==", "requires": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -14768,9 +14768,9 @@ } }, "electron-to-chromium": { - "version": "1.4.566", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.566.tgz", - "integrity": "sha512-mv+fAy27uOmTVlUULy15U3DVJ+jg+8iyKH1bpwboCRhtDC69GKf1PPTZvEIhCyDr81RFqfxZJYrbgp933a1vtg==" + "version": "1.4.567", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.567.tgz", + "integrity": "sha512-8KR114CAYQ4/r5EIEsOmOMqQ9j0MRbJZR3aXD/KFA8RuKzyoUB4XrUCg+l8RUGqTVQgKNIgTpjaG8YHRPAbX2w==" }, "emoji-regex": { "version": "8.0.0", diff --git a/src/frontend/src/pages/StorePage/index.tsx b/src/frontend/src/pages/StorePage/index.tsx index 0fa3a5ed8..118498b73 100644 --- a/src/frontend/src/pages/StorePage/index.tsx +++ b/src/frontend/src/pages/StorePage/index.tsx @@ -58,7 +58,12 @@ export default function StorePage(): JSX.Element { } useEffect(() => { - getSavedComponents().then((_) => handleGetComponents()); + getSavedComponents() + .finally(() => handleGetComponents()) + .catch((err) => { + setErrorApiKey(true); + console.error(err); + }); }, []); const handleGetComponents = () => { @@ -108,7 +113,10 @@ export default function StorePage(): JSX.Element { handleGetComponents(); }} > - From d0f121e6623a66da35caf078c943e4a2bdd44c6e Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 26 Oct 2023 15:25:54 -0300 Subject: [PATCH 08/14] =?UTF-8?q?=F0=9F=94=A7=20fix(store.py):=20add=20"me?= =?UTF-8?q?tadata"=20field=20to=20the=20list=20of=20requested=20fields=20i?= =?UTF-8?q?n=20the=20list=5Fcomponents=20function=20to=20include=20metadat?= =?UTF-8?q?a=20in=20the=20response=20=F0=9F=94=A7=20fix(schema.py):=20add?= =?UTF-8?q?=20"metadata"=20field=20to=20the=20ComponentResponse,=20ListCom?= =?UTF-8?q?ponentResponse,=20DownloadComponentResponse,=20and=20StoreCompo?= =?UTF-8?q?nentCreate=20models=20to=20support=20metadata=20in=20the=20stor?= =?UTF-8?q?e=20component=20data=20=F0=9F=94=A7=20fix(service.py):=20add=20?= =?UTF-8?q?"metadata"=20field=20to=20the=20list=20of=20requested=20fields?= =?UTF-8?q?=20in=20the=20StoreService=20class=20to=20include=20metadata=20?= =?UTF-8?q?in=20the=20query=20parameters?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/api/v1/store.py | 1 + src/backend/langflow/services/store/schema.py | 4 ++++ src/backend/langflow/services/store/service.py | 1 + 3 files changed, 6 insertions(+) diff --git a/src/backend/langflow/api/v1/store.py b/src/backend/langflow/api/v1/store.py index dd97a9e33..e2632911f 100644 --- a/src/backend/langflow/api/v1/store.py +++ b/src/backend/langflow/api/v1/store.py @@ -83,6 +83,7 @@ def list_components( "tags.tags_id.name", "tags.tags_id.id", "count(liked_by)", + "metadata", ] result = store_service.query_components( store_api_Key, diff --git a/src/backend/langflow/services/store/schema.py b/src/backend/langflow/services/store/schema.py index 6127eb8f7..ceef1c9a3 100644 --- a/src/backend/langflow/services/store/schema.py +++ b/src/backend/langflow/services/store/schema.py @@ -29,6 +29,7 @@ class ComponentResponse(BaseModel): tags: Optional[List[int]] liked_by_count: Optional[int] parent: Optional[UUID] + metadata: Optional[dict] class ListComponentResponse(BaseModel): @@ -37,6 +38,7 @@ class ListComponentResponse(BaseModel): description: Optional[str] liked_by_count: Optional[int] is_component: Optional[bool] + metadata: Optional[dict] class DownloadComponentResponse(BaseModel): @@ -45,6 +47,7 @@ class DownloadComponentResponse(BaseModel): description: Optional[str] data: Optional[dict] is_component: Optional[bool] + metadata: Optional[dict] class StoreComponentCreate(BaseModel): @@ -54,3 +57,4 @@ class StoreComponentCreate(BaseModel): tags: Optional[List[str]] parent: Optional[UUID] is_component: Optional[bool] + metadata: Optional[dict] diff --git a/src/backend/langflow/services/store/service.py b/src/backend/langflow/services/store/service.py index 3bedcb63e..e71f1def1 100644 --- a/src/backend/langflow/services/store/service.py +++ b/src/backend/langflow/services/store/service.py @@ -174,6 +174,7 @@ class StoreService(Service): "tags.tags_id.name", "tags.tags_id.id", "count(liked_by)", + "metadata", ] else: params["filter"] = params["filter"] = json.dumps( From 654a1de6c6fbc8257e5ab2efff4265c0347a043a Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 26 Oct 2023 15:48:42 -0300 Subject: [PATCH 09/14] =?UTF-8?q?=F0=9F=94=A7=20fix(store.py):=20flatten?= =?UTF-8?q?=20the=20tags=20in=20the=20list=5Fcomponents=20response=20to=20?= =?UTF-8?q?match=20the=20schema=20=F0=9F=94=A7=20fix(store.py):=20add=20us?= =?UTF-8?q?er=5Fcreated.id=20field=20to=20the=20list=5Fcomponents=20respon?= =?UTF-8?q?se=20to=20match=20the=20schema=20=F0=9F=94=A7=20fix(store.py):?= =?UTF-8?q?=20add=20count(downloads)=20field=20to=20the=20list=5Fcomponent?= =?UTF-8?q?s=20response=20to=20match=20the=20schema=20=F0=9F=94=A7=20fix(s?= =?UTF-8?q?tore.py):=20add=20tags=5Fid=20field=20to=20the=20TagsIdResponse?= =?UTF-8?q?=20schema=20to=20match=20the=20response=20structure=20?= =?UTF-8?q?=F0=9F=94=A7=20fix(service.py):=20add=20user=5Fcreated.first=5F?= =?UTF-8?q?name=20and=20user=5Fcreated.id=20fields=20to=20the=20list=5Fcom?= =?UTF-8?q?ponents=20query=20to=20match=20the=20schema=20=F0=9F=94=A7=20fi?= =?UTF-8?q?x(service.py):=20add=20count(downloads)=20field=20to=20the=20li?= =?UTF-8?q?st=5Fcomponents=20query=20to=20match=20the=20schema?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/api/v1/store.py | 5 ++++ src/backend/langflow/services/store/schema.py | 6 +++++ .../langflow/services/store/service.py | 24 +++++++++++++++++-- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/backend/langflow/api/v1/store.py b/src/backend/langflow/api/v1/store.py index e2632911f..47f377058 100644 --- a/src/backend/langflow/api/v1/store.py +++ b/src/backend/langflow/api/v1/store.py @@ -79,10 +79,12 @@ def list_components( "name", "description", "user_created.first_name", + "user_created.id", "is_component", "tags.tags_id.name", "tags.tags_id.id", "count(liked_by)", + "count(downloads)", "metadata", ] result = store_service.query_components( @@ -92,6 +94,9 @@ def list_components( fields=fields, filter_by_user=filter_by_user, ) + # tags comes as "tags" : [{"tags_id": {"name": "tag1", "id": 1}}] + # so we need to flatten it + return result except Exception as exc: raise HTTPException(status_code=400, detail=str(exc)) diff --git a/src/backend/langflow/services/store/schema.py b/src/backend/langflow/services/store/schema.py index ceef1c9a3..1b4e82d54 100644 --- a/src/backend/langflow/services/store/schema.py +++ b/src/backend/langflow/services/store/schema.py @@ -32,6 +32,10 @@ class ComponentResponse(BaseModel): metadata: Optional[dict] +class TagsIdResponse(BaseModel): + tags_id: Optional[TagResponse] + + class ListComponentResponse(BaseModel): id: UUID name: Optional[str] @@ -39,6 +43,8 @@ class ListComponentResponse(BaseModel): liked_by_count: Optional[int] is_component: Optional[bool] metadata: Optional[dict] + user_created: Optional[dict] + tags: Optional[List[TagsIdResponse]] = None class DownloadComponentResponse(BaseModel): diff --git a/src/backend/langflow/services/store/service.py b/src/backend/langflow/services/store/service.py index e71f1def1..22d93057b 100644 --- a/src/backend/langflow/services/store/service.py +++ b/src/backend/langflow/services/store/service.py @@ -1,6 +1,7 @@ from datetime import datetime import json from uuid import UUID +from bs4 import Tag from langflow.services.base import Service from typing import TYPE_CHECKING, List, Dict, Any, Optional, Union import httpx @@ -11,6 +12,7 @@ from langflow.services.store.schema import ( DownloadComponentResponse, ListComponentResponse, StoreComponentCreate, + TagResponse, ) if TYPE_CHECKING: @@ -152,7 +154,19 @@ class StoreService(Service): ",".join(fields) if fields else ",".join( - ["id", "name", "description", "count(liked_by)", "is_component"] + [ + "id", + "name", + "description", + "user_created.first_name", + "user_created.id", + "is_component", + "tags.tags_id.name", + "tags.tags_id.id", + "count(liked_by)", + "count(downloads)", + "metadata", + ] ) ) # Only public components or the ones created by the user @@ -174,6 +188,7 @@ class StoreService(Service): "tags.tags_id.name", "tags.tags_id.id", "count(liked_by)", + "count(downloads)", "metadata", ] else: @@ -182,7 +197,12 @@ class StoreService(Service): ) results = self._get(self.components_url, api_key, params) - return [ListComponentResponse(**component) for component in results] + results_objects = [ListComponentResponse(**component) for component in results] + # Flatten the tags + for component in results_objects: + if component.tags: + component.tags = [tags_id.tags_id for tags_id in component.tags] + return results_objects def download(self, api_key: str, component_id: str) -> DownloadComponentResponse: url = f"{self.components_url}/{component_id}" From 5a54fa74fe61f4ff7f8bbb4b60abbf2f98c585a3 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 26 Oct 2023 15:50:15 -0300 Subject: [PATCH 10/14] =?UTF-8?q?=F0=9F=94=A7=20fix(schema.py):=20add=20'd?= =?UTF-8?q?ownloads=5Fcount'=20field=20to=20ComponentResponse,=20ListCompo?= =?UTF-8?q?nentResponse,=20and=20DownloadComponentResponse=20models=20to?= =?UTF-8?q?=20track=20the=20number=20of=20downloads=20for=20each=20compone?= =?UTF-8?q?nt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/services/store/schema.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/backend/langflow/services/store/schema.py b/src/backend/langflow/services/store/schema.py index 1b4e82d54..215b15b91 100644 --- a/src/backend/langflow/services/store/schema.py +++ b/src/backend/langflow/services/store/schema.py @@ -28,6 +28,7 @@ class ComponentResponse(BaseModel): data: Optional[dict] tags: Optional[List[int]] liked_by_count: Optional[int] + downloads_count: Optional[int] parent: Optional[UUID] metadata: Optional[dict] @@ -45,6 +46,7 @@ class ListComponentResponse(BaseModel): metadata: Optional[dict] user_created: Optional[dict] tags: Optional[List[TagsIdResponse]] = None + downloads_count: Optional[int] class DownloadComponentResponse(BaseModel): @@ -54,6 +56,7 @@ class DownloadComponentResponse(BaseModel): data: Optional[dict] is_component: Optional[bool] metadata: Optional[dict] + downloads_count: Optional[int] class StoreComponentCreate(BaseModel): From 44b90b36d7aea206b653c122b28fd1edca857b41 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 26 Oct 2023 15:53:24 -0300 Subject: [PATCH 11/14] =?UTF-8?q?=F0=9F=90=9B=20fix(service.py):=20remove?= =?UTF-8?q?=20unnecessary=20fields=20from=20params=20to=20improve=20perfor?= =?UTF-8?q?mance=20and=20reduce=20payload=20size=20=E2=9C=A8=20feat(servic?= =?UTF-8?q?e.py):=20remove=20page=20and=20limit=20params=20to=20retrieve?= =?UTF-8?q?=20all=20results=20instead=20of=20a=20limited=20number=20of=20r?= =?UTF-8?q?esults?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../langflow/services/store/service.py | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/backend/langflow/services/store/service.py b/src/backend/langflow/services/store/service.py index 22d93057b..89e10f4b4 100644 --- a/src/backend/langflow/services/store/service.py +++ b/src/backend/langflow/services/store/service.py @@ -177,20 +177,11 @@ class StoreService(Service): f"{self.base_url}/users/me", api_key, params={"fields": "id"} ) params["filter"] = json.dumps({"user_created": {"_eq": user_data["id"]}}) - params["limit"] = 100 - params["fields"] = [ - "id", - "name", - "description", - "user_created.first_name", - "user_created.id", - "is_component", - "tags.tags_id.name", - "tags.tags_id.id", - "count(liked_by)", - "count(downloads)", - "metadata", - ] + # Get the + params.pop("page", None) + params.pop("limit", None) + + params["fields"] = ["id"] else: params["filter"] = params["filter"] = json.dumps( {"status": {"_in": ["public", "Public"]}} From 4775cd1d95030b9c9308453dd616b1aeca592094 Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Thu, 26 Oct 2023 16:26:25 -0300 Subject: [PATCH 12/14] fix(market-card.tsx): fix import statement for storeComponent type feat(market-card.tsx): add ShadTooltip component for displaying tooltips on market card fix(index.tsx): fix import statement for storeComponent type feat(index.tsx): change data and dataSelect state types to storeComponent[] fix(index.tsx): add missing properties to storeComponent type fix(styleUtils.ts): add missing import statement for Heart and ToyBrick icons --- .../StorePage/components/market-card.tsx | 33 ++++++++++++++----- src/frontend/src/pages/StorePage/index.tsx | 6 ++-- src/frontend/src/types/store/index.ts | 13 +++----- src/frontend/src/utils/styleUtils.ts | 5 +++ 4 files changed, 38 insertions(+), 19 deletions(-) diff --git a/src/frontend/src/pages/StorePage/components/market-card.tsx b/src/frontend/src/pages/StorePage/components/market-card.tsx index 87b73a28c..5a8927af2 100644 --- a/src/frontend/src/pages/StorePage/components/market-card.tsx +++ b/src/frontend/src/pages/StorePage/components/market-card.tsx @@ -1,5 +1,5 @@ -import { Link, ToyBrick } from "lucide-react"; import { useContext, useEffect, useRef, useState } from "react"; +import ShadTooltip from "../../../components/ShadTooltipComponent"; import IconComponent from "../../../components/genericIconComponent"; import { Badge } from "../../../components/ui/badge"; import { Button } from "../../../components/ui/button"; @@ -15,10 +15,10 @@ import { StoreContext } from "../../../contexts/storeContext"; import { TabsContext } from "../../../contexts/tabsContext"; import { getComponent, saveFlowStore } from "../../../controllers/API"; import { FlowType } from "../../../types/flow"; -import { FlowComponent } from "../../../types/store"; +import { storeComponent } from "../../../types/store"; import cloneFLowWithParent from "../../../utils/storeUtils"; -export const MarketCardComponent = ({ data }: { data: FlowComponent }) => { +export const MarketCardComponent = ({ data }: { data: storeComponent }) => { const { savedFlows } = useContext(StoreContext); const [added, setAdded] = useState(savedFlows.has(data.id) ? true : false); const [loading, setLoading] = useState(false); @@ -143,12 +143,29 @@ export const MarketCardComponent = ({ data }: { data: FlowComponent }) => {
chain - + - - - 123 - + + + + 123 + + + + + + {data.liked_by_count ?? 0} + + + + + + {data.downloads_count} + +
{/* {data.isChat ? (