mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
ddb07dbe5f
* chore: removed inbox id * fix: inbox changes * chore: resolved merge conflicts * chore: inbox issue response changes * chore: inbox issue filters * fix: inbox implementation revamp * fix: type fixes * fix: pagination implementation * fix: inbox fixes * fix: pagination fixes * fix: inbox Issues pagination fixes * chore: triage state change * fix: inbox fixes * chore: filtering using boolean * chore: total results in the pagination * fix: inbox main content changes * fix: develop pull fixes * chore: resolved build erros in inbox issues * dev: fix migrations * chore: module, labels and assignee in inbox * chore: inbox issue order by * chore: inbox filters * chore: inbox ui revamp * chore: inbox type updated * chore: updated filters * chore: updated filter menmbers and date types in inbox issue filter * chore: inbox issue filter updated * chore: updated date filter in the inbox issue filter * chore: moved the current tab state from local state to store * chore: updated the filter and fetch request in the inbox issues * chore: updated tab change handler * chore: handled isEmpty in the issue filters query params * chore: inbox sidebar updated * chore: enabled create inbox issue in mobx * chore: replaced the key inbox_status to status * chore: inbox sidebar pagination * chore: updated inbox issue services * chore: inbox sidebar total count indicator * chore: create inbox issue updated * chore: updated inbox issue sidebar layout * chore: rendering issue detail in inbox issue * chore: inbox issue content updated * chore: create inbox issue modal description improvement * fix: updated delete functionality in inbox store * chore: updated multiple inbox issue creation * chore: handled loading, empty states and inbox user access permissions * chore: updated rendering issues in the sidebar * chore: inbox sidebar label improvement * chore: handled empty states * chore: disabled inbox empty state added * chore: module, labels and assignee in list endpoint * chore: labels in list endpoint * chore: inboc issue serializer * chore: representation in serializer * chore: super function * chore: inbox empty state updated * chore: implemented applied filters * chore: inbox empty state updated * chore: update date formats in applied filters * chore: inbox skeleton updated * chore: ui changes in the siebar list item * chore: removed the module and cycle ids * chore: inbox sidebar tab * chore: inbox actions * chore: updated inbox issue header actions * chore: updated inbox issue code cleanup * chore: loader improvement * chore: inbox sidebar improvement * chore: inbox sidebar empty state flicker * fix: inbox issue delete operation * chore: inbox issue title and description update indicator added * fix: resolved issue property rendering in initial load * chore: inbox sidebar and detail header improvement * fix: handling selected filter in the issue filters and applied filters * chore: inbox issue detail improvement * chore: inbox issue label updated * chore: inbox issue sidebar improvement * fix: handling issue description update when we move between the issues in inbox * chore: removed inbox issue helpers file * chore: boolean checked * chore: resolved file change requests --------- Co-authored-by: NarayanBavisetti <narayan3119@gmail.com> Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com> Co-authored-by: pablohashescobar <nikhilschacko@gmail.com> Co-authored-by: Anmol Singh Bhatia <anmolsinghbhatia@plane.so>
145 lines
5.0 KiB
TypeScript
145 lines
5.0 KiB
TypeScript
import { FC, useCallback, useRef } from "react";
|
|
import { observer } from "mobx-react";
|
|
import { useRouter } from "next/router";
|
|
import { TInboxIssueCurrentTab } from "@plane/types";
|
|
import { Loader } from "@plane/ui";
|
|
// components
|
|
import { EmptyState } from "@/components/empty-state";
|
|
import { FiltersRoot, InboxIssueAppliedFilters, InboxIssueList } from "@/components/inbox";
|
|
import { InboxSidebarLoader } from "@/components/ui";
|
|
// constants
|
|
import { EmptyStateType } from "@/constants/empty-state";
|
|
// helpers
|
|
import { cn } from "@/helpers/common.helper";
|
|
// hooks
|
|
import { useProject, useProjectInbox } from "@/hooks/store";
|
|
import { useIntersectionObserver } from "@/hooks/use-intersection-observer";
|
|
|
|
type IInboxSidebarProps = {
|
|
workspaceSlug: string;
|
|
projectId: string;
|
|
};
|
|
|
|
const tabNavigationOptions: { key: TInboxIssueCurrentTab; label: string }[] = [
|
|
{
|
|
key: "open",
|
|
label: "Open",
|
|
},
|
|
{
|
|
key: "closed",
|
|
label: "Closed",
|
|
},
|
|
];
|
|
|
|
export const InboxSidebar: FC<IInboxSidebarProps> = observer((props) => {
|
|
const { workspaceSlug, projectId } = props;
|
|
// ref
|
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
const elementRef = useRef<HTMLDivElement>(null);
|
|
// store
|
|
const { currentProjectDetails } = useProject();
|
|
const {
|
|
currentTab,
|
|
handleCurrentTab,
|
|
isLoading,
|
|
inboxIssuesArray,
|
|
inboxIssuePaginationInfo,
|
|
fetchInboxPaginationIssues,
|
|
getAppliedFiltersCount,
|
|
} = useProjectInbox();
|
|
|
|
const router = useRouter();
|
|
|
|
const fetchNextPages = useCallback(() => {
|
|
if (!workspaceSlug || !projectId) return;
|
|
fetchInboxPaginationIssues(workspaceSlug.toString(), projectId.toString());
|
|
}, [workspaceSlug, projectId, fetchInboxPaginationIssues]);
|
|
// page observer
|
|
useIntersectionObserver({
|
|
containerRef,
|
|
elementRef,
|
|
callback: fetchNextPages,
|
|
rootMargin: "20%",
|
|
});
|
|
|
|
return (
|
|
<div className="flex-shrink-0 w-2/6 h-full border-r border-custom-border-300">
|
|
<div className="relative w-full h-full flex flex-col overflow-hidden">
|
|
<div className="border-b border-custom-border-300 flex-shrink-0 w-full h-[50px] relative flex items-center gap-2 pr-3 whitespace-nowrap">
|
|
{tabNavigationOptions.map((option) => (
|
|
<div
|
|
key={option?.key}
|
|
className={cn(
|
|
`text-sm relative flex items-center gap-1 h-[50px] px-2 cursor-pointer transition-all font-medium`,
|
|
currentTab === option?.key ? `text-custom-primary-100` : `hover:text-custom-text-200`
|
|
)}
|
|
onClick={() => {
|
|
if (currentTab != option?.key) handleCurrentTab(option?.key);
|
|
router.push(`/${workspaceSlug}/projects/${projectId}/inbox`);
|
|
}}
|
|
>
|
|
<div>{option?.label}</div>
|
|
{option?.key === "open" && currentTab === option?.key && (
|
|
<div className="rounded-full p-1.5 py-0.5 bg-custom-primary-100/20 text-custom-primary-100 text-xs font-semibold">
|
|
{inboxIssuePaginationInfo?.total_results || 0}
|
|
</div>
|
|
)}
|
|
<div
|
|
className={cn(
|
|
`border absolute bottom-0 right-0 left-0 rounded-t-md`,
|
|
currentTab === option?.key ? `border-custom-primary-100` : `border-transparent`
|
|
)}
|
|
/>
|
|
</div>
|
|
))}
|
|
<div className="ml-auto">
|
|
<FiltersRoot />
|
|
</div>
|
|
</div>
|
|
|
|
<InboxIssueAppliedFilters />
|
|
|
|
{isLoading && !inboxIssuePaginationInfo?.next_page_results ? (
|
|
<InboxSidebarLoader />
|
|
) : (
|
|
<div
|
|
className="w-full h-full overflow-hidden overflow-y-auto vertical-scrollbar scrollbar-md"
|
|
ref={containerRef}
|
|
>
|
|
{inboxIssuesArray.length > 0 ? (
|
|
<InboxIssueList
|
|
workspaceSlug={workspaceSlug}
|
|
projectId={projectId}
|
|
projectIdentifier={currentProjectDetails?.identifier}
|
|
inboxIssues={inboxIssuesArray}
|
|
/>
|
|
) : (
|
|
<div className="flex items-center justify-center h-full w-full">
|
|
<EmptyState
|
|
type={
|
|
getAppliedFiltersCount > 0
|
|
? EmptyStateType.INBOX_SIDEBAR_FILTER_EMPTY_STATE
|
|
: currentTab === "open"
|
|
? EmptyStateType.INBOX_SIDEBAR_OPEN_TAB
|
|
: EmptyStateType.INBOX_SIDEBAR_CLOSED_TAB
|
|
}
|
|
layout="screen-simple"
|
|
/>
|
|
</div>
|
|
)}
|
|
|
|
<div ref={elementRef}>
|
|
{inboxIssuePaginationInfo?.next_page_results && (
|
|
<Loader className="mx-auto w-full space-y-4 py-4 px-2">
|
|
<Loader.Item height="64px" width="w-100" />
|
|
<Loader.Item height="64px" width="w-100" />
|
|
</Loader>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
});
|