[WEB-2625] chore: workspace favorite and draft improvement (#5855)
* chore: favorite empty state updated * chore: added draft issue count in workspace members * chore: workspace draft count improvement --------- Co-authored-by: NarayanBavisetti <narayan3119@gmail.com>
This commit is contained in:
parent
d552913171
commit
a7b58e4a93
6 changed files with 55 additions and 10 deletions
|
|
@ -65,6 +65,7 @@ class WorkSpaceMemberSerializer(DynamicBaseSerializer):
|
|||
|
||||
|
||||
class WorkspaceMemberMeSerializer(BaseSerializer):
|
||||
draft_issue_count = serializers.IntegerField(read_only=True)
|
||||
class Meta:
|
||||
model = WorkspaceMember
|
||||
fields = "__all__"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,11 @@ from django.db.models import (
|
|||
CharField,
|
||||
Count,
|
||||
Q,
|
||||
OuterRef,
|
||||
Subquery,
|
||||
IntegerField,
|
||||
)
|
||||
from django.db.models.functions import Coalesce
|
||||
from django.db.models.functions import Cast
|
||||
|
||||
# Third party modules
|
||||
|
|
@ -34,6 +38,7 @@ from plane.db.models import (
|
|||
User,
|
||||
Workspace,
|
||||
WorkspaceMember,
|
||||
DraftIssue,
|
||||
)
|
||||
from plane.utils.cache import cache_response, invalidate_cache
|
||||
|
||||
|
|
@ -283,10 +288,26 @@ class WorkspaceMemberUserViewsEndpoint(BaseAPIView):
|
|||
|
||||
class WorkspaceMemberUserEndpoint(BaseAPIView):
|
||||
def get(self, request, slug):
|
||||
workspace_member = WorkspaceMember.objects.get(
|
||||
member=request.user,
|
||||
workspace__slug=slug,
|
||||
is_active=True,
|
||||
draft_issue_count = (
|
||||
DraftIssue.objects.filter(
|
||||
created_by=request.user,
|
||||
workspace_id=OuterRef("workspace_id"),
|
||||
)
|
||||
.values("workspace_id")
|
||||
.annotate(count=Count("id"))
|
||||
.values("count")
|
||||
)
|
||||
|
||||
workspace_member = (
|
||||
WorkspaceMember.objects.filter(
|
||||
member=request.user, workspace__slug=slug, is_active=True
|
||||
)
|
||||
.annotate(
|
||||
draft_issue_count=Coalesce(
|
||||
Subquery(draft_issue_count, output_field=IntegerField()), 0
|
||||
)
|
||||
)
|
||||
.first()
|
||||
)
|
||||
serializer = WorkspaceMemberMeSerializer(workspace_member)
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
|
|
|
|||
1
packages/types/src/workspace.d.ts
vendored
1
packages/types/src/workspace.d.ts
vendored
|
|
@ -91,6 +91,7 @@ export interface IWorkspaceMemberMe {
|
|||
updated_by: string;
|
||||
view_props: IWorkspaceViewProps;
|
||||
workspace: string;
|
||||
draft_issue_count: number;
|
||||
}
|
||||
|
||||
export interface ILastActiveWorkspaceDetails {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { FC, useEffect, useRef } from "react";
|
||||
import isEmpty from "lodash/isEmpty";
|
||||
import { observer } from "mobx-react";
|
||||
// plane helpers
|
||||
import { useOutsideClickDetector } from "@plane/helpers";
|
||||
|
|
@ -16,8 +17,9 @@ import { SidebarFavoritesMenu } from "@/components/workspace/sidebar/favorites/f
|
|||
import { cn } from "@/helpers/common.helper";
|
||||
// hooks
|
||||
import { useAppTheme, useUserPermissions } from "@/hooks/store";
|
||||
// plane web components
|
||||
import { useFavorite } from "@/hooks/store/use-favorite";
|
||||
import useSize from "@/hooks/use-window-size";
|
||||
// plane web components
|
||||
import { SidebarAppSwitcher } from "@/plane-web/components/sidebar";
|
||||
import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/user-permissions";
|
||||
|
||||
|
|
@ -25,6 +27,7 @@ export const AppSidebar: FC = observer(() => {
|
|||
// store hooks
|
||||
const { allowPermissions } = useUserPermissions();
|
||||
const { toggleSidebar, sidebarCollapsed } = useAppTheme();
|
||||
const { groupedFavorites } = useFavorite();
|
||||
const windowSize = useSize();
|
||||
// refs
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
|
|
@ -48,6 +51,8 @@ export const AppSidebar: FC = observer(() => {
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [windowSize]);
|
||||
|
||||
const isFavoriteEmpty = isEmpty(groupedFavorites);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
|
|
@ -91,7 +96,7 @@ export const AppSidebar: FC = observer(() => {
|
|||
"opacity-0": !sidebarCollapsed,
|
||||
})}
|
||||
/>
|
||||
{canPerformWorkspaceMemberActions && <SidebarFavoritesMenu />}
|
||||
{canPerformWorkspaceMemberActions && !isFavoriteEmpty && <SidebarFavoritesMenu />}
|
||||
|
||||
<SidebarProjectsList />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ export const SidebarUserMenu = observer(() => {
|
|||
const { captureEvent } = useEventTracker();
|
||||
const { isMobile } = usePlatformOS();
|
||||
const { data: currentUser } = useUser();
|
||||
const { allowPermissions } = useUserPermissions();
|
||||
const { allowPermissions, workspaceUserInfo } = useUserPermissions();
|
||||
// router params
|
||||
const { workspaceSlug } = useParams();
|
||||
// pathname
|
||||
|
|
@ -50,14 +50,17 @@ export const SidebarUserMenu = observer(() => {
|
|||
/>
|
||||
);
|
||||
|
||||
const draftIssueCount = workspaceUserInfo[workspaceSlug.toString()]?.draft_issue_count;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn("flex flex-col gap-0.5", {
|
||||
"space-y-0": sidebarCollapsed,
|
||||
})}
|
||||
>
|
||||
{SIDEBAR_USER_MENU_ITEMS.map(
|
||||
(link) =>
|
||||
{SIDEBAR_USER_MENU_ITEMS.map((link) => {
|
||||
if (link.key === "drafts" && draftIssueCount === 0) return null;
|
||||
return (
|
||||
allowPermissions(link.access, EUserPermissionsLevel.WORKSPACE, workspaceSlug.toString()) && (
|
||||
<Tooltip
|
||||
key={link.key}
|
||||
|
|
@ -81,7 +84,8 @@ export const SidebarUserMenu = observer(() => {
|
|||
</Link>
|
||||
</Tooltip>
|
||||
)
|
||||
)}
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -139,6 +139,13 @@ export class WorkspaceDraftIssues implements IWorkspaceDraftIssues {
|
|||
});
|
||||
}
|
||||
|
||||
private updateWorkspaceUserDraftIssueCount(workspaceSlug: string, increment: number) {
|
||||
const workspaceUserInfo = this.issueStore.rootStore.user.permission.workspaceUserInfo;
|
||||
const currentCount = workspaceUserInfo[workspaceSlug]?.draft_issue_count ?? 0;
|
||||
|
||||
set(workspaceUserInfo, [workspaceSlug, "draft_issue_count"], currentCount + increment);
|
||||
}
|
||||
|
||||
// computed
|
||||
get issueIds() {
|
||||
const workspaceSlug = this.issueStore.workspaceSlug;
|
||||
|
|
@ -259,6 +266,8 @@ export class WorkspaceDraftIssues implements IWorkspaceDraftIssues {
|
|||
total_count: this.paginationInfo.total_count + 1,
|
||||
});
|
||||
}
|
||||
// Update draft issue count in workspaceUserInfo
|
||||
this.updateWorkspaceUserDraftIssueCount(workspaceSlug, 1);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -310,6 +319,8 @@ export class WorkspaceDraftIssues implements IWorkspaceDraftIssues {
|
|||
total_count: this.paginationInfo.total_count - 1,
|
||||
});
|
||||
}
|
||||
// Update draft issue count in workspaceUserInfo
|
||||
this.updateWorkspaceUserDraftIssueCount(workspaceSlug, -1);
|
||||
});
|
||||
|
||||
this.loader = undefined;
|
||||
|
|
@ -337,6 +348,8 @@ export class WorkspaceDraftIssues implements IWorkspaceDraftIssues {
|
|||
total_count: this.paginationInfo.total_count - 1,
|
||||
});
|
||||
}
|
||||
// Update draft issue count in workspaceUserInfo
|
||||
this.updateWorkspaceUserDraftIssueCount(workspaceSlug, -1);
|
||||
});
|
||||
|
||||
this.loader = undefined;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue