fix: projects scope dropdown (#1071)

This commit is contained in:
Akshita Goyal
2024-09-11 13:13:53 +05:30
committed by GitHub
parent d3369e3286
commit 223dd70218
5 changed files with 42 additions and 23 deletions

View File

@@ -5,7 +5,7 @@ import { observer } from "mobx-react";
import { useRouter } from "next/navigation";
import { ChevronDown } from "lucide-react";
import { cn } from "@plane/editor";
import { CustomMenu } from "@plane/ui";
import { CustomMenu, Loader } from "@plane/ui";
// plane web constants
import { PROJECT_SCOPES } from "@/plane-web/constants/project";
// plane web hooks
@@ -25,14 +25,13 @@ export const ProjectScopeDropdown: FC<TProjectScopeDropdown> = observer((props)
const router = useRouter();
// derived values
const selectedScope = filters?.scope || EProjectScope.ALL_PROJECTS;
const selectedScopeCount = scopeProjectsCount?.[selectedScope];
const selectedScope = filters?.scope;
const selectedScopeCount = selectedScope && scopeProjectsCount?.[selectedScope];
const DropdownLabel = () => (
<>
<div className="hidden md:flex relative items-center gap-2 w-[150px]">
<div className="flex gap-2 flex-1 my-auto">
{" "}
<div className="whitespace-nowrap font-medium my-auto">
{(PROJECT_SCOPES || []).find((scope) => selectedScope === scope.key)?.label}
</div>
@@ -48,7 +47,6 @@ export const ProjectScopeDropdown: FC<TProjectScopeDropdown> = observer((props)
</div>
</>
);
const DropdownOptions = () =>
(PROJECT_SCOPES || []).map((scope) => (
<CustomMenu.MenuItem
@@ -72,7 +70,7 @@ export const ProjectScopeDropdown: FC<TProjectScopeDropdown> = observer((props)
</CustomMenu.MenuItem>
));
return (
return selectedScope ? (
<CustomMenu
maxHeight={"md"}
className={cn(
@@ -86,5 +84,9 @@ export const ProjectScopeDropdown: FC<TProjectScopeDropdown> = observer((props)
>
<DropdownOptions />
</CustomMenu>
) : (
<Loader>
<Loader.Item width="150px" height="32px" />
</Loader>
);
});

View File

@@ -4,6 +4,7 @@ import { useParams, usePathname } from "next/navigation";
import { ChevronDown } from "lucide-react";
// hooks
import { useWorkspace } from "@/hooks/store";
import { useProjectFilter } from "@/plane-web/hooks/store";
import { ProjectScopeDropdown } from "./dropdowns";
import { ProjectAttributesDropdown, ProjectDisplayFiltersDropdown, ProjectLayoutSelection } from "./header";
@@ -12,9 +13,11 @@ export const ProjectsListMobileHeader = observer(() => {
const { workspaceSlug } = useParams();
const { currentWorkspace } = useWorkspace();
const pathname = usePathname();
const { filters } = useProjectFilter();
const workspaceId = currentWorkspace?.id || undefined;
const isArchived = pathname.includes("/archives");
const selectedScope = filters?.scope;
const customButton = (label: string) => (
<div className="flex text-sm items-center gap-2 neutral-primary text-custom-text-200">
@@ -30,7 +33,7 @@ export const ProjectsListMobileHeader = observer(() => {
<ProjectLayoutSelection workspaceSlug={workspaceSlug.toString()} />
</div>
)}
{!isArchived && (
{!isArchived && selectedScope && (
<div className="border-l border-custom-border-200 flex justify-around w-full">
<ProjectScopeDropdown workspaceSlug={workspaceSlug.toString()} className={"border-none"} />
</div>

View File

@@ -4,10 +4,11 @@ import { FC, useEffect } from "react";
import { observer } from "mobx-react";
// plane web components
import { usePathname, useSearchParams } from "next/navigation";
import { useProject } from "@/hooks/store";
import { ProjectLayoutRoot } from "@/plane-web/components/projects";
// plane web hooks
import { useProjectFilter } from "@/plane-web/hooks/store";
import { EProjectScope } from "@/plane-web/types/workspace-project-filters";
import { EProjectFilters, EProjectScope } from "@/plane-web/types/workspace-project-filters";
type TWorkspaceProjectsRoot = {
workspaceSlug: string;
@@ -21,18 +22,23 @@ export const WorkspaceProjectsRoot: FC<TWorkspaceProjectsRoot> = observer((props
const searchParams = useSearchParams();
const showAllProjects = searchParams.get("show-all-projects");
const pathname = usePathname();
const { loader } = useProject();
useEffect(() => {
if (workspaceSlug)
if (workspaceSlug) {
let filtersToInit = [EProjectFilters.LAYOUT, EProjectFilters.ATTRIBUTES, EProjectFilters.DISPLAY_FILTERS];
filtersToInit = loader ? filtersToInit : [EProjectFilters.SCOPE, ...filtersToInit];
initWorkspaceFilters(
workspaceSlug,
typeof showAllProjects === "string"
? showAllProjects === "true"
? EProjectScope.ALL_PROJECTS
: EProjectScope.MY_PROJECTS
: undefined
: undefined,
filtersToInit
);
}, [workspaceSlug, initWorkspaceFilters, pathname, showAllProjects]);
}
}, [workspaceSlug, initWorkspaceFilters, pathname, showAllProjects, loader]);
return <ProjectLayoutRoot />;
});

View File

@@ -9,6 +9,7 @@ import { IProjectFilterHelper, ProjectFilterHelper } from "@/plane-web/store/wor
// plane web types
import { TProject } from "@/plane-web/types/projects";
import {
EProjectFilters,
EProjectLayouts,
EProjectScope,
TProjectAttributes,
@@ -39,7 +40,7 @@ export interface IProjectFilterStore extends IProjectFilterHelper {
) => TProjectsLayoutStructure[T] | undefined;
// helpers actions
// actions
initWorkspaceFilters: (workspaceSlug: string, scope?: EProjectScope) => void;
initWorkspaceFilters: (workspaceSlug: string, scope?: EProjectScope, filtersToInit?: EProjectFilters[]) => void;
updateScope: (workspaceSlug: string, scope: TProjectScope, setLocalStorage?: boolean) => void;
updateLayout: (workspaceSlug: string, layout: TProjectLayouts, setLocalStorage?: boolean) => void;
updateAttributes: <T extends keyof TProjectAttributes>(
@@ -205,28 +206,29 @@ export class ProjectFilterStore extends ProjectFilterHelper implements IProjectF
* @param { string } workspaceSlug
* @returns { void }
*/
initWorkspaceFilters = (workspaceSlug: string, scope?: EProjectScope): void => {
initWorkspaceFilters = (workspaceSlug: string, scope?: EProjectScope, filtersToInit?: EProjectFilters[]): void => {
const savedFilters = this.handleProjectLocalFilters.get(workspaceSlug);
this.updateScope(
workspaceSlug,
scope ||
(this.scopeProjectsCount[EProjectScope.MY_PROJECTS] > 0
? EProjectScope.MY_PROJECTS
: EProjectScope.ALL_PROJECTS)
);
filtersToInit?.includes(EProjectFilters.SCOPE) &&
this.updateScope(
workspaceSlug,
scope ||
(this.scopeProjectsCount[EProjectScope.MY_PROJECTS] > 0
? EProjectScope.MY_PROJECTS
: EProjectScope.ALL_PROJECTS)
);
if (!this.layoutMap[workspaceSlug]) {
if (!this.layoutMap[workspaceSlug] && filtersToInit?.includes(EProjectFilters.LAYOUT)) {
this.updateLayout(workspaceSlug, savedFilters?.layout || EProjectLayouts.GALLERY, false);
}
if (!this.attributesMap[workspaceSlug]) {
if (!this.attributesMap[workspaceSlug] && filtersToInit?.includes(EProjectFilters.ATTRIBUTES)) {
this.updateAttributes(workspaceSlug, "priority", savedFilters?.attributes?.priority || [], false);
this.updateAttributes(workspaceSlug, "state", savedFilters?.attributes?.state || [], false);
this.updateAttributes(workspaceSlug, "lead", savedFilters?.attributes?.lead || [], false);
this.updateAttributes(workspaceSlug, "members", savedFilters?.attributes?.members || [], false);
this.updateAttributes(workspaceSlug, "access", savedFilters?.attributes?.access || [], false);
}
if (!this.displayFiltersMap[workspaceSlug]) {
if (!this.displayFiltersMap[workspaceSlug] && filtersToInit?.includes(EProjectFilters.DISPLAY_FILTERS)) {
this.updateDisplayFilters(workspaceSlug, "group_by", savedFilters?.display_filters?.group_by || "states", false);
this.updateDisplayFilters(workspaceSlug, "sort_by", savedFilters?.display_filters?.sort_by || "manual", false);
this.updateDisplayFilters(workspaceSlug, "sort_order", savedFilters?.display_filters?.sort_order || "asc", false);

View File

@@ -59,6 +59,12 @@ export type TProjectFilters = {
attributes: TProjectAttributes;
display_filters: TProjectDisplayFilters;
};
export enum EProjectFilters {
SCOPE = "scope",
LAYOUT = "layout",
ATTRIBUTES = "attributes",
DISPLAY_FILTERS = "display_filters",
}
// project_is structure based on the display filter group_by
export type TProjectsBoardLayoutStructure = {