[WEB-3092] fix: fixed recents + removed home route (#6365)
* fix: fixed recents + removed home route * Return current users recents --------- Co-authored-by: sangeethailango <sangeethailango21@gmail.com>
This commit is contained in:
parent
448a34aa5f
commit
add35b5ea6
6 changed files with 81 additions and 119 deletions
|
|
@ -9,6 +9,7 @@ from plane.app.serializers import WorkspaceRecentVisitSerializer
|
|||
from ..base import BaseViewSet
|
||||
from plane.app.permissions import allow_permission, ROLE
|
||||
|
||||
|
||||
class UserRecentVisitViewSet(BaseViewSet):
|
||||
model = UserRecentVisit
|
||||
|
||||
|
|
@ -17,15 +18,18 @@ class UserRecentVisitViewSet(BaseViewSet):
|
|||
|
||||
@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST], level="WORKSPACE")
|
||||
def list(self, request, slug):
|
||||
user_recent_visits = UserRecentVisit.objects.filter(workspace__slug=slug)
|
||||
user_recent_visits = UserRecentVisit.objects.filter(
|
||||
workspace__slug=slug, user=request.user
|
||||
)
|
||||
|
||||
entity_name = request.query_params.get("entity_name")
|
||||
entity_name = request.query_params.get("entity_name")
|
||||
|
||||
if entity_name:
|
||||
user_recent_visits = user_recent_visits.filter(entity_name=entity_name)
|
||||
|
||||
user_recent_visits = user_recent_visits.filter(entity_name__in=["issue","page","project"])
|
||||
|
||||
serializer = WorkspaceRecentVisitSerializer(user_recent_visits[:20], many=True)
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
if entity_name:
|
||||
user_recent_visits = user_recent_visits.filter(entity_name=entity_name)
|
||||
|
||||
user_recent_visits = user_recent_visits.filter(
|
||||
entity_name__in=["issue", "page", "project"]
|
||||
)
|
||||
|
||||
serializer = WorkspaceRecentVisitSerializer(user_recent_visits[:20], many=True)
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
|
|
|
|||
|
|
@ -1,60 +0,0 @@
|
|||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import { useTheme } from "next-themes";
|
||||
import { Home } from "lucide-react";
|
||||
// images
|
||||
import githubBlackImage from "/public/logos/github-black.png";
|
||||
import githubWhiteImage from "/public/logos/github-white.png";
|
||||
// ui
|
||||
import { Breadcrumbs, Header } from "@plane/ui";
|
||||
// components
|
||||
import { BreadcrumbLink } from "@/components/common";
|
||||
// constants
|
||||
import { GITHUB_REDIRECTED } from "@/constants/event-tracker";
|
||||
// hooks
|
||||
import { useEventTracker } from "@/hooks/store";
|
||||
|
||||
export const WorkspaceDashboardHeader = () => {
|
||||
// hooks
|
||||
const { captureEvent } = useEventTracker();
|
||||
const { resolvedTheme } = useTheme();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Header>
|
||||
<Header.LeftItem>
|
||||
<div>
|
||||
<Breadcrumbs>
|
||||
<Breadcrumbs.BreadcrumbItem
|
||||
type="text"
|
||||
link={<BreadcrumbLink label="Home" icon={<Home className="h-4 w-4 text-custom-text-300" />} />}
|
||||
/>
|
||||
</Breadcrumbs>
|
||||
</div>
|
||||
</Header.LeftItem>
|
||||
<Header.RightItem>
|
||||
<a
|
||||
onClick={() =>
|
||||
captureEvent(GITHUB_REDIRECTED, {
|
||||
element: "navbar",
|
||||
})
|
||||
}
|
||||
className="flex flex-shrink-0 items-center gap-1.5 rounded bg-custom-background-80 px-3 py-1.5"
|
||||
href="https://github.com/makeplane/plane"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
src={resolvedTheme === "dark" ? githubWhiteImage : githubBlackImage}
|
||||
height={16}
|
||||
width={16}
|
||||
alt="GitHub Logo"
|
||||
/>
|
||||
<span className="hidden text-xs font-medium sm:hidden md:block">Star us on GitHub</span>
|
||||
</a>
|
||||
</Header.RightItem>
|
||||
</Header>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
"use client";
|
||||
|
||||
import { observer } from "mobx-react";
|
||||
// components
|
||||
import { PageHead, AppHeader, ContentWrapper } from "@/components/core";
|
||||
// hooks
|
||||
import { WorkspaceHomeView } from "@/components/home";
|
||||
import { useWorkspace } from "@/hooks/store";
|
||||
// local components
|
||||
import { WorkspaceDashboardHeader } from "../header";
|
||||
|
||||
const WorkspaceDashboardPage = observer(() => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
// derived values
|
||||
const pageTitle = currentWorkspace?.name ? `${currentWorkspace?.name} - Home` : undefined;
|
||||
|
||||
return (
|
||||
<>
|
||||
<AppHeader header={<WorkspaceDashboardHeader />} />
|
||||
<ContentWrapper>
|
||||
<PageHead title={pageTitle} />
|
||||
<WorkspaceHomeView />
|
||||
</ContentWrapper>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
export default WorkspaceDashboardPage;
|
||||
|
|
@ -23,9 +23,11 @@ export const ContentOverflowWrapper = observer((props: IContentOverflowWrapper)
|
|||
// states
|
||||
const [containerHeight, setContainerHeight] = useState(0);
|
||||
const [showAll, setShowAll] = useState(false);
|
||||
const [isTransitioning, setIsTransitioning] = useState(false);
|
||||
|
||||
// refs
|
||||
const contentRef = useRef<HTMLDivElement>(null);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!contentRef?.current) return;
|
||||
|
|
@ -70,37 +72,72 @@ export const ContentOverflowWrapper = observer((props: IContentOverflowWrapper)
|
|||
};
|
||||
}, [contentRef?.current]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!containerRef.current) return;
|
||||
|
||||
const handleTransitionEnd = () => {
|
||||
setIsTransitioning(false);
|
||||
};
|
||||
|
||||
containerRef.current.addEventListener("transitionend", handleTransitionEnd);
|
||||
|
||||
return () => {
|
||||
containerRef.current?.removeEventListener("transitionend", handleTransitionEnd);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleToggle = () => {
|
||||
setIsTransitioning(true);
|
||||
setShowAll((prev) => !prev);
|
||||
};
|
||||
|
||||
if (!children) return fallback;
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={containerRef}
|
||||
className={cn(
|
||||
"relative",
|
||||
{
|
||||
[`overflow-hidden`]: !showAll,
|
||||
"overflow-visible": showAll,
|
||||
[`overflow-hidden transition-[height] duration-300 ease-in-out`]: containerHeight > maxHeight,
|
||||
},
|
||||
containerClassName
|
||||
)}
|
||||
style={{ maxHeight: showAll ? "100%" : `${maxHeight}px` }}
|
||||
style={{
|
||||
height: showAll ? `${containerHeight}px` : `${Math.min(maxHeight, containerHeight)}px`,
|
||||
}}
|
||||
>
|
||||
<div ref={contentRef}>{children}</div>
|
||||
<div
|
||||
ref={contentRef}
|
||||
className={cn("h-auto", {
|
||||
"pb-6": showAll,
|
||||
})}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
|
||||
{containerHeight > maxHeight && (
|
||||
<div
|
||||
className={cn(
|
||||
"bottom-0 left-0 w-full",
|
||||
"bottom-0 left-0 w-full transition-all duration-300 ease-in-out",
|
||||
`bg-gradient-to-t from-custom-background-100 to-transparent flex flex-col items-center justify-end`,
|
||||
"text-center",
|
||||
{
|
||||
"absolute h-[100px]": !showAll,
|
||||
"h-[30px]": showAll,
|
||||
"absolute h-[100px] opacity-100": !showAll,
|
||||
"absolute h-[30px] opacity-70": showAll,
|
||||
}
|
||||
)}
|
||||
style={{
|
||||
pointerEvents: isTransitioning ? "none" : "auto",
|
||||
}}
|
||||
>
|
||||
<button
|
||||
className={cn("gap-1 w-full text-custom-primary-100 text-sm font-medium", buttonClassName)}
|
||||
onClick={() => setShowAll((prev) => !prev)}
|
||||
className={cn(
|
||||
"gap-1 w-full text-custom-primary-100 text-sm font-medium transition-opacity duration-300",
|
||||
buttonClassName
|
||||
)}
|
||||
onClick={handleToggle}
|
||||
disabled={isTransitioning}
|
||||
>
|
||||
{showAll ? "Show less" : "Show all"}
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -28,20 +28,21 @@ export const ProjectLinkList: FC<TProjectLinkList> = observer((props) => {
|
|||
if (links === undefined) return <WidgetLoader widgetKey={EWidgetKeys.QUICK_LINKS} />;
|
||||
|
||||
if (links.length === 0) return <LinksEmptyState handleCreate={() => toggleLinkModal(true)} />;
|
||||
|
||||
return (
|
||||
<ContentOverflowWrapper
|
||||
maxHeight={150}
|
||||
containerClassName="pb-2 box-border"
|
||||
fallback={<></>}
|
||||
buttonClassName="bg-custom-background-90/20"
|
||||
>
|
||||
<div>
|
||||
<div className="flex gap-2 mb-2 flex-wrap">
|
||||
<div className="relative">
|
||||
<ContentOverflowWrapper
|
||||
maxHeight={150}
|
||||
containerClassName="box-border min-h-[30px] flex flex-col"
|
||||
fallback={<></>}
|
||||
buttonClassName="bg-custom-background-90/20"
|
||||
>
|
||||
<div className="flex gap-2 mb-2 flex-wrap flex-1">
|
||||
{links &&
|
||||
links.length > 0 &&
|
||||
links.map((linkId) => <ProjectLinkDetail key={linkId} linkId={linkId} linkOperations={linkOperations} />)}
|
||||
</div>
|
||||
</div>
|
||||
</ContentOverflowWrapper>
|
||||
</ContentOverflowWrapper>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import { FiltersDropdown } from "./filters";
|
|||
import { RecentIssue } from "./issue";
|
||||
import { RecentPage } from "./page";
|
||||
import { RecentProject } from "./project";
|
||||
import { ContentOverflowWrapper } from "@/components/core/content-overflow-HOC";
|
||||
|
||||
const WIDGET_KEY = EWidgetKeys.RECENT_ACTIVITY;
|
||||
const workspaceService = new WorkspaceService();
|
||||
|
|
@ -79,7 +80,12 @@ export const RecentActivityWidget: React.FC<THomeWidgetProps> = observer((props)
|
|||
);
|
||||
|
||||
return (
|
||||
<div ref={ref} className=" max-h-[500px] min-h-[250px] overflow-y-scroll">
|
||||
<ContentOverflowWrapper
|
||||
maxHeight={415}
|
||||
containerClassName="box-border min-h-[250px]"
|
||||
fallback={<></>}
|
||||
buttonClassName="bg-custom-background-90/20"
|
||||
>
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<div className="text-base font-semibold text-custom-text-350">Recents</div>
|
||||
|
||||
|
|
@ -89,8 +95,10 @@ export const RecentActivityWidget: React.FC<THomeWidgetProps> = observer((props)
|
|||
{isLoading && <WidgetLoader widgetKey={WIDGET_KEY} />}
|
||||
{!isLoading &&
|
||||
recents?.length > 0 &&
|
||||
recents.map((activity: TActivityEntityData) => <div key={activity.id}>{resolveRecent(activity)}</div>)}
|
||||
recents
|
||||
.filter((recent: TActivityEntityData) => recent.entity_data)
|
||||
.map((activity: TActivityEntityData) => <div key={activity.id}>{resolveRecent(activity)}</div>)}
|
||||
</div>
|
||||
</div>
|
||||
</ContentOverflowWrapper>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue