From 34edfdc22095bccfd85dc31632db7773da501f49 Mon Sep 17 00:00:00 2001 From: guru_sainath Date: Fri, 30 Aug 2024 18:00:45 +0530 Subject: [PATCH] [MOBIL-157] chore: updated global search (#996) * chore: updated module and cycle filter in the global search * chore: handled project lite details in pages object in global search * chore: code cleanup in global search --- apiserver/plane/graphql/queries/search.py | 104 ++++++++++++++-------- apiserver/plane/graphql/schema.py | 4 +- apiserver/plane/graphql/types/cycle.py | 7 ++ apiserver/plane/graphql/types/issue.py | 5 -- apiserver/plane/graphql/types/module.py | 7 ++ apiserver/plane/graphql/types/page.py | 7 +- apiserver/plane/graphql/types/project.py | 7 -- apiserver/plane/graphql/types/search.py | 7 +- 8 files changed, 92 insertions(+), 56 deletions(-) diff --git a/apiserver/plane/graphql/queries/search.py b/apiserver/plane/graphql/queries/search.py index d82ec1905f..fcff55b268 100644 --- a/apiserver/plane/graphql/queries/search.py +++ b/apiserver/plane/graphql/queries/search.py @@ -19,11 +19,13 @@ from django.contrib.postgres.aggregates import ArrayAgg from django.contrib.postgres.fields import ArrayField # Module Imports -from plane.graphql.types.search import ProjectSearchType -from plane.db.models import Issue, Project, Page +from plane.graphql.types.search import GlobalSearchType +from plane.db.models import Issue, Project, Page, Module, Cycle from plane.graphql.types.project import ProjectLiteType from plane.graphql.types.issue import IssueLiteType from plane.graphql.types.page import PageLiteType +from plane.graphql.types.module import ModuleLiteType +from plane.graphql.types.cycle import CycleLiteType from plane.graphql.permissions.workspace import WorkspaceBasePermission @@ -106,43 +108,60 @@ async def filter_pages(query: str, slug: str, user) -> list[PageLiteType]: projects__project_projectmember__is_active=True, projects__archived_at__isnull=True, workspace__slug=slug, - ) - .annotate( - project_ids=Coalesce( - ArrayAgg( - "projects__id", - distinct=True, - filter=~Q(projects__id=True), - ), - Value([], output_field=ArrayField(UUIDField())), - ), - ) - .annotate( - project_identifiers=Coalesce( - ArrayAgg( - "projects__identifier", - distinct=True, - filter=~Q(projects__id=True), - ), - Value([], output_field=ArrayField(CharField())), - ), - ) - .distinct() - .values( - "name", - "id", - "project_ids", - # "project_identifiers", - # "workspace__slug", - ) + ).distinct() ) )() - return [PageLiteType(**page) for page in pages] + return pages + + +async def filter_modules(query: str, slug: str, user) -> list[ModuleLiteType]: + fields = ["name"] + q = Q() + for field in fields: + q |= Q(**{f"{field}__icontains": query}) + + modules = await sync_to_async( + lambda: list( + Module.objects.filter( + q, + project__project_projectmember__member=user, + project__project_projectmember__is_active=True, + workspace__slug=slug, + archived_at__isnull=True, + ) + .distinct() + .values("id", "name", "project") + ) + )() + + return [ModuleLiteType(**module) for module in modules] + + +async def filter_cycles(query: str, slug: str, user) -> list[CycleLiteType]: + fields = ["name"] + q = Q() + for field in fields: + q |= Q(**{f"{field}__icontains": query}) + + cycles = await sync_to_async( + lambda: list( + Cycle.objects.filter( + q, + project__project_projectmember__member=user, + project__project_projectmember__is_active=True, + archived_at__isnull=True, + workspace__slug=slug, + ) + .distinct() + .values("id", "name", "project") + ) + )() + + return [CycleLiteType(**cycle) for cycle in cycles] @strawberry.type -class ProjectSearchQuery: - +class GlobalSearchQuery: @strawberry.field( extensions=[ PermissionExtension(permissions=[WorkspaceBasePermission()]) @@ -153,15 +172,22 @@ class ProjectSearchQuery: info: Info, slug: str, query: Optional[str] = None, - ) -> ProjectSearchType: - + ) -> GlobalSearchType: user = info.context.user if not query: - return ProjectSearchType(projects=[], issues=[]) + return GlobalSearchType(projects=[], issues=[]) projects = await filter_projects(query, slug, user) issues = await filter_issues(query, slug, user) pages = await filter_pages(query, slug, user) + modules = await filter_modules(query, slug, user) + cycles = await filter_cycles(query, slug, user) - # Return the ProjectSearchType with the list of ProjectLiteType objects - return ProjectSearchType(projects=projects, issues=issues, pages=pages) + # Return the GlobalSearchType with the list of ProjectLiteType objects + return GlobalSearchType( + projects=projects, + issues=issues, + pages=pages, + modules=modules, + cycles=cycles, + ) diff --git a/apiserver/plane/graphql/schema.py b/apiserver/plane/graphql/schema.py index 5142afece2..e8bbf17140 100644 --- a/apiserver/plane/graphql/schema.py +++ b/apiserver/plane/graphql/schema.py @@ -38,7 +38,7 @@ from .queries.module import ( ModuleIssueQuery, ModuleIssueUserPropertyQuery, ) -from .queries.search import ProjectSearchQuery +from .queries.search import GlobalSearchQuery from .queries.attachment import IssueAttachmentQuery from .queries.link import IssueLinkQuery from .queries.estimate import EstimatePointQuery @@ -94,7 +94,7 @@ class Query( PageQuery, WorkspaceLabelQuery, WorkspaceStateQuery, - ProjectSearchQuery, + GlobalSearchQuery, IssueAttachmentQuery, CycleQuery, CycleIssueQuery, diff --git a/apiserver/plane/graphql/types/cycle.py b/apiserver/plane/graphql/types/cycle.py index c5cd4b7691..fe025d9b53 100644 --- a/apiserver/plane/graphql/types/cycle.py +++ b/apiserver/plane/graphql/types/cycle.py @@ -85,6 +85,13 @@ class CycleType: return issue_assignees_count +@strawberry_django.type(Cycle) +class CycleLiteType: + id: strawberry.ID + name: str + project: strawberry.ID + + @strawberry_django.type(CycleUserProperties) class CycleUserPropertyType: display_filters: JSON diff --git a/apiserver/plane/graphql/types/issue.py b/apiserver/plane/graphql/types/issue.py index 0fe305dd9a..4b2b022b51 100644 --- a/apiserver/plane/graphql/types/issue.py +++ b/apiserver/plane/graphql/types/issue.py @@ -242,10 +242,6 @@ class IssueLiteType: def workspace(self) -> int: return self.workspace_id - # @strawberry.field - # def project(self) -> int: - # return self.project_id - @strawberry_django.type(IssueType) class IssueTypesType: @@ -258,7 +254,6 @@ class IssueTypesType: level: int is_active: bool - @strawberry.field def workspace(self) -> int: return self.workspace_id diff --git a/apiserver/plane/graphql/types/module.py b/apiserver/plane/graphql/types/module.py index 1ec6087449..6e6ee12127 100644 --- a/apiserver/plane/graphql/types/module.py +++ b/apiserver/plane/graphql/types/module.py @@ -87,6 +87,13 @@ class ModuleType: return issue_assignees_count +@strawberry_django.type(Module) +class ModuleLiteType: + id: strawberry.ID + name: str + project: strawberry.ID + + @strawberry_django.type(ModuleUserProperties) class ModuleUserPropertyType: display_filters: JSON diff --git a/apiserver/plane/graphql/types/page.py b/apiserver/plane/graphql/types/page.py index a6e67c75ee..e4d9438d8c 100644 --- a/apiserver/plane/graphql/types/page.py +++ b/apiserver/plane/graphql/types/page.py @@ -12,6 +12,7 @@ from strawberry.scalars import JSON # Module imports from plane.db.models import Page +from plane.graphql.types.project import ProjectLiteType @strawberry_django.type(Page) @@ -71,5 +72,7 @@ class PageType: class PageLiteType: id: strawberry.ID name: str - project_ids: list[strawberry.ID] - # owned_by: strawberry.ID + + @strawberry.field + def projects(self) -> list[ProjectLiteType]: + return self.projects.all() diff --git a/apiserver/plane/graphql/types/project.py b/apiserver/plane/graphql/types/project.py index 7f79762fe8..6271ab0ca4 100644 --- a/apiserver/plane/graphql/types/project.py +++ b/apiserver/plane/graphql/types/project.py @@ -118,10 +118,3 @@ class ProjectLiteType: id: strawberry.ID name: str identifier: str - # workspace: str - # is_member: bool - # is_favorite: bool - - # @strawberry.field - # def workspace(self) -> int: - # return self.workspace_id diff --git a/apiserver/plane/graphql/types/search.py b/apiserver/plane/graphql/types/search.py index 050d36f413..ff8abf247b 100644 --- a/apiserver/plane/graphql/types/search.py +++ b/apiserver/plane/graphql/types/search.py @@ -5,9 +5,14 @@ import strawberry from plane.graphql.types.project import ProjectLiteType from plane.graphql.types.issue import IssueLiteType from plane.graphql.types.page import PageLiteType +from plane.graphql.types.module import ModuleLiteType +from plane.graphql.types.cycle import CycleLiteType + @strawberry.type -class ProjectSearchType: +class GlobalSearchType: projects: list[ProjectLiteType] issues: list[IssueLiteType] pages: list[PageLiteType] + modules: list[ModuleLiteType] + cycles: list[CycleLiteType]