Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WEB-2937] feat: home recent activies list endpoint #6295

Merged
merged 18 commits into from
Jan 3, 2025
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion apiserver/plane/app/serializers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
WorkspaceMemberAdminSerializer,
WorkspaceMemberMeSerializer,
WorkspaceUserPropertiesSerializer,
WorkspaceUserLinkSerializer
WorkspaceUserLinkSerializer,
WorkspaceRecentVisitSerializer
)
from .project import (
ProjectSerializer,
Expand Down
1 change: 0 additions & 1 deletion apiserver/plane/app/serializers/favorite.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ def get_entity_model_and_serializer(entity_type):
}
return entity_map.get(entity_type, (None, None))


class UserFavoriteSerializer(serializers.ModelSerializer):
entity_data = serializers.SerializerMethodField()

Expand Down
95 changes: 94 additions & 1 deletion apiserver/plane/app/serializers/workspace.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
# Third party imports
from rest_framework import serializers
from rest_framework import status
from rest_framework.response import Response

# Module imports
from .base import BaseSerializer, DynamicBaseSerializer
from .user import UserLiteSerializer, UserAdminLiteSerializer


from plane.db.models import (
Workspace,
WorkspaceMember,
WorkspaceMemberInvite,
WorkspaceTheme,
WorkspaceUserProperties,
WorkspaceUserLink
WorkspaceUserLink,
UserRecentVisit,
Issue,
Page,
Project,
ProjectMember
)
from plane.utils.constants import RESTRICTED_WORKSPACE_SLUGS

Expand Down Expand Up @@ -132,3 +140,88 @@ def validate_url(self, value):
raise serializers.ValidationError({"error": "Invalid URL format."})

return value

class IssueRecentVisitSerializer(serializers.ModelSerializer):
project_identifier = serializers.SerializerMethodField()

class Meta:
model = Issue
fields = ["name", "state", "priority", "assignees", "type", "sequence_id", "project_id", "project_identifier"]

def get_project_identifier(self, obj):
project = obj.project

return project.identifier if project else None

class ProjectMemberSerializer(BaseSerializer):
member = UserLiteSerializer(read_only=True)

class Meta:
model = ProjectMember
fields = ["member"]

class ProjectRecentVisitSerializer(serializers.ModelSerializer):
project_members = serializers.SerializerMethodField()

class Meta:
model = Project
fields = ["id", "name", "logo_props", "project_members", "identifier"]

def get_project_members(self, obj):
members = ProjectMember.objects.filter(project_id=obj.id).select_related('member')

serializer = ProjectMemberSerializer(members, many=True)
return serializer.data

class PageRecentVisitSerializer(serializers.ModelSerializer):
project_id = serializers.SerializerMethodField()
project_identifier = serializers.SerializerMethodField()

class Meta:
model = Page
fields = ["id", "name", "logo_props", "project_id", "owned_by", "project_identifier"]

def get_project_id(self, obj):
return obj.project_id if hasattr(obj, 'project_id') else obj.projects.values_list('id', flat=True).first()

def get_project_identifier(self, obj):
project = obj.projects.first()

return project.identifier if project else None

def get_entity_model_and_serializer(entity_type):
entity_map = {
"issue": (Issue, IssueRecentVisitSerializer),
"page": (Page, PageRecentVisitSerializer),
"project": (Project, ProjectRecentVisitSerializer)
}
return entity_map.get(entity_type, (None, None))

class WorkspaceRecentVisitSerializer(BaseSerializer):
entity_data = serializers.SerializerMethodField()

class Meta:
model = UserRecentVisit
fields = [
"id",
"entity_name",
"entity_identifier",
"entity_data",
"visited_at"
]
read_only_fields = ["workspace", "owner", "created_by", "updated_by"]

def get_entity_data(self, obj):
entity_name = obj.entity_name
entity_identifier = obj.entity_identifier

entity_model, entity_serializer = get_entity_model_and_serializer(entity_name)

if entity_model and entity_serializer:
try:
entity = entity_model.objects.get(pk=entity_identifier)

return entity_serializer(entity).data
except entity_model.DoesNotExist:
return None
return None
16 changes: 13 additions & 3 deletions apiserver/plane/app/urls/workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
WorkspaceFavoriteEndpoint,
WorkspaceFavoriteGroupEndpoint,
WorkspaceDraftIssueViewSet,
QuickLinkViewSet
QuickLinkViewSet,
UserRecentVisitViewSet
)


Expand Down Expand Up @@ -219,11 +220,20 @@
path(
"workspaces/<str:slug>/quick-links/",
QuickLinkViewSet.as_view({"get": "list", "post": "create"}),
name="workspace-quick-links "
name="workspace-quick-links"
),
path(
"workspaces/<str:slug>/quick-links/<uuid:pk>/",
QuickLinkViewSet.as_view({"get": "retrieve", "patch": "partial_update", "delete": "destroy"}),
QuickLinkViewSet.as_view({
"get": "retrieve",
"patch": "partial_update",
"delete": "destroy"
}),
name="workspace-quick-links"
),
path(
"workspaces/<str:slug>/recent-visits/",
UserRecentVisitViewSet.as_view({"get": "list"}),
name="workspace-recent-visits"
)
sangeethailango marked this conversation as resolved.
Show resolved Hide resolved
]
1 change: 1 addition & 0 deletions apiserver/plane/app/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
WorkspaceFavoriteEndpoint,
WorkspaceFavoriteGroupEndpoint,
)
from .workspace.recent_visit import UserRecentVisitViewSet

from .workspace.member import (
WorkSpaceMemberViewSet,
Expand Down
31 changes: 31 additions & 0 deletions apiserver/plane/app/views/workspace/recent_visit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Third party imports
from rest_framework import status
from rest_framework.response import Response

from plane.db.models import UserRecentVisit
from plane.app.serializers import WorkspaceRecentVisitSerializer

# Modules imports
from ..base import BaseViewSet
from plane.app.permissions import allow_permission, ROLE

class UserRecentVisitViewSet(BaseViewSet):
model = UserRecentVisit

def get_serializer_class(self):
return WorkspaceRecentVisitSerializer

@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST], level="WORKSPACE")
def list(self, request, slug):
user_recent_visits = UserRecentVisit.objects.filter(workspace__slug=slug)
sangeethailango marked this conversation as resolved.
Show resolved Hide resolved

entity_name = request.query_params.get("entity_name")

if entity_name:
user_recent_visits = user_recent_visits.filter(entity_name=entity_name)[:10]

user_recent_visits = user_recent_visits[:10]

serializer = WorkspaceRecentVisitSerializer(user_recent_visits, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)

Loading