[WEB-4951] [WEB-4884] feat: work item filters revamp (#7810)

This commit is contained in:
Prateek Shourya 2025-09-19 18:27:36 +05:30 committed by GitHub
parent e6a7ca4c72
commit 9aef5d4aa9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
160 changed files with 5879 additions and 4881 deletions

View file

@ -6,25 +6,11 @@ import { EIssueFilterType, ISSUE_DISPLAY_FILTERS_BY_PAGE } from "@plane/constant
// i18n
import { useTranslation } from "@plane/i18n";
// types
import {
EIssuesStoreType,
IIssueDisplayFilterOptions,
IIssueDisplayProperties,
IIssueFilterOptions,
EIssueLayoutTypes,
} from "@plane/types";
import { EIssuesStoreType, IIssueDisplayFilterOptions, IIssueDisplayProperties, EIssueLayoutTypes } from "@plane/types";
// components
import { isIssueFilterActive } from "@plane/utils";
import {
DisplayFiltersSelection,
FilterSelection,
FiltersDropdown,
LayoutSelection,
} from "@/components/issues/issue-layouts/filters";
// helpers
import { DisplayFiltersSelection, FiltersDropdown, LayoutSelection } from "@/components/issues/issue-layouts/filters";
// hooks
import { useIssues } from "@/hooks/store/use-issues";
import { useLabel } from "@/hooks/store/use-label";
export const ProfileIssuesFilter = observer(() => {
// i18n
@ -35,11 +21,7 @@ export const ProfileIssuesFilter = observer(() => {
const {
issuesFilter: { issueFilters, updateFilters },
} = useIssues(EIssuesStoreType.PROFILE);
const { workspaceLabels } = useLabel();
// derived values
const states = undefined;
const members = undefined;
const activeLayout = issueFilters?.displayFilters?.layout;
const handleLayoutChange = useCallback(
@ -56,33 +38,6 @@ export const ProfileIssuesFilter = observer(() => {
[workspaceSlug, updateFilters, userId]
);
const handleFiltersUpdate = useCallback(
(key: keyof IIssueFilterOptions, value: string | string[]) => {
if (!workspaceSlug || !userId) return;
const newValues = issueFilters?.filters?.[key] ?? [];
if (Array.isArray(value)) {
// this validation is majorly for the filter start_date, target_date custom
value.forEach((val) => {
if (!newValues.includes(val)) newValues.push(val);
else newValues.splice(newValues.indexOf(val), 1);
});
} else {
if (issueFilters?.filters?.[key]?.includes(value)) newValues.splice(newValues.indexOf(value), 1);
else newValues.push(value);
}
updateFilters(
workspaceSlug.toString(),
undefined,
EIssueFilterType.FILTERS,
{ [key]: newValues },
userId.toString()
);
},
[workspaceSlug, issueFilters, updateFilters, userId]
);
const handleDisplayFilters = useCallback(
(updatedDisplayFilter: Partial<IIssueDisplayFilterOptions>) => {
if (!workspaceSlug || !userId) return;
@ -118,30 +73,10 @@ export const ProfileIssuesFilter = observer(() => {
onChange={(layout) => handleLayoutChange(layout)}
selectedLayout={activeLayout}
/>
<FiltersDropdown
title={t("common.filters")}
placement="bottom-end"
isFiltersApplied={isIssueFilterActive(issueFilters)}
>
<FilterSelection
layoutDisplayFiltersOptions={
activeLayout ? ISSUE_DISPLAY_FILTERS_BY_PAGE.profile_issues[activeLayout] : undefined
}
filters={issueFilters?.filters ?? {}}
handleFiltersUpdate={handleFiltersUpdate}
displayFilters={issueFilters?.displayFilters ?? {}}
handleDisplayFiltersUpdate={handleDisplayFilters}
states={states}
labels={workspaceLabels}
memberIds={members}
/>
</FiltersDropdown>
<FiltersDropdown title={t("common.display")} placement="bottom-end">
<DisplayFiltersSelection
layoutDisplayFiltersOptions={
activeLayout ? ISSUE_DISPLAY_FILTERS_BY_PAGE.profile_issues[activeLayout] : undefined
activeLayout ? ISSUE_DISPLAY_FILTERS_BY_PAGE.profile_issues.layoutOptions[activeLayout] : undefined
}
displayFilters={issueFilters?.displayFilters ?? {}}
handleDisplayFiltersUpdate={handleDisplayFilters}

View file

@ -3,12 +3,14 @@ import { observer } from "mobx-react";
import { useParams } from "next/navigation";
import useSWR from "swr";
// plane imports
import { ISSUE_DISPLAY_FILTERS_BY_PAGE } from "@plane/constants";
import { EIssuesStoreType } from "@plane/types";
// components
import { ProfileIssuesAppliedFiltersRoot } from "@/components/issues/issue-layouts/filters";
import { ProfileIssuesKanBanLayout } from "@/components/issues/issue-layouts/kanban/roots/profile-issues-root";
import { ProfileIssuesListLayout } from "@/components/issues/issue-layouts/list/roots/profile-issues-root";
import { IssuePeekOverview } from "@/components/issues/peek-overview";
import { WorkspaceLevelWorkItemFiltersHOC } from "@/components/work-item-filters/filters-hoc/workspace-level";
import { WorkItemFiltersRow } from "@/components/work-item-filters/work-item-filters-row";
// hooks
import { useIssues } from "@/hooks/store/use-issues";
import { IssuesStoreContext } from "@/hooks/use-issue-layout-store";
@ -19,7 +21,6 @@ type Props = {
export const ProfileIssuesPage = observer((props: Props) => {
const { type } = props;
const { workspaceSlug, userId } = useParams() as {
workspaceSlug: string;
userId: string;
@ -27,8 +28,10 @@ export const ProfileIssuesPage = observer((props: Props) => {
// store hooks
const {
issues: { setViewId },
issuesFilter: { issueFilters, fetchFilters },
issuesFilter: { issueFilters, fetchFilters, updateFilterExpression },
} = useIssues(EIssuesStoreType.PROFILE);
// derived values
const activeLayout = issueFilters?.displayFilters?.layout || undefined;
useEffect(() => {
if (setViewId) setViewId(type);
@ -44,22 +47,33 @@ export const ProfileIssuesPage = observer((props: Props) => {
{ revalidateIfStale: false, revalidateOnFocus: false }
);
const activeLayout = issueFilters?.displayFilters?.layout || undefined;
return (
<IssuesStoreContext.Provider value={EIssuesStoreType.PROFILE}>
<div className="flex flex-col h-full w-full">
<ProfileIssuesAppliedFiltersRoot />
<div className="-z-1 relative h-full w-full overflow-auto">
{activeLayout === "list" ? (
<ProfileIssuesListLayout />
) : activeLayout === "kanban" ? (
<ProfileIssuesKanBanLayout />
) : null}
</div>
</div>
{/* peek overview */}
<IssuePeekOverview />
<WorkspaceLevelWorkItemFiltersHOC
entityId={userId}
entityType={EIssuesStoreType.PROFILE}
filtersToShowByLayout={ISSUE_DISPLAY_FILTERS_BY_PAGE.profile_issues.filters}
initialWorkItemFilters={issueFilters}
updateFilters={updateFilterExpression.bind(updateFilterExpression, workspaceSlug, userId)}
workspaceSlug={workspaceSlug}
>
{({ filter: profileWorkItemsFilter }) => (
<>
<div className="flex flex-col h-full w-full">
{profileWorkItemsFilter && <WorkItemFiltersRow filter={profileWorkItemsFilter} />}
<div className="-z-1 relative h-full w-full overflow-auto">
{activeLayout === "list" ? (
<ProfileIssuesListLayout />
) : activeLayout === "kanban" ? (
<ProfileIssuesKanBanLayout />
) : null}
</div>
</div>
{/* peek overview */}
<IssuePeekOverview />
</>
)}
</WorkspaceLevelWorkItemFiltersHOC>
</IssuesStoreContext.Provider>
);
});

View file

@ -119,7 +119,7 @@ export const ProfileSidebar: FC<TProfileSidebar> = observer((props) => {
className="h-full w-full rounded object-cover"
/>
) : (
<div className="flex h-[52px] w-[52px] items-center justify-center rounded bg-custom-background-90 capitalize text-custom-text-100">
<div className="flex h-[52px] w-[52px] items-center justify-center rounded bg-[#028375] capitalize text-white">
{userData?.first_name?.[0]}
</div>
)}