refactor: recents widget for scalability (#6453)

Co-authored-by: pushya22 <130810100+pushya22@users.noreply.github.com>
This commit is contained in:
Aaryan Khandelwal
2025-01-24 15:34:28 +05:30
committed by GitHub
parent ee22dbba1b
commit c429ca7b36
3 changed files with 31 additions and 14 deletions

View File

@@ -1,7 +1,7 @@
import { TLogoProps } from "./common";
import { TIssuePriorities } from "./issues";
export type TRecentActivityFilterKeys = "all item" | "issue" | "page" | "project";
export type TRecentActivityFilterKeys = "all item" | "issue" | "page" | "project" | "workspace_page";
export type THomeWidgetKeys = "quick_links" | "recents" | "my_stickies" | "quick_tutorial" | "new_at_plane";
export type THomeWidgetProps = {
@@ -39,7 +39,7 @@ export type TIssueEntityData = {
export type TActivityEntityData = {
id: string;
entity_name: "page" | "project" | "issue";
entity_name: "page" | "project" | "issue" | "workspace_page";
entity_identifier: string;
visited_at: string;
entity_data: TPageEntityData | TProjectEntityData | TIssueEntityData;

View File

@@ -22,15 +22,21 @@ const WIDGET_KEY = EWidgetKeys.RECENT_ACTIVITY;
const workspaceService = new WorkspaceService();
const filters: { name: TRecentActivityFilterKeys; icon?: React.ReactNode }[] = [
{ name: "all item" },
{ name: "issue", icon: <LayersIcon className="w-4 h-4" /> },
{ name: "page", icon: <FileText size={16} /> },
{ name: "project", icon: <Briefcase size={16} /> },
{ name: "issue", icon: <LayersIcon className="flex-shrink-0 size-4" /> },
{ name: "page", icon: <FileText className="flex-shrink-0 size-4" /> },
{ name: "workspace_page", icon: <FileText className="flex-shrink-0 size-4" /> },
{ name: "project", icon: <Briefcase className="flex-shrink-0 size-4" /> },
];
export const RecentActivityWidget: React.FC<THomeWidgetProps> = observer((props) => {
const { workspaceSlug } = props;
type TRecentWidgetProps = THomeWidgetProps & {
presetFilter?: TRecentActivityFilterKeys;
showFilterSelect?: boolean;
};
export const RecentActivityWidget: React.FC<TRecentWidgetProps> = observer((props) => {
const { presetFilter, showFilterSelect = true, workspaceSlug } = props;
// state
const [filter, setFilter] = useState<TRecentActivityFilterKeys>(filters[0].name);
const [filter, setFilter] = useState<TRecentActivityFilterKeys>(presetFilter ?? filters[0].name);
// ref
const ref = useRef<HTMLDivElement>(null);
// store hooks
@@ -55,6 +61,7 @@ export const RecentActivityWidget: React.FC<THomeWidgetProps> = observer((props)
const resolveRecent = (activity: TActivityEntityData) => {
switch (activity.entity_name) {
case "page":
case "workspace_page":
return <RecentPage activity={activity} ref={ref} workspaceSlug={workspaceSlug} />;
case "project":
return <RecentProject activity={activity} ref={ref} workspaceSlug={workspaceSlug} />;
@@ -72,7 +79,7 @@ export const RecentActivityWidget: React.FC<THomeWidgetProps> = observer((props)
<div ref={ref} className="max-h-[500px] overflow-y-scroll">
<div className="flex items-center justify-between mb-4">
<div className="text-base font-semibold text-custom-text-350">Recents</div>
<FiltersDropdown filters={filters} activeFilter={filter} setActiveFilter={setFilter} />
{showFilterSelect && <FiltersDropdown filters={filters} activeFilter={filter} setActiveFilter={setFilter} />}
</div>
<div className="flex flex-col items-center justify-center">
<RecentsEmptyState type={filter} />
@@ -89,8 +96,7 @@ export const RecentActivityWidget: React.FC<THomeWidgetProps> = observer((props)
>
<div className="flex items-center justify-between mb-2">
<div className="text-base font-semibold text-custom-text-350">Recents</div>
<FiltersDropdown filters={filters} activeFilter={filter} setActiveFilter={setFilter} />
{showFilterSelect && <FiltersDropdown filters={filters} activeFilter={filter} setActiveFilter={setFilter} />}
</div>
<div className="min-h-[250px] flex flex-col">
{isLoading && <WidgetLoader widgetKey={WIDGET_KEY} />}

View File

@@ -1,10 +1,16 @@
import { useRouter } from "next/navigation";
import { FileText } from "lucide-react";
// plane types
import { TActivityEntityData, TPageEntityData } from "@plane/types";
// plane ui
import { Avatar, Logo } from "@plane/ui";
// plane utils
import { getFileURL } from "@plane/utils";
// components
import { ListItem } from "@/components/core/list";
// helpers
import { calculateTimeAgo } from "@/helpers/date-time.helper";
// hooks
import { useMember } from "@/hooks/store";
type BlockProps = {
@@ -12,15 +18,20 @@ type BlockProps = {
ref: React.RefObject<HTMLDivElement>;
workspaceSlug: string;
};
export const RecentPage = (props: BlockProps) => {
const { activity, ref, workspaceSlug } = props;
// router
const router = useRouter();
// hooks
// store hooks
const { getUserDetails } = useMember();
// derived values
const pageDetails: TPageEntityData = activity.entity_data as TPageEntityData;
const pageDetails = activity.entity_data as TPageEntityData;
const ownerDetails = getUserDetails(pageDetails?.owned_by);
const pageLink = pageDetails.project_id
? `/${workspaceSlug}/projects/${pageDetails.project_id}/pages/${pageDetails.id}`
: `/${workspaceSlug}/pages/${pageDetails.id}`;
return (
<ListItem
key={activity.id}
@@ -58,7 +69,7 @@ export const RecentPage = (props: BlockProps) => {
onItemClick={(e) => {
e.preventDefault();
e.stopPropagation();
router.push(`/${workspaceSlug}/projects/${pageDetails?.project_id}/pages/${pageDetails.id}`);
router.push(pageLink);
}}
/>
);