save all filters and properties for views (#4728)

This commit is contained in:
rahulramesha 2024-06-07 19:43:27 +05:30 committed by GitHub
parent de8da176d3
commit fb2b4ae303
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 63 additions and 19 deletions

View File

@ -19,7 +19,7 @@ import { EUserProjectRoles } from "@/constants/project";
// helpers // helpers
import { replaceUnderscoreIfSnakeCase } from "@/helpers/string.helper"; import { replaceUnderscoreIfSnakeCase } from "@/helpers/string.helper";
// hooks // hooks
import { useAppRouter, useUser } from "@/hooks/store"; import { useUser } from "@/hooks/store";
type Props = { type Props = {
appliedFilters: IIssueFilterOptions; appliedFilters: IIssueFilterOptions;
@ -36,7 +36,6 @@ const dateFilters = ["start_date", "target_date"];
export const AppliedFiltersList: React.FC<Props> = observer((props) => { export const AppliedFiltersList: React.FC<Props> = observer((props) => {
const { appliedFilters, handleClearAllFilters, handleRemoveFilter, labels, states, alwaysAllowEditing } = props; const { appliedFilters, handleClearAllFilters, handleRemoveFilter, labels, states, alwaysAllowEditing } = props;
// store hooks // store hooks
const { moduleId, cycleId } = useAppRouter();
const { const {
membership: { currentProjectRole }, membership: { currentProjectRole },
} = useUser(); } = useUser();
@ -108,14 +107,14 @@ export const AppliedFiltersList: React.FC<Props> = observer((props) => {
values={value} values={value}
/> />
)} )}
{filterKey === "cycle" && !cycleId && ( {filterKey === "cycle" && (
<AppliedCycleFilters <AppliedCycleFilters
editable={isEditingAllowed} editable={isEditingAllowed}
handleRemove={(val) => handleRemoveFilter("cycle", val)} handleRemove={(val) => handleRemoveFilter("cycle", val)}
values={value} values={value}
/> />
)} )}
{filterKey === "module" && !moduleId && ( {filterKey === "module" && (
<AppliedModuleFilters <AppliedModuleFilters
editable={isEditingAllowed} editable={isEditingAllowed}
handleRemove={(val) => handleRemoveFilter("module", val)} handleRemove={(val) => handleRemoveFilter("module", val)}

View File

@ -2,7 +2,7 @@ import { observer } from "mobx-react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { IIssueFilterOptions } from "@plane/types"; import { IIssueFilterOptions } from "@plane/types";
// hooks // hooks
import { AppliedFiltersList, SaveFilterView } from "@/components/issues"; import { AppliedFiltersList } from "@/components/issues";
import { EIssueFilterType, EIssuesStoreType } from "@/constants/issue"; import { EIssueFilterType, EIssuesStoreType } from "@/constants/issue";
import { useIssues, useLabel, useProjectState } from "@/hooks/store"; import { useIssues, useLabel, useProjectState } from "@/hooks/store";
// components // components
@ -76,8 +76,6 @@ export const ArchivedIssueAppliedFiltersRoot: React.FC = observer(() => {
labels={projectLabels ?? []} labels={projectLabels ?? []}
states={projectStates} states={projectStates}
/> />
<SaveFilterView workspaceSlug={workspaceSlug} projectId={projectId} filterParams={appliedFilters} />
</div> </div>
); );
}); });

View File

@ -74,7 +74,7 @@ export const CycleAppliedFiltersRoot: React.FC = observer(() => {
}; };
// return if no filters are applied // return if no filters are applied
if (Object.keys(appliedFilters).length === 0 || !workspaceSlug || !projectId) return null; if (Object.keys(appliedFilters).length === 0 || !workspaceSlug || !projectId || !cycleId) return null;
return ( return (
<div className="flex justify-between p-4 gap-2.5"> <div className="flex justify-between p-4 gap-2.5">
@ -89,7 +89,11 @@ export const CycleAppliedFiltersRoot: React.FC = observer(() => {
<SaveFilterView <SaveFilterView
workspaceSlug={workspaceSlug.toString()} workspaceSlug={workspaceSlug.toString()}
projectId={projectId.toString()} projectId={projectId.toString()}
filterParams={appliedFilters} filterParams={{
filters: { ...appliedFilters, cycle: [cycleId?.toString()] },
display_filters: issueFilters?.displayFilters,
display_properties: issueFilters?.displayProperties,
}}
/> />
</div> </div>
); );

View File

@ -2,7 +2,7 @@ import { observer } from "mobx-react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { IIssueFilterOptions } from "@plane/types"; import { IIssueFilterOptions } from "@plane/types";
// hooks // hooks
import { AppliedFiltersList, SaveFilterView } from "@/components/issues"; import { AppliedFiltersList } from "@/components/issues";
import { EIssueFilterType, EIssuesStoreType } from "@/constants/issue"; import { EIssueFilterType, EIssuesStoreType } from "@/constants/issue";
import { useIssues, useLabel, useProjectState } from "@/hooks/store"; import { useIssues, useLabel, useProjectState } from "@/hooks/store";
// components // components
@ -71,8 +71,6 @@ export const DraftIssueAppliedFiltersRoot: React.FC = observer(() => {
labels={projectLabels ?? []} labels={projectLabels ?? []}
states={projectStates} states={projectStates}
/> />
<SaveFilterView workspaceSlug={workspaceSlug} projectId={projectId} filterParams={appliedFilters} />
</div> </div>
); );
}); });

View File

@ -73,7 +73,7 @@ export const ModuleAppliedFiltersRoot: React.FC = observer(() => {
}; };
// return if no filters are applied // return if no filters are applied
if (!workspaceSlug || !projectId || Object.keys(appliedFilters).length === 0) return null; if (!workspaceSlug || !projectId || !moduleId || Object.keys(appliedFilters).length === 0) return null;
return ( return (
<div className="flex justify-between p-4 gap-2.5"> <div className="flex justify-between p-4 gap-2.5">
@ -88,7 +88,11 @@ export const ModuleAppliedFiltersRoot: React.FC = observer(() => {
<SaveFilterView <SaveFilterView
workspaceSlug={workspaceSlug.toString()} workspaceSlug={workspaceSlug.toString()}
projectId={projectId.toString()} projectId={projectId.toString()}
filterParams={appliedFilters} filterParams={{
filters: { ...appliedFilters, module: [moduleId.toString()] },
display_filters: issueFilters?.displayFilters,
display_properties: issueFilters?.displayProperties,
}}
/> />
</div> </div>
); );

View File

@ -77,7 +77,15 @@ export const ProjectAppliedFiltersRoot: React.FC = observer(() => {
states={projectStates} states={projectStates}
/> />
{isEditingAllowed && ( {isEditingAllowed && (
<SaveFilterView workspaceSlug={workspaceSlug} projectId={projectId} filterParams={appliedFilters} /> <SaveFilterView
workspaceSlug={workspaceSlug}
projectId={projectId}
filterParams={{
filters: appliedFilters,
display_filters: issueFilters?.displayFilters,
display_properties: issueFilters?.displayProperties,
}}
/>
)} )}
</div> </div>
); );

View File

@ -1,5 +1,4 @@
import isEmpty from "lodash/isEmpty"; import isEmpty from "lodash/isEmpty";
import isEqual from "lodash/isEqual";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { IIssueFilterOptions } from "@plane/types"; import { IIssueFilterOptions } from "@plane/types";
@ -8,6 +7,7 @@ import { Button } from "@plane/ui";
import { AppliedFiltersList } from "@/components/issues"; import { AppliedFiltersList } from "@/components/issues";
import { EIssueFilterType, EIssuesStoreType } from "@/constants/issue"; import { EIssueFilterType, EIssuesStoreType } from "@/constants/issue";
import { useIssues, useLabel, useProjectState, useProjectView } from "@/hooks/store"; import { useIssues, useLabel, useProjectState, useProjectView } from "@/hooks/store";
import { getAreFiltersEqual } from "../../../utils";
// components // components
// ui // ui
// types // types
@ -79,7 +79,7 @@ export const ProjectViewAppliedFiltersRoot: React.FC = observer(() => {
); );
}; };
const areFiltersEqual = isEqual(appliedFilters ?? {}, viewDetails?.filters ?? {}); const areFiltersEqual = getAreFiltersEqual(appliedFilters, issueFilters, viewDetails);
// return if no filters are applied // return if no filters are applied
if (isEmpty(appliedFilters) && areFiltersEqual) return null; if (isEmpty(appliedFilters) && areFiltersEqual) return null;
@ -91,6 +91,12 @@ export const ProjectViewAppliedFiltersRoot: React.FC = observer(() => {
filters: { filters: {
...(appliedFilters ?? {}), ...(appliedFilters ?? {}),
}, },
display_filters: {
...issueFilters?.displayFilters,
},
display_properties: {
...issueFilters?.displayProperties,
},
}); });
}; };

View File

@ -1,4 +1,5 @@
import { FC, useState } from "react"; import { FC, useState } from "react";
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions } from "@plane/types";
import { Button } from "@plane/ui"; import { Button } from "@plane/ui";
// components // components
import { CreateUpdateProjectViewModal } from "@/components/views"; import { CreateUpdateProjectViewModal } from "@/components/views";
@ -6,7 +7,11 @@ import { CreateUpdateProjectViewModal } from "@/components/views";
interface ISaveFilterView { interface ISaveFilterView {
workspaceSlug: string; workspaceSlug: string;
projectId: string; projectId: string;
filterParams: any; filterParams: {
filters: IIssueFilterOptions;
display_filters?: IIssueDisplayFilterOptions;
display_properties?: IIssueDisplayProperties;
};
} }
export const SaveFilterView: FC<ISaveFilterView> = (props) => { export const SaveFilterView: FC<ISaveFilterView> = (props) => {
@ -19,7 +24,7 @@ export const SaveFilterView: FC<ISaveFilterView> = (props) => {
<CreateUpdateProjectViewModal <CreateUpdateProjectViewModal
workspaceSlug={workspaceSlug} workspaceSlug={workspaceSlug}
projectId={projectId} projectId={projectId}
preLoadedData={{ filters: { ...filterParams } }} preLoadedData={{ ...filterParams }}
isOpen={viewModal} isOpen={viewModal}
onClose={() => setViewModal(false)} onClose={() => setViewModal(false)}
/> />

View File

@ -1,6 +1,7 @@
import { extractInstruction } from "@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item"; import { extractInstruction } from "@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item";
import clone from "lodash/clone"; import clone from "lodash/clone";
import concat from "lodash/concat"; import concat from "lodash/concat";
import isEqual from "lodash/isEqual";
import pull from "lodash/pull"; import pull from "lodash/pull";
import uniq from "lodash/uniq"; import uniq from "lodash/uniq";
import scrollIntoView from "smooth-scroll-into-view-if-needed"; import scrollIntoView from "smooth-scroll-into-view-if-needed";
@ -13,6 +14,9 @@ import {
IPragmaticDropPayload, IPragmaticDropPayload,
TIssue, TIssue,
TIssueGroupByOptions, TIssueGroupByOptions,
IIssueFilterOptions,
IIssueFilters,
IProjectView,
} from "@plane/types"; } from "@plane/types";
// ui // ui
import { Avatar, CycleGroupIcon, DiceIcon, PriorityIcon, StateGroupIcon } from "@plane/ui"; import { Avatar, CycleGroupIcon, DiceIcon, PriorityIcon, StateGroupIcon } from "@plane/ui";
@ -535,3 +539,19 @@ export const handleGroupDragDrop = async (
return await updateIssueOnDrop(sourceIssue.project_id, sourceIssue.id, updatedIssue, issueUpdates); return await updateIssueOnDrop(sourceIssue.project_id, sourceIssue.id, updatedIssue, issueUpdates);
} }
}; };
/**
* This Method compares filters and returns a boolean based on which and updateView button is shown
* @param appliedFilters
* @param issueFilters
* @param viewDetails
* @returns
*/
export const getAreFiltersEqual = (
appliedFilters: IIssueFilterOptions | undefined,
issueFilters: IIssueFilters | undefined,
viewDetails: IProjectView | null
) =>
isEqual(appliedFilters ?? {}, viewDetails?.filters ?? {}) &&
isEqual(issueFilters?.displayFilters ?? {}, viewDetails?.display_filters ?? {}) &&
isEqual(issueFilters?.displayProperties ?? {}, viewDetails?.display_properties ?? {});

View File

@ -94,6 +94,8 @@ export const ProjectViewForm: React.FC<Props> = observer((props) => {
description: formData.description, description: formData.description,
logo_props: formData.logo_props, logo_props: formData.logo_props,
filters: formData.filters, filters: formData.filters,
display_filters: formData.display_filters,
display_properties: formData.display_properties,
} as IProjectView); } as IProjectView);
reset({ reset({