[WEB-1215] chore: display favorite module filter in applied filter section. (#4402)

* [WEB-1215] chore: display `favorite module` filter in applied filter section.

* fix: build errors.
This commit is contained in:
Prateek Shourya 2024-05-08 13:40:58 +05:30 committed by GitHub
parent cc4bb385fe
commit 1cbbddb1be
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 61 additions and 21 deletions

View File

@ -1,5 +1,5 @@
import { X } from "lucide-react"; import { X } from "lucide-react";
import { TModuleFilters } from "@plane/types"; import { TModuleDisplayFilters, TModuleFilters } from "@plane/types";
// components // components
import { AppliedDateFilters, AppliedMembersFilters, AppliedStatusFilters } from "@/components/modules"; import { AppliedDateFilters, AppliedMembersFilters, AppliedStatusFilters } from "@/components/modules";
// helpers // helpers
@ -8,19 +8,30 @@ import { replaceUnderscoreIfSnakeCase } from "@/helpers/string.helper";
type Props = { type Props = {
appliedFilters: TModuleFilters; appliedFilters: TModuleFilters;
isFavoriteFilterApplied?: boolean;
handleClearAllFilters: () => void; handleClearAllFilters: () => void;
handleDisplayFiltersUpdate?: (updatedDisplayProperties: Partial<TModuleDisplayFilters>) => void;
handleRemoveFilter: (key: keyof TModuleFilters, value: string | null) => void; handleRemoveFilter: (key: keyof TModuleFilters, value: string | null) => void;
alwaysAllowEditing?: boolean; alwaysAllowEditing?: boolean;
isArchived?: boolean;
}; };
const MEMBERS_FILTERS = ["lead", "members"]; const MEMBERS_FILTERS = ["lead", "members"];
const DATE_FILTERS = ["start_date", "target_date"]; const DATE_FILTERS = ["start_date", "target_date"];
export const ModuleAppliedFiltersList: React.FC<Props> = (props) => { export const ModuleAppliedFiltersList: React.FC<Props> = (props) => {
const { appliedFilters, handleClearAllFilters, handleRemoveFilter, alwaysAllowEditing } = props; const {
appliedFilters,
isFavoriteFilterApplied,
handleClearAllFilters,
handleRemoveFilter,
handleDisplayFiltersUpdate,
alwaysAllowEditing,
isArchived = false,
} = props;
if (!appliedFilters) return null; if (!appliedFilters && !isFavoriteFilterApplied) return null;
if (Object.keys(appliedFilters).length === 0) return null; if (Object.keys(appliedFilters).length === 0 && !isFavoriteFilterApplied) return null;
const isEditingAllowed = alwaysAllowEditing; const isEditingAllowed = alwaysAllowEditing;
@ -73,6 +84,33 @@ export const ModuleAppliedFiltersList: React.FC<Props> = (props) => {
</div> </div>
); );
})} })}
{!isArchived && isFavoriteFilterApplied && (
<div
key="module_display_filters"
className="flex flex-wrap items-center gap-2 rounded-md border border-custom-border-200 px-2 py-1 capitalize"
>
<div className="flex flex-wrap items-center gap-1.5">
<span className="text-xs text-custom-text-300">Modules</span>
<div className="flex items-center gap-1 rounded p-1 text-xs bg-custom-background-80">
Favorite
{isEditingAllowed && (
<button
type="button"
className="grid place-items-center text-custom-text-300 hover:text-custom-text-200"
onClick={() =>
handleDisplayFiltersUpdate &&
handleDisplayFiltersUpdate({
favorites: !isFavoriteFilterApplied,
})
}
>
<X size={10} strokeWidth={2} />
</button>
)}
</div>
</div>
</div>
)}
{isEditingAllowed && ( {isEditingAllowed && (
<button <button
type="button" type="button"

View File

@ -64,6 +64,7 @@ export const ArchivedModuleLayoutRoot: React.FC = observer(() => {
handleClearAllFilters={() => clearAllFilters(projectId.toString(), "archived")} handleClearAllFilters={() => clearAllFilters(projectId.toString(), "archived")}
handleRemoveFilter={handleRemoveFilter} handleRemoveFilter={handleRemoveFilter}
alwaysAllowEditing alwaysAllowEditing
isArchived
/> />
</div> </div>
)} )}

View File

@ -84,7 +84,7 @@ export const ModuleViewHeader: FC = observer(() => {
if (isSearchOpen && searchQuery.trim() === "") setIsSearchOpen(false); if (isSearchOpen && searchQuery.trim() === "") setIsSearchOpen(false);
}); });
const isFiltersApplied = calculateTotalFilters(filters ?? {}) !== 0; const isFiltersApplied = calculateTotalFilters(filters ?? {}) !== 0 || displayFilters?.favorites;
return ( return (
<div className="hidden h-full sm:flex items-center gap-3 self-end"> <div className="hidden h-full sm:flex items-center gap-3 self-end">

View File

@ -4,13 +4,7 @@ import { useRouter } from "next/router";
// components // components
import { ListLayout } from "@/components/core/list"; import { ListLayout } from "@/components/core/list";
import { EmptyState } from "@/components/empty-state"; import { EmptyState } from "@/components/empty-state";
import { import { ModuleCardItem, ModuleListItem, ModulePeekOverview, ModulesListGanttChartView } from "@/components/modules";
ModuleCardItem,
ModuleListItem,
ModulePeekOverview,
ModuleViewHeader,
ModulesListGanttChartView,
} from "@/components/modules";
import { CycleModuleBoardLayout, CycleModuleListLayout, GanttLayoutLoader } from "@/components/ui"; import { CycleModuleBoardLayout, CycleModuleListLayout, GanttLayoutLoader } from "@/components/ui";
// constants // constants
import { EmptyStateType } from "@/constants/empty-state"; import { EmptyStateType } from "@/constants/empty-state";
@ -73,12 +67,6 @@ export const ModulesListView: React.FC = observer(() => {
return ( return (
<> <>
<div className="h-[50px] flex-shrink-0 w-full border-b border-custom-border-200 px-6 relative flex items-center gap-4 justify-between">
<div className="flex items-center">
<span className="block text-sm font-medium">Module name</span>
</div>
<ModuleViewHeader />
</div>
{displayFilters?.layout === "list" && ( {displayFilters?.layout === "list" && (
<div className="h-full overflow-y-auto"> <div className="h-full overflow-y-auto">
<div className="flex h-full w-full justify-between"> <div className="flex h-full w-full justify-between">

View File

@ -7,7 +7,7 @@ import { TModuleFilters } from "@plane/types";
import { PageHead } from "@/components/core"; import { PageHead } from "@/components/core";
import { EmptyState } from "@/components/empty-state"; import { EmptyState } from "@/components/empty-state";
import { ModulesListHeader } from "@/components/headers"; import { ModulesListHeader } from "@/components/headers";
import { ModuleAppliedFiltersList, ModulesListView } from "@/components/modules"; import { ModuleViewHeader, ModuleAppliedFiltersList, ModulesListView } from "@/components/modules";
// types // types
// hooks // hooks
import ModulesListMobileHeader from "@/components/modules/moduels-list-mobile-header"; import ModulesListMobileHeader from "@/components/modules/moduels-list-mobile-header";
@ -22,7 +22,8 @@ const ProjectModulesPage: NextPageWithLayout = observer(() => {
const { workspaceSlug, projectId } = router.query; const { workspaceSlug, projectId } = router.query;
// store // store
const { getProjectById, currentProjectDetails } = useProject(); const { getProjectById, currentProjectDetails } = useProject();
const { currentProjectFilters, clearAllFilters, updateFilters } = useModuleFilter(); const { currentProjectFilters, currentProjectDisplayFilters, clearAllFilters, updateFilters, updateDisplayFilters } =
useModuleFilter();
// derived values // derived values
const project = projectId ? getProjectById(projectId.toString()) : undefined; const project = projectId ? getProjectById(projectId.toString()) : undefined;
const pageTitle = project?.name ? `${project?.name} - Modules` : undefined; const pageTitle = project?.name ? `${project?.name} - Modules` : undefined;
@ -57,12 +58,23 @@ const ProjectModulesPage: NextPageWithLayout = observer(() => {
<> <>
<PageHead title={pageTitle} /> <PageHead title={pageTitle} />
<div className="h-full w-full flex flex-col"> <div className="h-full w-full flex flex-col">
{calculateTotalFilters(currentProjectFilters ?? {}) !== 0 && ( <div className="h-[50px] flex-shrink-0 w-full border-b border-custom-border-200 px-6 relative flex items-center gap-4 justify-between">
<div className="flex items-center">
<span className="block text-sm font-medium">Module name</span>
</div>
<ModuleViewHeader />
</div>
{(calculateTotalFilters(currentProjectFilters ?? {}) !== 0 || currentProjectDisplayFilters?.favorites) && (
<div className="border-b border-custom-border-200 px-5 py-3"> <div className="border-b border-custom-border-200 px-5 py-3">
<ModuleAppliedFiltersList <ModuleAppliedFiltersList
appliedFilters={currentProjectFilters ?? {}} appliedFilters={currentProjectFilters ?? {}}
isFavoriteFilterApplied={currentProjectDisplayFilters?.favorites ?? false}
handleClearAllFilters={() => clearAllFilters(`${projectId}`)} handleClearAllFilters={() => clearAllFilters(`${projectId}`)}
handleRemoveFilter={handleRemoveFilter} handleRemoveFilter={handleRemoveFilter}
handleDisplayFiltersUpdate={(val) => {
if (!projectId) return;
updateDisplayFilters(projectId.toString(), val);
}}
alwaysAllowEditing alwaysAllowEditing
/> />
</div> </div>

View File

@ -177,6 +177,7 @@ export class ModuleFilterStore implements IModuleFilterStore {
clearAllFilters = (projectId: string, state: keyof TModuleFiltersByState = "default") => { clearAllFilters = (projectId: string, state: keyof TModuleFiltersByState = "default") => {
runInAction(() => { runInAction(() => {
this.filters[projectId][state] = {}; this.filters[projectId][state] = {};
this.displayFilters[projectId].favorites = false;
}); });
}; };
} }