diff --git a/apiserver/plane/graphql/bgtasks/recent_visited_task.py b/apiserver/plane/graphql/bgtasks/recent_visited_task.py new file mode 100644 index 0000000000..0f84ad3d38 --- /dev/null +++ b/apiserver/plane/graphql/bgtasks/recent_visited_task.py @@ -0,0 +1,64 @@ +# Python imports +from django.utils import timezone + +# Third party imports +from celery import shared_task + +# Module imports +from plane.db.models import UserRecentVisit, Workspace +from plane.utils.exception_logger import log_exception + + +@shared_task +def recent_visited_task( + slug, + project_id, + user_id, + entity_name, + entity_identifier, +): + try: + workspace = Workspace.objects.get(slug=slug) + recent_visited = UserRecentVisit.objects.filter( + entity_name=entity_name, + entity_identifier=entity_identifier, + user_id=user_id, + project_id=project_id, + workspace_id=workspace.id, + ).first() + + if recent_visited: + recent_visited.visited_at = timezone.now() + recent_visited.save(update_fields=["visited_at"]) + else: + recent_visited_count = UserRecentVisit.objects.filter( + user_id=user_id, workspace_id=workspace.id + ).count() + if recent_visited_count == 20: + recent_visited = ( + UserRecentVisit.objects.filter( + user_id=user_id, workspace_id=workspace.id + ) + .order_by("created_at") + .first() + ) + recent_visited.delete() + + recent_activity = UserRecentVisit.objects.create( + entity_name=entity_name, + entity_identifier=entity_identifier, + user_id=user_id, + visited_at=timezone.now(), + project_id=project_id, + workspace_id=workspace.id, + ) + recent_activity.created_by_id = user_id + recent_activity.updated_by_id = user_id + recent_activity.save( + update_fields=["created_by_id", "updated_by_id"] + ) + + return + except Exception as e: + log_exception(e) + return diff --git a/apiserver/plane/graphql/queries/cycle.py b/apiserver/plane/graphql/queries/cycle.py index c8d9c522bc..a3a9c68cf4 100644 --- a/apiserver/plane/graphql/queries/cycle.py +++ b/apiserver/plane/graphql/queries/cycle.py @@ -29,6 +29,7 @@ from plane.graphql.types.paginator import PaginatorResponse from plane.graphql.utils.issue_filters import issue_filters from plane.graphql.utils.paginator import paginate from plane.graphql.utils.issue import issue_information_query_execute +from plane.graphql.bgtasks.recent_visited_task import recent_visited_task @strawberry.type @@ -81,6 +82,17 @@ class CycleQuery: project__project_projectmember__member=info.context.user, project__project_projectmember__is_active=True, ) + + # Background task to update recent visited project + user_id = info.context.user.id + recent_visited_task.delay( + slug=slug, + project_id=project, + user_id=user_id, + entity_name="cycle", + entity_identifier=cycle, + ) + return cycle diff --git a/apiserver/plane/graphql/queries/issue.py b/apiserver/plane/graphql/queries/issue.py index 87e796997d..5bbaa365c7 100644 --- a/apiserver/plane/graphql/queries/issue.py +++ b/apiserver/plane/graphql/queries/issue.py @@ -37,6 +37,7 @@ from plane.graphql.permissions.project import ProjectBasePermission from plane.graphql.types.paginator import PaginatorResponse from plane.graphql.utils.paginator import paginate from plane.graphql.utils.issue import issue_information_query_execute +from plane.graphql.bgtasks.recent_visited_task import recent_visited_task # issues information query @@ -111,6 +112,16 @@ class IssuesInformationQuery: ), ) + # Background task to update recent visited project + user_id = info.context.user.id + recent_visited_task.delay( + slug=slug, + project_id=project, + user_id=user_id, + entity_name="project", + entity_identifier=project, + ) + return issue_information @@ -171,6 +182,16 @@ class IssueQuery: project__project_projectmember__member=info.context.user, project__project_projectmember__is_active=True, ) + + # Background task to update recent visited project + user_id = info.context.user.id + recent_visited_task.delay( + slug=slug, + project_id=project, + user_id=user_id, + entity_name="issue", + entity_identifier=issue, + ) return issue diff --git a/apiserver/plane/graphql/queries/module.py b/apiserver/plane/graphql/queries/module.py index b75ff8ddf0..f72a72a115 100644 --- a/apiserver/plane/graphql/queries/module.py +++ b/apiserver/plane/graphql/queries/module.py @@ -25,6 +25,7 @@ from plane.graphql.types.paginator import PaginatorResponse from plane.graphql.utils.issue_filters import issue_filters from plane.graphql.utils.paginator import paginate from plane.graphql.utils.issue import issue_information_query_execute +from plane.graphql.bgtasks.recent_visited_task import recent_visited_task @strawberry.type @@ -67,6 +68,17 @@ class ModuleQuery: project__project_projectmember__member=info.context.user, project__project_projectmember__is_active=True, ) + + # Background task to update recent visited project + user_id = info.context.user.id + recent_visited_task.delay( + slug=slug, + project_id=project, + user_id=user_id, + entity_name="module", + entity_identifier=module, + ) + return module @strawberry.field( diff --git a/apiserver/plane/graphql/queries/page.py b/apiserver/plane/graphql/queries/page.py index e9a7f6c868..5d1ad5454f 100644 --- a/apiserver/plane/graphql/queries/page.py +++ b/apiserver/plane/graphql/queries/page.py @@ -18,12 +18,15 @@ from plane.db.models import UserFavorite, Page from plane.graphql.permissions.workspace import WorkspaceBasePermission from plane.graphql.types.paginator import PaginatorResponse from plane.graphql.utils.paginator import paginate +from plane.graphql.bgtasks.recent_visited_task import recent_visited_task @strawberry.type class UserPageQuery: @strawberry.field( - extensions=[PermissionExtension(permissions=[WorkspaceBasePermission()])] + extensions=[ + PermissionExtension(permissions=[WorkspaceBasePermission()]) + ] ) async def userPages( self, @@ -56,7 +59,6 @@ class UserPageQuery: @strawberry.type class PageQuery: - @strawberry.field( extensions=[ PermissionExtension(permissions=[WorkspaceBasePermission()]) @@ -133,4 +135,14 @@ class PageQuery: # Fetch the page asynchronously page_result = await sync_to_async(query.get, thread_sensitive=True)() + # Background task to update recent visited project + user_id = info.context.user.id + recent_visited_task.delay( + slug=slug, + project_id=project, + user_id=user_id, + entity_name="page", + entity_identifier=page, + ) + return page_result diff --git a/apiserver/plane/graphql/queries/project.py b/apiserver/plane/graphql/queries/project.py index 35d323745f..7c05f1b27c 100644 --- a/apiserver/plane/graphql/queries/project.py +++ b/apiserver/plane/graphql/queries/project.py @@ -17,6 +17,7 @@ from plane.graphql.permissions.workspace import WorkspaceBasePermission from plane.graphql.permissions.project import ProjectBasePermission from plane.graphql.types.paginator import PaginatorResponse from plane.graphql.utils.paginator import paginate +from plane.graphql.bgtasks.recent_visited_task import recent_visited_task @strawberry.type @@ -113,6 +114,17 @@ class ProjectQuery: ) project = await sync_to_async(get_project)() + + # Background task to update recent visited project + user_id = info.context.user.id + recent_visited_task.delay( + slug=slug, + project_id=project, + user_id=user_id, + entity_name="project", + entity_identifier=project, + ) + return project diff --git a/apiserver/plane/graphql/queries/users.py b/apiserver/plane/graphql/queries/users.py index 07f72c18ac..c956f5c171 100644 --- a/apiserver/plane/graphql/queries/users.py +++ b/apiserver/plane/graphql/queries/users.py @@ -103,7 +103,7 @@ class UserRecentVisitQuery: recent_visits = await sync_to_async(list)( UserRecentVisit.objects.filter( workspace__slug=slug, user=info.context.user - ).order_by("-created_at") + ).order_by("-visited_at") ) if limit: