chore: refactor apply/ clear filter implementation in All Issues.

This commit is contained in:
Prateek Shourya 2023-12-27 17:40:36 +05:30
parent 1a05c07f67
commit f4b1b4ddcf
10 changed files with 140 additions and 77 deletions

View File

@ -11,10 +11,11 @@ import { DATE_FILTER_OPTIONS } from "constants/filters";
type Props = { type Props = {
handleRemove: (val: string) => void; handleRemove: (val: string) => void;
values: string[]; values: string[];
disableClearOption?: boolean;
}; };
export const AppliedDateFilters: React.FC<Props> = observer((props) => { export const AppliedDateFilters: React.FC<Props> = observer((props) => {
const { handleRemove, values } = props; const { handleRemove, values, disableClearOption } = props;
const getDateLabel = (value: string): string => { const getDateLabel = (value: string): string => {
let dateLabel = ""; let dateLabel = "";
@ -40,13 +41,15 @@ export const AppliedDateFilters: React.FC<Props> = observer((props) => {
{values.map((date) => ( {values.map((date) => (
<div key={date} className="flex items-center gap-1 rounded bg-custom-background-80 p-1 text-xs"> <div key={date} className="flex items-center gap-1 rounded bg-custom-background-80 p-1 text-xs">
<span className="normal-case">{getDateLabel(date)}</span> <span className="normal-case">{getDateLabel(date)}</span>
<button {!disableClearOption && (
type="button" <button
className="grid place-items-center text-custom-text-300 hover:text-custom-text-200" type="button"
onClick={() => handleRemove(date)} className="grid place-items-center text-custom-text-300 hover:text-custom-text-200"
> onClick={() => handleRemove(date)}
<X size={10} strokeWidth={2} /> >
</button> <X size={10} strokeWidth={2} />
</button>
)}
</div> </div>
))} ))}
</> </>

View File

@ -24,13 +24,23 @@ type Props = {
members?: IUserLite[] | undefined; members?: IUserLite[] | undefined;
projects?: IProject[] | undefined; projects?: IProject[] | undefined;
states?: IState[] | undefined; states?: IState[] | undefined;
disableClearFilterOptions?: (keyof IIssueFilterOptions)[];
}; };
const membersFilters = ["assignees", "mentions", "created_by", "subscriber"]; const membersFilters = ["assignees", "mentions", "created_by", "subscriber"];
const dateFilters = ["start_date", "target_date"]; 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, members, projects, states } = props; const {
appliedFilters,
handleClearAllFilters,
handleRemoveFilter,
labels,
members,
projects,
states,
disableClearFilterOptions,
} = props;
if (!appliedFilters) return null; if (!appliedFilters) return null;
@ -52,16 +62,22 @@ export const AppliedFiltersList: React.FC<Props> = observer((props) => {
<div className="flex flex-wrap items-center gap-1"> <div className="flex flex-wrap items-center gap-1">
{membersFilters.includes(filterKey) && ( {membersFilters.includes(filterKey) && (
<AppliedMembersFilters <AppliedMembersFilters
disableClearOption={disableClearFilterOptions?.includes(filterKey)}
handleRemove={(val) => handleRemoveFilter(filterKey, val)} handleRemove={(val) => handleRemoveFilter(filterKey, val)}
members={members} members={members}
values={value} values={value}
/> />
)} )}
{dateFilters.includes(filterKey) && ( {dateFilters.includes(filterKey) && (
<AppliedDateFilters handleRemove={(val) => handleRemoveFilter(filterKey, val)} values={value} /> <AppliedDateFilters
disableClearOption={disableClearFilterOptions?.includes(filterKey)}
handleRemove={(val) => handleRemoveFilter(filterKey, val)}
values={value}
/>
)} )}
{filterKey === "labels" && ( {filterKey === "labels" && (
<AppliedLabelsFilters <AppliedLabelsFilters
disableClearOption={disableClearFilterOptions?.includes(filterKey)}
handleRemove={(val) => handleRemoveFilter("labels", val)} handleRemove={(val) => handleRemoveFilter("labels", val)}
labels={labels} labels={labels}
values={value} values={value}
@ -69,12 +85,14 @@ export const AppliedFiltersList: React.FC<Props> = observer((props) => {
)} )}
{filterKey === "priority" && ( {filterKey === "priority" && (
<AppliedPriorityFilters <AppliedPriorityFilters
disableClearOption={disableClearFilterOptions?.includes(filterKey)}
handleRemove={(val) => handleRemoveFilter("priority", val)} handleRemove={(val) => handleRemoveFilter("priority", val)}
values={value} values={value}
/> />
)} )}
{filterKey === "state" && states && ( {filterKey === "state" && states && (
<AppliedStateFilters <AppliedStateFilters
disableClearOption={disableClearFilterOptions?.includes(filterKey)}
handleRemove={(val) => handleRemoveFilter("state", val)} handleRemove={(val) => handleRemoveFilter("state", val)}
states={states} states={states}
values={value} values={value}
@ -82,36 +100,42 @@ export const AppliedFiltersList: React.FC<Props> = observer((props) => {
)} )}
{filterKey === "state_group" && ( {filterKey === "state_group" && (
<AppliedStateGroupFilters <AppliedStateGroupFilters
disableClearOption={disableClearFilterOptions?.includes(filterKey)}
handleRemove={(val) => handleRemoveFilter("state_group", val)} handleRemove={(val) => handleRemoveFilter("state_group", val)}
values={value} values={value}
/> />
)} )}
{filterKey === "project" && ( {filterKey === "project" && (
<AppliedProjectFilters <AppliedProjectFilters
disableClearOption={disableClearFilterOptions?.includes(filterKey)}
handleRemove={(val) => handleRemoveFilter("project", val)} handleRemove={(val) => handleRemoveFilter("project", val)}
projects={projects} projects={projects}
values={value} values={value}
/> />
)} )}
<button {!disableClearFilterOptions?.includes(filterKey) && (
type="button" <button
className="grid place-items-center text-custom-text-300 hover:text-custom-text-200" type="button"
onClick={() => handleRemoveFilter(filterKey, null)} className="grid place-items-center text-custom-text-300 hover:text-custom-text-200"
> onClick={() => handleRemoveFilter(filterKey, null)}
<X size={12} strokeWidth={2} /> >
</button> <X size={12} strokeWidth={2} />
</button>
)}
</div> </div>
</div> </div>
); );
})} })}
<button {(!disableClearFilterOptions || disableClearFilterOptions.length === 0) && (
type="button" <button
onClick={handleClearAllFilters} type="button"
className="flex items-center gap-2 rounded-md border border-custom-border-200 px-2 py-1 text-xs text-custom-text-300 hover:text-custom-text-200" onClick={handleClearAllFilters}
> className="flex items-center gap-2 rounded-md border border-custom-border-200 px-2 py-1 text-xs text-custom-text-300 hover:text-custom-text-200"
Clear all >
<X size={12} strokeWidth={2} /> Clear all
</button> <X size={12} strokeWidth={2} />
</div> </button>
)}
</div>
); );
}); });

View File

@ -9,10 +9,11 @@ type Props = {
handleRemove: (val: string) => void; handleRemove: (val: string) => void;
labels: IIssueLabel[] | undefined; labels: IIssueLabel[] | undefined;
values: string[]; values: string[];
disableClearOption?: boolean;
}; };
export const AppliedLabelsFilters: React.FC<Props> = observer((props) => { export const AppliedLabelsFilters: React.FC<Props> = observer((props) => {
const { handleRemove, labels, values } = props; const { handleRemove, labels, values, disableClearOption } = props;
return ( return (
<> <>
@ -30,13 +31,15 @@ export const AppliedLabelsFilters: React.FC<Props> = observer((props) => {
}} }}
/> />
<span className="normal-case">{labelDetails.name}</span> <span className="normal-case">{labelDetails.name}</span>
<button {!disableClearOption && (
type="button" <button
className="grid place-items-center text-custom-text-300 hover:text-custom-text-200" type="button"
onClick={() => handleRemove(labelId)} className="grid place-items-center text-custom-text-300 hover:text-custom-text-200"
> onClick={() => handleRemove(labelId)}
<X size={10} strokeWidth={2} /> >
</button> <X size={10} strokeWidth={2} />
</button>
)}
</div> </div>
); );
})} })}

View File

@ -9,10 +9,11 @@ type Props = {
handleRemove: (val: string) => void; handleRemove: (val: string) => void;
members: IUserLite[] | undefined; members: IUserLite[] | undefined;
values: string[]; values: string[];
disableClearOption?: boolean;
}; };
export const AppliedMembersFilters: React.FC<Props> = observer((props) => { export const AppliedMembersFilters: React.FC<Props> = observer((props) => {
const { handleRemove, members, values } = props; const { handleRemove, members, values, disableClearOption } = props;
return ( return (
<> <>
@ -25,13 +26,15 @@ export const AppliedMembersFilters: React.FC<Props> = observer((props) => {
<div key={memberId} className="flex items-center gap-1 rounded bg-custom-background-80 p-1 text-xs"> <div key={memberId} className="flex items-center gap-1 rounded bg-custom-background-80 p-1 text-xs">
<Avatar name={memberDetails.display_name} src={memberDetails.avatar} showTooltip={false} /> <Avatar name={memberDetails.display_name} src={memberDetails.avatar} showTooltip={false} />
<span className="normal-case">{memberDetails.display_name}</span> <span className="normal-case">{memberDetails.display_name}</span>
<button {!disableClearOption && (
type="button" <button
className="grid place-items-center text-custom-text-300 hover:text-custom-text-200" type="button"
onClick={() => handleRemove(memberId)} className="grid place-items-center text-custom-text-300 hover:text-custom-text-200"
> onClick={() => handleRemove(memberId)}
<X size={10} strokeWidth={2} /> >
</button> <X size={10} strokeWidth={2} />
</button>
)}
</div> </div>
); );
})} })}

View File

@ -9,10 +9,11 @@ import { TIssuePriorities } from "types";
type Props = { type Props = {
handleRemove: (val: string) => void; handleRemove: (val: string) => void;
values: string[]; values: string[];
disableClearOption?: boolean;
}; };
export const AppliedPriorityFilters: React.FC<Props> = observer((props) => { export const AppliedPriorityFilters: React.FC<Props> = observer((props) => {
const { handleRemove, values } = props; const { handleRemove, values, disableClearOption } = props;
return ( return (
<> <>
@ -20,13 +21,15 @@ export const AppliedPriorityFilters: React.FC<Props> = observer((props) => {
<div key={priority} className="flex items-center gap-1 rounded bg-custom-background-80 p-1 text-xs"> <div key={priority} className="flex items-center gap-1 rounded bg-custom-background-80 p-1 text-xs">
<PriorityIcon priority={priority as TIssuePriorities} className={`h-3 w-3`} /> <PriorityIcon priority={priority as TIssuePriorities} className={`h-3 w-3`} />
{priority} {priority}
<button {!disableClearOption && (
type="button" <button
className="grid place-items-center text-custom-text-300 hover:text-custom-text-200" type="button"
onClick={() => handleRemove(priority)} className="grid place-items-center text-custom-text-300 hover:text-custom-text-200"
> onClick={() => handleRemove(priority)}
<X size={10} strokeWidth={2} /> >
</button> <X size={10} strokeWidth={2} />
</button>
)}
</div> </div>
))} ))}
</> </>

View File

@ -10,10 +10,11 @@ type Props = {
handleRemove: (val: string) => void; handleRemove: (val: string) => void;
projects: IProject[] | undefined; projects: IProject[] | undefined;
values: string[]; values: string[];
disableClearOption?: boolean;
}; };
export const AppliedProjectFilters: React.FC<Props> = observer((props) => { export const AppliedProjectFilters: React.FC<Props> = observer((props) => {
const { handleRemove, projects, values } = props; const { handleRemove, projects, values, disableClearOption } = props;
return ( return (
<> <>
@ -34,13 +35,15 @@ export const AppliedProjectFilters: React.FC<Props> = observer((props) => {
</span> </span>
)} )}
<span className="normal-case">{projectDetails.name}</span> <span className="normal-case">{projectDetails.name}</span>
<button {!disableClearOption && (
type="button" <button
className="grid place-items-center text-custom-text-300 hover:text-custom-text-200" type="button"
onClick={() => handleRemove(projectId)} className="grid place-items-center text-custom-text-300 hover:text-custom-text-200"
> onClick={() => handleRemove(projectId)}
<X size={10} strokeWidth={2} /> >
</button> <X size={10} strokeWidth={2} />
</button>
)}
</div> </div>
); );
})} })}

View File

@ -1,3 +1,4 @@
import React from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
@ -9,10 +10,16 @@ import { AppliedFiltersList } from "components/issues";
import { IIssueFilterOptions } from "types"; import { IIssueFilterOptions } from "types";
import { EFilterType } from "store/issues/types"; import { EFilterType } from "store/issues/types";
export const GlobalViewsAppliedFiltersRoot = observer(() => { type Props = {
disableClearFilterOptions?: (keyof IIssueFilterOptions)[];
};
export const GlobalViewsAppliedFiltersRoot: React.FC<Props> = observer((props) => {
const { disableClearFilterOptions } = props;
// router
const router = useRouter(); const router = useRouter();
const { workspaceSlug } = router.query as { workspaceSlug: string; globalViewId: string }; const { workspaceSlug } = router.query as { workspaceSlug: string; globalViewId: string };
// mobx store
const { const {
project: { workspaceProjects }, project: { workspaceProjects },
workspace: { workspaceLabels }, workspace: { workspaceLabels },
@ -83,6 +90,7 @@ export const GlobalViewsAppliedFiltersRoot = observer(() => {
appliedFilters={appliedFilters ?? {}} appliedFilters={appliedFilters ?? {}}
handleClearAllFilters={handleClearAllFilters} handleClearAllFilters={handleClearAllFilters}
handleRemoveFilter={handleRemoveFilter} handleRemoveFilter={handleRemoveFilter}
disableClearFilterOptions={disableClearFilterOptions}
/> />
{/* {storedFilters && viewDetails && areFiltersDifferent(storedFilters, viewDetails.query_data.filters ?? {}) && ( {/* {storedFilters && viewDetails && areFiltersDifferent(storedFilters, viewDetails.query_data.filters ?? {}) && (

View File

@ -8,10 +8,11 @@ import { TStateGroups } from "types";
type Props = { type Props = {
handleRemove: (val: string) => void; handleRemove: (val: string) => void;
values: string[]; values: string[];
disableClearOption?: boolean;
}; };
export const AppliedStateGroupFilters: React.FC<Props> = observer((props) => { export const AppliedStateGroupFilters: React.FC<Props> = observer((props) => {
const { handleRemove, values } = props; const { handleRemove, values, disableClearOption } = props;
return ( return (
<> <>
@ -19,13 +20,15 @@ export const AppliedStateGroupFilters: React.FC<Props> = observer((props) => {
<div key={stateGroup} className="flex items-center gap-1 rounded bg-custom-background-80 p-1 text-xs"> <div key={stateGroup} className="flex items-center gap-1 rounded bg-custom-background-80 p-1 text-xs">
<StateGroupIcon stateGroup={stateGroup as TStateGroups} height="12px" width="12px" /> <StateGroupIcon stateGroup={stateGroup as TStateGroups} height="12px" width="12px" />
{stateGroup} {stateGroup}
<button {!disableClearOption && (
type="button" <button
className="grid place-items-center text-custom-text-300 hover:text-custom-text-200" type="button"
onClick={() => handleRemove(stateGroup)} className="grid place-items-center text-custom-text-300 hover:text-custom-text-200"
> onClick={() => handleRemove(stateGroup)}
<X size={10} strokeWidth={2} /> >
</button> <X size={10} strokeWidth={2} />
</button>
)}
</div> </div>
))} ))}
</> </>

View File

@ -10,10 +10,11 @@ type Props = {
handleRemove: (val: string) => void; handleRemove: (val: string) => void;
states: IState[]; states: IState[];
values: string[]; values: string[];
disableClearOption: boolean | undefined;
}; };
export const AppliedStateFilters: React.FC<Props> = observer((props) => { export const AppliedStateFilters: React.FC<Props> = observer((props) => {
const { handleRemove, states, values } = props; const { handleRemove, states, values, disableClearOption } = props;
return ( return (
<> <>
@ -26,13 +27,15 @@ export const AppliedStateFilters: React.FC<Props> = observer((props) => {
<div key={stateId} className="flex items-center gap-1 rounded bg-custom-background-80 p-1 text-xs"> <div key={stateId} className="flex items-center gap-1 rounded bg-custom-background-80 p-1 text-xs">
<StateGroupIcon color={stateDetails.color} stateGroup={stateDetails.group} height="12px" width="12px" /> <StateGroupIcon color={stateDetails.color} stateGroup={stateDetails.group} height="12px" width="12px" />
{stateDetails.name} {stateDetails.name}
<button {!disableClearOption && (
type="button" <button
className="grid place-items-center text-custom-text-300 hover:text-custom-text-200" type="button"
onClick={() => handleRemove(stateId)} className="grid place-items-center text-custom-text-300 hover:text-custom-text-200"
> onClick={() => handleRemove(stateId)}
<X size={10} strokeWidth={2} /> >
</button> <X size={10} strokeWidth={2} />
</button>
)}
</div> </div>
); );
})} })}

View File

@ -110,7 +110,17 @@ export const AllIssueLayoutRoot: React.FC<Props> = observer((props) => {
</div> </div>
) : ( ) : (
<> <>
<GlobalViewsAppliedFiltersRoot /> <GlobalViewsAppliedFiltersRoot
disableClearFilterOptions={
type === "assigned"
? ["assignees"]
: type === "created"
? ["created_by"]
: type === "subscribed"
? ["subscriber"]
: undefined
}
/>
{Object.keys(getIssues ?? {}).length == 0 ? ( {Object.keys(getIssues ?? {}).length == 0 ? (
<>{/* <GlobalViewEmptyState /> */}</> <>{/* <GlobalViewEmptyState /> */}</>