From ec3cad1f251a73513b4bdb6e764522e757bf3edf Mon Sep 17 00:00:00 2001 From: guru_sainath Date: Thu, 25 Jan 2024 14:27:35 +0530 Subject: [PATCH] chore: applying query params to the global issues filters in the global views (#3464) * chore: applying filters from the route params to the global issue filters store and Typos * chore: enabled posthog * fix: labels disbaled and loader while creating the label in isse detail and relation modal loader and mutation issue --- .../modals/existing-issues-list-modal.tsx | 16 +++++-- .../issue-detail/label/create-label.tsx | 5 ++- .../roots/profile-issues-root.tsx | 4 +- .../roots/all-issue-layout-root.tsx | 42 +++++++++++++++++-- ...s.ts => use-workspace-issue-properties.ts} | 6 +-- web/store/estimate.store.ts | 6 +-- web/store/issue/workspace/filter.store.ts | 13 +++--- 7 files changed, 70 insertions(+), 22 deletions(-) rename web/hooks/{use-worskspace-issue-properties.ts => use-workspace-issue-properties.ts} (76%) diff --git a/web/components/core/modals/existing-issues-list-modal.tsx b/web/components/core/modals/existing-issues-list-modal.tsx index 09c9bfc52..058aae38c 100644 --- a/web/components/core/modals/existing-issues-list-modal.tsx +++ b/web/components/core/modals/existing-issues-list-modal.tsx @@ -27,8 +27,8 @@ export const ExistingIssuesListModal: React.FC = (props) => { // states const [searchTerm, setSearchTerm] = useState(""); const [issues, setIssues] = useState([]); - const [isSearching, setIsSearching] = useState(false); const [selectedIssues, setSelectedIssues] = useState([]); + const [isSearching, setIsSearching] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false); const [isWorkspaceLevel, setIsWorkspaceLevel] = useState(false); @@ -72,8 +72,7 @@ export const ExistingIssuesListModal: React.FC = (props) => { useEffect(() => { if (!isOpen || !workspaceSlug || !projectId) return; - - setIsSearching(true); + if (issues.length <= 0) setIsSearching(true); projectService .projectIssuesSearch(workspaceSlug as string, projectId as string, { @@ -83,7 +82,16 @@ export const ExistingIssuesListModal: React.FC = (props) => { }) .then((res) => setIssues(res)) .finally(() => setIsSearching(false)); - }, [debouncedSearchTerm, isOpen, isWorkspaceLevel, projectId, searchParams, workspaceSlug]); + }, [issues, debouncedSearchTerm, isOpen, isWorkspaceLevel, projectId, searchParams, workspaceSlug]); + + useEffect(() => { + setSearchTerm(""); + setIssues([]); + setSelectedIssues([]); + setIsSearching(false); + setIsSubmitting(false); + setIsWorkspaceLevel(false); + }, [isOpen]); return ( <> diff --git a/web/components/issues/issue-detail/label/create-label.tsx b/web/components/issues/issue-detail/label/create-label.tsx index 7babaee00..72bc034f8 100644 --- a/web/components/issues/issue-detail/label/create-label.tsx +++ b/web/components/issues/issue-detail/label/create-label.tsx @@ -1,5 +1,5 @@ import { FC, useState, Fragment, useEffect } from "react"; -import { Plus, X } from "lucide-react"; +import { Plus, X, Loader } from "lucide-react"; import { Controller, useForm } from "react-hook-form"; import { TwitterPicker } from "react-color"; import { Popover, Transition } from "@headlessui/react"; @@ -138,6 +138,7 @@ export const LabelCreate: FC = (props) => { hasError={Boolean(errors.name)} placeholder="Title" className="w-full" + disabled={isSubmitting} /> )} /> @@ -150,7 +151,7 @@ export const LabelCreate: FC = (props) => { )} diff --git a/web/components/issues/issue-layouts/filters/applied-filters/roots/profile-issues-root.tsx b/web/components/issues/issue-layouts/filters/applied-filters/roots/profile-issues-root.tsx index 7b483ef98..7a6c39336 100644 --- a/web/components/issues/issue-layouts/filters/applied-filters/roots/profile-issues-root.tsx +++ b/web/components/issues/issue-layouts/filters/applied-filters/roots/profile-issues-root.tsx @@ -7,14 +7,14 @@ import { AppliedFiltersList } from "components/issues"; // types import { IIssueFilterOptions } from "@plane/types"; import { EIssueFilterType, EIssuesStoreType } from "constants/issue"; -import { useWorskspaceIssueProperties } from "hooks/use-worskspace-issue-properties"; +import { useWorkspaceIssueProperties } from "hooks/use-workspace-issue-properties"; export const ProfileIssuesAppliedFiltersRoot: React.FC = observer(() => { // router const router = useRouter(); const { workspaceSlug, userId } = router.query; //swr hook for fetching issue properties - useWorskspaceIssueProperties(workspaceSlug); + useWorkspaceIssueProperties(workspaceSlug); // store hooks const { issuesFilter: { issueFilters, updateFilters }, diff --git a/web/components/issues/issue-layouts/roots/all-issue-layout-root.tsx b/web/components/issues/issue-layouts/roots/all-issue-layout-root.tsx index 394e8eafb..b8a2b571b 100644 --- a/web/components/issues/issue-layouts/roots/all-issue-layout-root.tsx +++ b/web/components/issues/issue-layouts/roots/all-issue-layout-root.tsx @@ -2,9 +2,10 @@ import React, { useCallback, useMemo } from "react"; import { useRouter } from "next/router"; import { observer } from "mobx-react-lite"; import useSWR from "swr"; +import isEmpty from "lodash/isEmpty"; // hooks import { useApplication, useGlobalView, useIssues, useProject, useUser } from "hooks/store"; -import { useWorskspaceIssueProperties } from "hooks/use-worskspace-issue-properties"; +import { useWorkspaceIssueProperties } from "hooks/use-workspace-issue-properties"; // components import { GlobalViewsAppliedFiltersRoot, IssuePeekOverview } from "components/issues"; import { SpreadsheetView } from "components/issues/issue-layouts"; @@ -17,7 +18,7 @@ import { TIssue, IIssueDisplayFilterOptions } from "@plane/types"; import { EIssueActions } from "../types"; // constants import { EUserProjectRoles } from "constants/project"; -import { EIssueFilterType, EIssuesStoreType } from "constants/issue"; +import { EIssueFilterType, EIssuesStoreType, ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "constants/issue"; import { ALL_ISSUES_EMPTY_STATE_DETAILS, EUserWorkspaceRoles } from "constants/workspace"; export const AllIssueLayoutRoot: React.FC = observer(() => { @@ -25,7 +26,7 @@ export const AllIssueLayoutRoot: React.FC = observer(() => { const router = useRouter(); const { workspaceSlug, globalViewId } = router.query; //swr hook for fetching issue properties - useWorskspaceIssueProperties(workspaceSlug); + useWorkspaceIssueProperties(workspaceSlug); // store const { commandPalette: commandPaletteStore } = useApplication(); const { @@ -47,6 +48,40 @@ export const AllIssueLayoutRoot: React.FC = observer(() => { const emptyStateImage = getEmptyStateImagePath("all-issues", currentView, currentUser?.theme.theme === "light"); + // filter init from the query params + + const routerFilterParams = () => { + if ( + workspaceSlug && + globalViewId && + ["all-issues", "assigned", "created", "subscribed"].includes(globalViewId.toString()) + ) { + const routerQueryParams = { ...router.query }; + const { ["workspaceSlug"]: _workspaceSlug, ["globalViewId"]: _globalViewId, ...filters } = routerQueryParams; + + let issueFilters: any = {}; + Object.keys(filters).forEach((key) => { + const filterKey: any = key; + const filterValue = filters[key]?.toString() || undefined; + if ( + ISSUE_DISPLAY_FILTERS_BY_LAYOUT.my_issues.spreadsheet.filters.includes(filterKey) && + filterKey && + filterValue + ) + issueFilters = { ...issueFilters, [filterKey]: filterValue.split(",") }; + }); + + if (!isEmpty(filters)) + updateFilters( + workspaceSlug.toString(), + undefined, + EIssueFilterType.FILTERS, + issueFilters, + globalViewId.toString() + ); + } + }; + useSWR(workspaceSlug ? `WORKSPACE_GLOBAL_VIEWS${workspaceSlug}` : null, async () => { if (workspaceSlug) { await fetchAllGlobalViews(workspaceSlug.toString()); @@ -60,6 +95,7 @@ export const AllIssueLayoutRoot: React.FC = observer(() => { await fetchAllGlobalViews(workspaceSlug.toString()); await fetchFilters(workspaceSlug.toString(), globalViewId.toString()); await fetchIssues(workspaceSlug.toString(), globalViewId.toString(), issueIds ? "mutation" : "init-loader"); + routerFilterParams(); } } ); diff --git a/web/hooks/use-worskspace-issue-properties.ts b/web/hooks/use-workspace-issue-properties.ts similarity index 76% rename from web/hooks/use-worskspace-issue-properties.ts rename to web/hooks/use-workspace-issue-properties.ts index 0accc3ec2..f6c1c6c2f 100644 --- a/web/hooks/use-worskspace-issue-properties.ts +++ b/web/hooks/use-workspace-issue-properties.ts @@ -1,12 +1,12 @@ import useSWR from "swr"; import { useEstimate, useLabel, useProjectState } from "./store"; -export const useWorskspaceIssueProperties = (workspaceSlug: string | string[] | undefined) => { +export const useWorkspaceIssueProperties = (workspaceSlug: string | string[] | undefined) => { const { fetchWorkspaceLabels } = useLabel(); const { fetchWorkspaceStates } = useProjectState(); - const { fetchWorskpaceEstimates } = useEstimate(); + const { fetchWorkspaceEstimates } = useEstimate(); // fetch workspace labels useSWR( @@ -23,6 +23,6 @@ export const useWorskspaceIssueProperties = (workspaceSlug: string | string[] | // fetch workspace estimates useSWR( workspaceSlug ? `WORKSPACE_ESTIMATES_${workspaceSlug}` : null, - workspaceSlug ? () => fetchWorskpaceEstimates(workspaceSlug.toString()) : null + workspaceSlug ? () => fetchWorkspaceEstimates(workspaceSlug.toString()) : null ); }; diff --git a/web/store/estimate.store.ts b/web/store/estimate.store.ts index 33c36ec52..beddd52ab 100644 --- a/web/store/estimate.store.ts +++ b/web/store/estimate.store.ts @@ -23,7 +23,7 @@ export interface IEstimateStore { getProjectActiveEstimateDetails: (projectId: string) => IEstimate | null; // fetch actions fetchProjectEstimates: (workspaceSlug: string, projectId: string) => Promise; - fetchWorskpaceEstimates: (workspaceSlug: string) => Promise; + fetchWorkspaceEstimates: (workspaceSlug: string) => Promise; // crud actions createEstimate: (workspaceSlug: string, projectId: string, data: IEstimateFormData) => Promise; updateEstimate: ( @@ -56,7 +56,7 @@ export class EstimateStore implements IEstimateStore { activeEstimateDetails: computed, // actions fetchProjectEstimates: action, - fetchWorskpaceEstimates: action, + fetchWorkspaceEstimates: action, createEstimate: action, updateEstimate: action, deleteEstimate: action, @@ -158,7 +158,7 @@ export class EstimateStore implements IEstimateStore { * @param workspaceSlug * @param projectId */ - fetchWorskpaceEstimates = async (workspaceSlug: string) => + fetchWorkspaceEstimates = async (workspaceSlug: string) => await this.estimateService.getWorkspaceEstimatesList(workspaceSlug).then((response) => { runInAction(() => { response.forEach((estimate) => { diff --git a/web/store/issue/workspace/filter.store.ts b/web/store/issue/workspace/filter.store.ts index a40d2a42f..df207fee9 100644 --- a/web/store/issue/workspace/filter.store.ts +++ b/web/store/issue/workspace/filter.store.ts @@ -162,14 +162,17 @@ export class WorkspaceIssuesFilter extends IssueFilterHelperStore implements IWo ) => { try { if (!viewId) throw new Error("View id is required"); + const issueFilters = this.getIssueFilters(viewId); - if (isEmpty(this.filters) || isEmpty(this.filters[viewId]) || isEmpty(filters)) return; + console.log("issueFilters", issueFilters); + + if (!issueFilters || isEmpty(filters)) return; const _filters = { - filters: this.filters[viewId].filters as IIssueFilterOptions, - displayFilters: this.filters[viewId].displayFilters as IIssueDisplayFilterOptions, - displayProperties: this.filters[viewId].displayProperties as IIssueDisplayProperties, - kanbanFilters: this.filters[viewId].kanbanFilters as TIssueKanbanFilters, + filters: issueFilters.filters as IIssueFilterOptions, + displayFilters: issueFilters.displayFilters as IIssueDisplayFilterOptions, + displayProperties: issueFilters.displayProperties as IIssueDisplayProperties, + kanbanFilters: issueFilters.kanbanFilters as TIssueKanbanFilters, }; switch (type) {