From f90595ca31bae42c619108bffe1be4a1ccdfb770 Mon Sep 17 00:00:00 2001 From: gurusainath Date: Fri, 9 Feb 2024 14:33:22 +0530 Subject: [PATCH] chore: updated ui and store --- web/components/view/all-issues-root.tsx | 42 +++--------- .../view/applied-filters/filter-item.tsx | 30 ++++----- .../view/applied-filters/filter.tsx | 53 ++++++++------- .../view/applied-filters/helper.tsx | 66 ------------------- web/components/view/applied-filters/root.tsx | 22 +++---- .../view/display-filters/dropdown.tsx | 32 ++++----- .../display-properties/property-selection.tsx | 40 +++++++++++ .../view/display-properties/root.tsx | 32 ++++----- web/components/view/filters/dropdown.tsx | 31 ++++----- .../view/filters/filter-item-root.tsx | 23 +------ web/components/view/filters/filter-item.tsx | 16 ++--- .../view/filters/filter-selection.tsx | 5 +- web/components/view/filters/root.tsx | 6 +- web/components/view/index.ts | 1 + web/components/view/layout.tsx | 2 +- web/components/view/types.d.ts | 6 +- .../[workspaceSlug]/views/public/[viewId].tsx | 5 +- web/store/view/helpers/filters_helpers.ts | 53 +++++++-------- web/store/view/root.store.ts | 1 - web/store/view/view.store.ts | 41 ++++++++---- 20 files changed, 221 insertions(+), 286 deletions(-) delete mode 100644 web/components/view/applied-filters/helper.tsx create mode 100644 web/components/view/display-properties/property-selection.tsx diff --git a/web/components/view/all-issues-root.tsx b/web/components/view/all-issues-root.tsx index 989e8ccf8..65422042b 100644 --- a/web/components/view/all-issues-root.tsx +++ b/web/components/view/all-issues-root.tsx @@ -10,10 +10,8 @@ import { ViewRoot, ViewCreateEditForm, ViewLayoutRoot, - ViewFiltersRoot, ViewFiltersDropdown, ViewDisplayFiltersDropdown, - ViewDisplayPropertiesRoot, ViewAppliedFiltersRoot, ViewDuplicateConfirmationModal, ViewDeleteConfirmationModal, @@ -73,11 +71,12 @@ export const AllIssuesViewRoot: FC = observer((props) => { () => ({ setName: (name: string) => viewDetailStore?.setName(name), setDescription: (name: string) => viewDetailStore?.setDescription(name), - setFilters: (filters: Partial) => viewDetailStore?.setFilters(filters), + setFilters: (filterKey: keyof TViewFilters, filterValue: "clear_all" | string) => + viewDetailStore?.setFilters(filterKey, filterValue), setDisplayFilters: (display_filters: Partial) => viewDetailStore?.setDisplayFilters(display_filters), - setDisplayProperties: (display_properties: Partial) => - viewDetailStore?.setDisplayProperties(display_properties), + setDisplayProperties: (displayPropertyKey: keyof TViewDisplayProperties) => + viewDetailStore?.setDisplayProperties(displayPropertyKey), localViewCreateEdit: (viewId: string | undefined) => { if (viewId === undefined) { const viewPayload = viewLocalPayload; @@ -171,29 +170,8 @@ export const AllIssuesViewRoot: FC = observer((props) => { /> -
- -
- - {/*
- -
*/} - -
- {/*
+
+
= observer((props) => { viewType={viewType} viewOperations={viewOperations} /> -
*/} +
-
+
= observer((props) => { viewId={viewId} viewType={viewType} viewOperations={viewOperations} - baseRoute={baseRoute} displayDropdownText={false} />
@@ -232,12 +209,11 @@ export const AllIssuesViewRoot: FC = observer((props) => { viewId={viewId} viewType={viewType} viewOperations={viewOperations} - baseRoute={baseRoute} displayDropdownText={false} />
-
+
diff --git a/web/components/view/applied-filters/filter-item.tsx b/web/components/view/applied-filters/filter-item.tsx index 916265937..0c7b0c3cc 100644 --- a/web/components/view/applied-filters/filter-item.tsx +++ b/web/components/view/applied-filters/filter-item.tsx @@ -1,9 +1,10 @@ import { FC } from "react"; -import { User, X } from "lucide-react"; +import { ImagePlus, X } from "lucide-react"; // hooks -import { useViewDetail } from "hooks/store"; +import { useViewFilter } from "hooks/store"; // types import { TViewFilters, TViewTypes } from "@plane/types"; +import { TViewOperations } from "../types"; type TViewAppliedFiltersItem = { workspaceSlug: string; @@ -11,33 +12,30 @@ type TViewAppliedFiltersItem = { viewId: string; viewType: TViewTypes; filterKey: keyof TViewFilters; - filterId: string; + propertyId: string; + viewOperations: TViewOperations; }; export const ViewAppliedFiltersItem: FC = (props) => { - const { workspaceSlug, projectId, viewId, viewType, filterKey, filterId } = props; + const { workspaceSlug, projectId, filterKey, propertyId, viewOperations } = props; // hooks - const viewDetailStore = useViewDetail(workspaceSlug, projectId, viewId, viewType); + const viewFilterHelper = useViewFilter(workspaceSlug, projectId); + + const propertyDetail = viewFilterHelper?.propertyDetails(filterKey, propertyId) || undefined; const removeFilterOption = () => { - const filters = viewDetailStore?.appliedFilters?.filters; - if (!filters) return; - const filterValues = filters[filterKey]; - const updatedFilterValues = filterValues.filter((value) => value !== filterId); - viewDetailStore?.setFilters({ [filterKey]: updatedFilterValues }); + viewOperations?.setFilters(filterKey, propertyId); }; return (
- -
-
- {filterKey} - {filterId} + {propertyDetail?.icon || }
+
{propertyDetail?.label || propertyId}
= observer((props) => { - const { workspaceSlug, projectId, viewId, viewType, filterKey } = props; + const { workspaceSlug, projectId, viewId, viewType, filterKey, viewOperations } = props; const viewDetailStore = useViewDetail(workspaceSlug, projectId, viewId, viewType); - const filterKeyValue = + const propertyValues = viewDetailStore?.appliedFilters?.filters && !isEmpty(viewDetailStore?.appliedFilters?.filters) ? viewDetailStore?.appliedFilters?.filters?.[filterKey] || undefined : undefined; - const clearFilter = () => viewDetailStore?.setFilters({ [filterKey]: [] }); + const clearPropertyFilter = () => viewDetailStore?.setFilters(filterKey, "clear_all"); - if (!filterKeyValue || filterKeyValue.length <= -1) return <>; + if (!propertyValues || propertyValues.length <= 0) return <>; return ( -
-
{generateTitle(filterKey)}
-
- {["1", "2", "3", "4"].map((filterId) => ( - - - - ))} +
+
{filterKey.replaceAll("_", " ")}
+
+ {propertyValues.length >= 100 ? ( +
+ {propertyValues.length} {filterKey.replaceAll("_", " ")}s +
+ ) : ( + <> + {propertyValues.map((propertyId) => ( + + + + ))} + + )}
diff --git a/web/components/view/applied-filters/helper.tsx b/web/components/view/applied-filters/helper.tsx deleted file mode 100644 index 52318fc8a..000000000 --- a/web/components/view/applied-filters/helper.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { ReactNode } from "react"; -import isEmpty from "lodash/isEmpty"; -// types -import { TViewFilters } from "@plane/types"; - -type TComputedAppliedFilters = { - key: string; - title: string; - selectedOptions?: { id: string; icon: ""; title: ""; component: ReactNode }[]; - dropdownOptions?: { id: string; icon: ""; title: ""; component: ReactNode }[]; -}[]; - -export const filterOptions = (key: keyof TViewFilters, selectedFilters: string[]) => { - switch (key) { - case "project": - return []; - case "priority": - return []; - case "state": - return []; - case "state_group": - return []; - case "assignees": - return []; - case "mentions": - return []; - case "subscriber": - return []; - case "created_by": - return []; - case "labels": - return []; - case "start_date": - return []; - case "target_date": - return []; - default: - return []; - } -}; - -export const generateTitle = (title: string) => - title - .split("_") - .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) - .join(" "); - -export const constructAppliedFilters = (filters: TViewFilters): TComputedAppliedFilters => { - const appliedFilters: TComputedAppliedFilters = []; - - if (filters && !isEmpty(filters)) { - Object.keys(filters).forEach((_filterKey) => { - const _key = _filterKey as keyof TViewFilters; - const _value = filters[_key]; - - if (_value && !isEmpty(_value)) { - appliedFilters.push({ - key: _key, - title: generateTitle(_key), - }); - } - }); - } - - return appliedFilters; -}; diff --git a/web/components/view/applied-filters/root.tsx b/web/components/view/applied-filters/root.tsx index 4e977b7e6..855667c8f 100644 --- a/web/components/view/applied-filters/root.tsx +++ b/web/components/view/applied-filters/root.tsx @@ -19,7 +19,7 @@ type TViewAppliedFiltersRoot = { }; export const ViewAppliedFiltersRoot: FC = observer((props) => { - const { workspaceSlug, projectId, viewId, viewType } = props; + const { workspaceSlug, projectId, viewId, viewType, viewOperations } = props; // hooks const viewDetailStore = useViewDetail(workspaceSlug, projectId, viewId, viewType); @@ -28,16 +28,14 @@ export const ViewAppliedFiltersRoot: FC = observer((pro ? Object.keys(viewDetailStore?.appliedFilters?.filters) : undefined; - const clearAllFilters = () => { - const clearedFilters: Partial> = {}; - filterKeys?.forEach((key) => { - const _key = key as keyof TViewFilters; - clearedFilters[_key] = []; - }); - viewDetailStore?.setFilters(clearedFilters); - }; + const clearAllFilters = () => viewDetailStore?.setFilters(undefined, "clear_all"); - if (!filterKeys) return <>; + if (!filterKeys || !viewDetailStore?.isFiltersApplied) + return ( +
+ No filters applied. Apply filters to create views. +
+ ); return (
{filterKeys.map((key) => { @@ -50,12 +48,14 @@ export const ViewAppliedFiltersRoot: FC = observer((pro viewId={viewId} viewType={viewType} filterKey={filterKey} + viewOperations={viewOperations} /> ); })} +
Clear All
diff --git a/web/components/view/display-filters/dropdown.tsx b/web/components/view/display-filters/dropdown.tsx index d6a1bf1e1..bc8d737c0 100644 --- a/web/components/view/display-filters/dropdown.tsx +++ b/web/components/view/display-filters/dropdown.tsx @@ -7,6 +7,8 @@ import { MonitorDot } from "lucide-react"; import useOutsideClickDetector from "hooks/use-outside-click-detector"; // components import { ViewDisplayPropertiesRoot } from "../"; +// ui +import { Tooltip } from "@plane/ui"; // types import { TViewOperations } from "../types"; import { TViewTypes } from "@plane/types"; @@ -17,22 +19,12 @@ type TViewDisplayFiltersDropdown = { viewId: string; viewType: TViewTypes; viewOperations: TViewOperations; - baseRoute: string; children?: ReactNode; displayDropdownText?: boolean; }; export const ViewDisplayFiltersDropdown: FC = observer((props) => { - const { - workspaceSlug, - projectId, - viewId, - viewType, - viewOperations, - baseRoute, - children, - displayDropdownText = true, - } = props; + const { workspaceSlug, projectId, viewId, viewType, viewOperations, children, displayDropdownText = true } = props; // state const [dropdownToggle, setDropdownToggle] = useState(false); // refs @@ -74,22 +66,24 @@ export const ViewDisplayFiltersDropdown: FC = obser onClick={handleDropdownToggle} > {children ? ( - {children} +
{children}
) : ( -
+
-
- + > +
+ +
+ {displayDropdownText &&
Display
}
- {displayDropdownText &&
Display
} -
+ )} diff --git a/web/components/view/display-properties/property-selection.tsx b/web/components/view/display-properties/property-selection.tsx new file mode 100644 index 000000000..2e34eb25c --- /dev/null +++ b/web/components/view/display-properties/property-selection.tsx @@ -0,0 +1,40 @@ +import { FC } from "react"; +import { observer } from "mobx-react-lite"; +// hooks +import { useViewDetail } from "hooks/store"; +// types +import { TViewDisplayProperties, TViewTypes } from "@plane/types"; +import { TViewOperations } from "../types"; + +type TViewDisplayPropertySelection = { + workspaceSlug: string; + projectId: string | undefined; + viewId: string; + viewType: TViewTypes; + viewOperations: TViewOperations; + property: keyof TViewDisplayProperties; +}; + +export const ViewDisplayPropertySelection: FC = observer((props) => { + const { workspaceSlug, projectId, viewId, viewType, viewOperations, property } = props; + // hooks + const viewDetailStore = useViewDetail(workspaceSlug, projectId, viewId, viewType); + + const propertyIsSelected = viewDetailStore?.appliedFilters?.display_properties?.[property]; + + const handlePropertySelection = () => viewOperations?.setDisplayProperties(property); + + return ( +
+ {["key"].includes(property) ? "ID" : property.replaceAll("_", " ")} +
+ ); +}); diff --git a/web/components/view/display-properties/root.tsx b/web/components/view/display-properties/root.tsx index 5c2601dca..ad027b047 100644 --- a/web/components/view/display-properties/root.tsx +++ b/web/components/view/display-properties/root.tsx @@ -1,4 +1,7 @@ -import { FC } from "react"; +import { FC, Fragment } from "react"; +import { observer } from "mobx-react-lite"; +// components +import { ViewDisplayPropertySelection } from "../"; // types import { TViewDisplayProperties, TViewTypes } from "@plane/types"; import { TViewOperations } from "../types"; @@ -11,7 +14,7 @@ type TViewDisplayPropertiesRoot = { viewOperations: TViewOperations; }; -export const ViewDisplayPropertiesRoot: FC = (props) => { +export const ViewDisplayPropertiesRoot: FC = observer((props) => { const { workspaceSlug, projectId, viewId, viewType, viewOperations } = props; const displayProperties: Partial[] = [ @@ -31,20 +34,17 @@ export const ViewDisplayPropertiesRoot: FC = (props) return (
{displayProperties.map((property) => ( -
{}} - > - {["key"].includes(property) ? "ID" : property.replaceAll("_", " ")} -
+ + + ))}
); -}; +}); diff --git a/web/components/view/filters/dropdown.tsx b/web/components/view/filters/dropdown.tsx index 0a22ccaf6..8a0a0b1af 100644 --- a/web/components/view/filters/dropdown.tsx +++ b/web/components/view/filters/dropdown.tsx @@ -7,6 +7,8 @@ import { ListFilter, Search } from "lucide-react"; import useOutsideClickDetector from "hooks/use-outside-click-detector"; // components import { ViewFiltersRoot } from "../"; +// ui +import { Tooltip } from "@plane/ui"; // types import { TViewOperations } from "../types"; import { TViewTypes } from "@plane/types"; @@ -17,22 +19,12 @@ type TViewFiltersDropdown = { viewId: string; viewType: TViewTypes; viewOperations: TViewOperations; - baseRoute: string; children?: ReactNode; displayDropdownText?: boolean; }; export const ViewFiltersDropdown: FC = observer((props) => { - const { - workspaceSlug, - projectId, - viewId, - viewType, - viewOperations, - baseRoute, - children, - displayDropdownText = true, - } = props; + const { workspaceSlug, projectId, viewId, viewType, viewOperations, children, displayDropdownText = true } = props; // state const [dropdownToggle, setDropdownToggle] = useState(false); const [query, setQuery] = useState(""); @@ -77,20 +69,22 @@ export const ViewFiltersDropdown: FC = observer((props) => {children ? ( {children} ) : ( -
+
-
- + > +
+ +
+ {displayDropdownText &&
Filters
}
- {displayDropdownText &&
Filters
} -
+ )} @@ -122,7 +116,6 @@ export const ViewFiltersDropdown: FC = observer((props) => viewId={viewId} viewType={viewType} viewOperations={viewOperations} - baseRoute={baseRoute} />
diff --git a/web/components/view/filters/filter-item-root.tsx b/web/components/view/filters/filter-item-root.tsx index e6da91ed9..0f37d4b40 100644 --- a/web/components/view/filters/filter-item-root.tsx +++ b/web/components/view/filters/filter-item-root.tsx @@ -1,10 +1,7 @@ import { FC, useState } from "react"; import { observer } from "mobx-react-lite"; -import concat from "lodash/concat"; -import pull from "lodash/pull"; -import uniq from "lodash/uniq"; // hooks -import { useViewFilter, useViewDetail } from "hooks/store"; +import { useViewFilter } from "hooks/store"; // components import { ViewFiltersItem, ViewFilterSelection } from "../"; // types @@ -17,15 +14,13 @@ type TViewFiltersItemRoot = { viewId: string; viewType: TViewTypes; viewOperations: TViewOperations; - baseRoute: string; filterKey: keyof TViewFilters; }; export const ViewFiltersItemRoot: FC = observer((props) => { - const { workspaceSlug, projectId, viewId, viewType, viewOperations, baseRoute, filterKey } = props; + const { workspaceSlug, projectId, viewId, viewType, viewOperations, filterKey } = props; // hooks const viewFilterHelper = useViewFilter(workspaceSlug, projectId); - const viewDetailStore = useViewDetail(workspaceSlug, projectId, viewId, viewType); // state const [viewAll, setViewAll] = useState(false); @@ -33,13 +28,7 @@ export const ViewFiltersItemRoot: FC = observer((props) => const filterPropertyIds = propertyIds.length > 5 ? (viewAll ? propertyIds : propertyIds.slice(0, 5)) : propertyIds; - const handlePropertySelection = (_propertyId: string) => { - const _propertyIds = viewDetailStore?.appliedFilters?.filters?.[filterKey] || []; - const isSelected = _propertyIds?.includes(_propertyId) || false; - viewOperations?.setFilters({ - [filterKey]: isSelected ? pull(_propertyIds, _propertyId) : uniq(concat(_propertyIds, [_propertyId])), - }); - }; + const handlePropertySelection = (_propertyId: string) => viewOperations?.setFilters(filterKey, _propertyId); if (propertyIds.length <= 0) return
No items are available.
; @@ -56,18 +45,12 @@ export const ViewFiltersItemRoot: FC = observer((props) => projectId={projectId} viewId={viewId} viewType={viewType} - viewOperations={viewOperations} - baseRoute={baseRoute} filterKey={filterKey} propertyId={propertyId} /> diff --git a/web/components/view/filters/filter-item.tsx b/web/components/view/filters/filter-item.tsx index dae19f5b9..beed1677f 100644 --- a/web/components/view/filters/filter-item.tsx +++ b/web/components/view/filters/filter-item.tsx @@ -1,26 +1,20 @@ import { FC, Fragment } from "react"; -import { CheckSquare } from "lucide-react"; +import { ImagePlus } from "lucide-react"; // hooks import { useViewFilter } from "hooks/store"; // types -import { TViewFilters, TViewTypes } from "@plane/types"; -import { TViewOperations } from "../types"; -// helpers -// import { filterPropertyItemByFilterKeyAndId } from "../helpers/filters"; +import { TViewFilters } from "@plane/types"; type TViewFiltersItem = { workspaceSlug: string; projectId: string | undefined; - viewId: string; - viewType: TViewTypes; - viewOperations: TViewOperations; - baseRoute: string; + filterKey: keyof TViewFilters; propertyId: string; }; export const ViewFiltersItem: FC = (props) => { - const { workspaceSlug, projectId, viewId, viewType, viewOperations, baseRoute, filterKey, propertyId } = props; + const { workspaceSlug, projectId, filterKey, propertyId } = props; // hooks const viewFilterHelper = useViewFilter(workspaceSlug, projectId); @@ -30,7 +24,7 @@ export const ViewFiltersItem: FC = (props) => { return (
- {propertyDetail?.icon || } + {propertyDetail?.icon || }
{propertyDetail?.label || propertyId} diff --git a/web/components/view/filters/filter-selection.tsx b/web/components/view/filters/filter-selection.tsx index 2aa0c54c2..c658d7d48 100644 --- a/web/components/view/filters/filter-selection.tsx +++ b/web/components/view/filters/filter-selection.tsx @@ -5,21 +5,18 @@ import { observer } from "mobx-react-lite"; import { useViewDetail } from "hooks/store"; // types import { TViewFilters, TViewTypes } from "@plane/types"; -import { TViewOperations } from "../types"; type TViewFilterSelection = { workspaceSlug: string; projectId: string | undefined; viewId: string; viewType: TViewTypes; - viewOperations: TViewOperations; - baseRoute: string; filterKey: keyof TViewFilters; propertyId: string; }; export const ViewFilterSelection: FC = observer((props) => { - const { workspaceSlug, projectId, viewId, viewType, viewOperations, baseRoute, filterKey, propertyId } = props; + const { workspaceSlug, projectId, viewId, viewType, filterKey, propertyId } = props; const viewDetailStore = useViewDetail(workspaceSlug, projectId, viewId, viewType); diff --git a/web/components/view/filters/root.tsx b/web/components/view/filters/root.tsx index c2ecaf8f5..f3b8bca24 100644 --- a/web/components/view/filters/root.tsx +++ b/web/components/view/filters/root.tsx @@ -1,6 +1,6 @@ import { FC, useState } from "react"; import { observer } from "mobx-react-lite"; -import { ChevronDown, ChevronUp, Search } from "lucide-react"; +import { ChevronDown, ChevronUp } from "lucide-react"; import concat from "lodash/concat"; import uniq from "lodash/uniq"; import filter from "lodash/filter"; @@ -19,11 +19,10 @@ type TViewFiltersRoot = { viewId: string; viewType: TViewTypes; viewOperations: TViewOperations; - baseRoute: string; }; export const ViewFiltersRoot: FC = observer((props) => { - const { workspaceSlug, projectId, viewId, viewType, viewOperations, baseRoute } = props; + const { workspaceSlug, projectId, viewId, viewType, viewOperations } = props; // hooks const viewDetailStore = useViewDetail(workspaceSlug, projectId, viewId, viewType); // state @@ -62,7 +61,6 @@ export const ViewFiltersRoot: FC = observer((props) => { viewId={viewId} viewType={viewType} viewOperations={viewOperations} - baseRoute={baseRoute} filterKey={filterKey} /> )} diff --git a/web/components/view/index.ts b/web/components/view/index.ts index 73d2622ef..8601dd210 100644 --- a/web/components/view/index.ts +++ b/web/components/view/index.ts @@ -25,6 +25,7 @@ export * from "./display-filters/root"; // view display properties export * from "./display-properties/root"; +export * from "./display-properties/property-selection"; // view applied filters export * from "./applied-filters/root"; diff --git a/web/components/view/layout.tsx b/web/components/view/layout.tsx index 84323b899..c68dc9d01 100644 --- a/web/components/view/layout.tsx +++ b/web/components/view/layout.tsx @@ -31,7 +31,7 @@ export const ViewLayoutRoot: FC = observer((props) => { const viewDetailStore = useViewDetail(workspaceSlug, projectId, viewId, viewType); return ( -
+
{LAYOUTS_DATA.map((layout) => ( diff --git a/web/components/view/types.d.ts b/web/components/view/types.d.ts index 5b88f2022..1330a18e1 100644 --- a/web/components/view/types.d.ts +++ b/web/components/view/types.d.ts @@ -1,11 +1,11 @@ -import { TView } from "@plane/types"; +import { TView, TViewFilters, TViewDisplayFilters, TViewDisplayProperties } from "@plane/types"; export type TViewOperations = { setName: (name: string) => void; setDescription: (description: string) => void; - setFilters: (filters: Partial) => void; + setFilters: (filterKey: keyof TViewFilters, filterValue: "clear_all" | string) => void; setDisplayFilters: (display_filters: Partial) => void; - setDisplayProperties: (display_properties: Partial) => void; + setDisplayProperties: (displayPropertyKey: keyof TViewDisplayProperties) => void; localViewCreateEdit: (viewId: string | undefined) => void; localViewCreateEditClear: (viewId: string | undefined) => Promise; diff --git a/web/pages/[workspaceSlug]/views/public/[viewId].tsx b/web/pages/[workspaceSlug]/views/public/[viewId].tsx index 10f8600c9..838e45345 100644 --- a/web/pages/[workspaceSlug]/views/public/[viewId].tsx +++ b/web/pages/[workspaceSlug]/views/public/[viewId].tsx @@ -15,8 +15,8 @@ const GlobalViewIssuesPage: NextPageWithLayout = () => { if (!workspaceSlug || !viewId) return <>; return ( -
-
+
+
{ baseRoute={`/${workspaceSlug?.toString()}/views/public`} />
+
Issues render
); }; diff --git a/web/store/view/helpers/filters_helpers.ts b/web/store/view/helpers/filters_helpers.ts index 6f2c3611e..c1a14277f 100644 --- a/web/store/view/helpers/filters_helpers.ts +++ b/web/store/view/helpers/filters_helpers.ts @@ -1,4 +1,5 @@ import isEmpty from "lodash/isEmpty"; +import get from "lodash/get"; // types import { TViewFilters, @@ -11,19 +12,19 @@ import { export class FiltersHelper { // computed filters computedFilters = (filters: TViewFilters, defaultValues?: Partial): TViewFilters => ({ - project: defaultValues?.project || filters?.project || [], - module: defaultValues?.module || filters?.module || [], - cycle: defaultValues?.cycle || filters?.cycle || [], - priority: defaultValues?.priority || filters?.priority || [], - state: defaultValues?.state || filters?.state || [], - state_group: defaultValues?.state_group || filters?.state_group || [], - assignees: defaultValues?.assignees || filters?.assignees || [], - mentions: defaultValues?.mentions || filters?.mentions || [], - subscriber: defaultValues?.subscriber || filters?.subscriber || [], - created_by: defaultValues?.created_by || filters?.created_by || [], - labels: defaultValues?.labels || filters?.labels || [], - start_date: defaultValues?.start_date || filters?.start_date || [], - target_date: defaultValues?.target_date || filters?.target_date || [], + project: get(defaultValues, "project", get(filters, "project", [])), + module: get(defaultValues, "module", get(filters, "module", [])), + cycle: get(defaultValues, "cycle", get(filters, "cycle", [])), + priority: get(defaultValues, "priority", get(filters, "priority", [])), + state: get(defaultValues, "state", get(filters, "state", [])), + state_group: get(defaultValues, "state_group", get(filters, "state_group", [])), + assignees: get(defaultValues, "assignees", get(filters, "assignees", [])), + mentions: get(defaultValues, "mentions", get(filters, "mentions", [])), + subscriber: get(defaultValues, "subscriber", get(filters, "subscriber", [])), + created_by: get(defaultValues, "created_by", get(filters, "created_by", [])), + labels: get(defaultValues, "labels", get(filters, "labels", [])), + start_date: get(defaultValues, "start_date", get(filters, "start_date", [])), + target_date: get(defaultValues, "target_date", get(filters, "target_date", [])), }); // computed display filters @@ -49,19 +50,19 @@ export class FiltersHelper { displayProperties: TViewDisplayProperties, defaultValues?: Partial ): TViewDisplayProperties => ({ - assignee: defaultValues?.assignee || displayProperties?.assignee || true, - start_date: defaultValues?.start_date || displayProperties?.start_date || true, - due_date: defaultValues?.due_date || displayProperties?.due_date || true, - labels: defaultValues?.labels || displayProperties?.labels || true, - priority: defaultValues?.priority || displayProperties?.priority || true, - state: defaultValues?.state || displayProperties?.state || true, - sub_issue_count: defaultValues?.sub_issue_count || displayProperties?.sub_issue_count || true, - attachment_count: defaultValues?.attachment_count || displayProperties?.attachment_count || true, - link: defaultValues?.link || displayProperties?.link || true, - estimate: defaultValues?.estimate || displayProperties?.estimate || true, - key: defaultValues?.key || displayProperties?.key || true, - created_on: defaultValues?.created_on || displayProperties?.created_on || true, - updated_on: defaultValues?.updated_on || displayProperties?.updated_on || true, + assignee: get(defaultValues, "assignee", get(displayProperties, "assignee", true)), + start_date: get(defaultValues, "start_date", get(displayProperties, "start_date", true)), + due_date: get(defaultValues, "due_date", get(displayProperties, "due_date", true)), + labels: get(defaultValues, "labels", get(displayProperties, "labels", true)), + priority: get(defaultValues, "priority", get(displayProperties, "priority", true)), + state: get(defaultValues, "state", get(displayProperties, "state", true)), + sub_issue_count: get(defaultValues, "sub_issue_count", get(displayProperties, "sub_issue_count", true)), + attachment_count: get(defaultValues, "attachment_count", get(displayProperties, "attachment_count", true)), + link: get(defaultValues, "link", get(displayProperties, "link", true)), + estimate: get(defaultValues, "estimate", get(displayProperties, "estimate", true)), + key: get(defaultValues, "key", get(displayProperties, "key", true)), + created_on: get(defaultValues, "created_on", get(displayProperties, "created_on", true)), + updated_on: get(defaultValues, "updated_on", get(displayProperties, "updated_on", true)), }); // compute filters and display_filters issue query parameters diff --git a/web/store/view/root.store.ts b/web/store/view/root.store.ts index 8dc3f81b7..088fbe0ed 100644 --- a/web/store/view/root.store.ts +++ b/web/store/view/root.store.ts @@ -1,5 +1,4 @@ // stores -import { autorun, makeObservable, observable } from "mobx"; import { ViewRootStore } from "./view-root.store"; // services import { diff --git a/web/store/view/view.store.ts b/web/store/view/view.store.ts index 6f44f2958..66e4730b9 100644 --- a/web/store/view/view.store.ts +++ b/web/store/view/view.store.ts @@ -1,5 +1,8 @@ import { action, computed, makeObservable, observable, runInAction } from "mobx"; import set from "lodash/set"; +import update from "lodash/update"; +import concat from "lodash/concat"; +import pull from "lodash/pull"; // store import { RootStore } from "store/root.store"; // types @@ -24,12 +27,13 @@ export type TViewStore = TView & { // computed appliedFilters: TViewFilterProps | undefined; appliedFiltersQueryParams: string | undefined; + isFiltersApplied: boolean; // helper actions setName: (name: string) => void; setDescription: (description: string) => void; - setFilters: (filters: Partial) => void; + setFilters: (filterKey: keyof TViewFilters | undefined, filterValue: "clear_all" | string) => void; setDisplayFilters: (display_filters: Partial) => void; - setDisplayProperties: (display_properties: Partial) => void; + setDisplayProperties: (displayPropertyKey: keyof TViewDisplayProperties) => void; resetChanges: () => void; saveChanges: () => Promise; // actions @@ -132,6 +136,7 @@ export class ViewStore extends FiltersHelper implements TViewStore { // computed appliedFilters: computed, appliedFiltersQueryParams: computed, + isFiltersApplied: computed, // helper actions setName: action, setFilters: action, @@ -164,6 +169,16 @@ export class ViewStore extends FiltersHelper implements TViewStore { return this.computeAppliedFiltersQueryParameters(filters, [])?.query || undefined; } + get isFiltersApplied() { + const filters = this.appliedFilters?.filters; + let isFiltersApplied = false; + Object.keys(filters).forEach((key) => { + const _key = key as keyof TViewFilters; + if (filters[_key]?.length > 0) isFiltersApplied = true; + }); + return isFiltersApplied; + } + // helper actions setName = (name: string) => { runInAction(() => { @@ -177,13 +192,18 @@ export class ViewStore extends FiltersHelper implements TViewStore { }); }; - setFilters = (filters: Partial) => { + setFilters = (filterKey: keyof TViewFilters | undefined = undefined, filterValue: "clear_all" | string) => { runInAction(() => { this.loader = "submit"; - Object.keys(filters).forEach((key) => { - const _key = key as keyof TViewFilters; - set(this.filtersToUpdate, ["filters", _key], filters[_key]); - }); + if (filterKey === undefined) { + if (filterValue === "clear_all") set(this.filtersToUpdate, ["filters"], {}); + this.loader = undefined; + } else + update(this.filtersToUpdate, ["filters", filterKey], (_values = []) => { + if (filterValue === "clear_all") return []; + if (_values.includes(filterValue)) return pull(_values, filterValue); + return concat(_values, filterValue); + }); }); }; @@ -210,12 +230,9 @@ export class ViewStore extends FiltersHelper implements TViewStore { }); }; - setDisplayProperties = async (display_properties: Partial) => { + setDisplayProperties = async (displayPropertyKey: keyof TViewDisplayProperties) => { runInAction(() => { - Object.keys(display_properties).forEach((key) => { - const _key = key as keyof TViewDisplayProperties; - set(this.filtersToUpdate, ["display_properties", _key], display_properties[_key]); - }); + update(this.filtersToUpdate, ["display_properties", displayPropertyKey], (_value: boolean = true) => !_value); }); };