From 7be038ac5a1417acda0cd7f1052fd03704eeb5b1 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> Date: Wed, 4 Oct 2023 12:04:55 +0530 Subject: [PATCH] refactor: filter components (#2359) * fix: calendar layout dividers * refactor: filter selection components * fix: dropdown closing after selection * refactor: filters components --- web/components/core/views/all-views.tsx | 4 +- .../issue-layouts/calendar/calendar.tsx | 2 +- .../calendar/dropdowns/months-dropdown.tsx | 127 ++++++------- .../issues/issue-layouts/calendar/header.tsx | 2 +- .../issue-layouts/calendar/week-days.tsx | 6 +- .../filters/applied-filters/filters-list.tsx | 77 ++------ .../filters/applied-filters/index.ts | 1 + .../filters/applied-filters/root.tsx | 79 ++++++++ .../filters/header/filters/assignee.tsx | 30 ++- .../filters/header/filters/created-by.tsx | 30 ++- .../header/filters/filters-selection.tsx | 177 +++++++----------- .../filters/header/filters/labels.tsx | 20 +- .../filters/header/filters/start-date.tsx | 9 +- .../filters/header/filters/state-group.tsx | 12 +- .../filters/header/filters/state.tsx | 21 +-- .../filters/header/filters/target-date.tsx | 9 +- 16 files changed, 280 insertions(+), 326 deletions(-) create mode 100644 web/components/issues/issue-layouts/filters/applied-filters/root.tsx diff --git a/web/components/core/views/all-views.tsx b/web/components/core/views/all-views.tsx index c5fcc7300..85830ee27 100644 --- a/web/components/core/views/all-views.tsx +++ b/web/components/core/views/all-views.tsx @@ -6,7 +6,7 @@ import useSWR from "swr"; // mobx store import { useMobxStore } from "lib/mobx/store-provider"; // components -import { AppliedFiltersList, CalendarLayout, GanttLayout, KanBanLayout, SpreadsheetLayout } from "components/issues"; +import { AppliedFiltersRoot, CalendarLayout, GanttLayout, KanBanLayout, SpreadsheetLayout } from "components/issues"; export const AllViews: React.FC = observer(() => { const router = useRouter(); @@ -35,7 +35,7 @@ export const AllViews: React.FC = observer(() => { return (
- + {activeLayout === "kanban" ? ( ) : activeLayout === "calendar" ? ( diff --git a/web/components/issues/issue-layouts/calendar/calendar.tsx b/web/components/issues/issue-layouts/calendar/calendar.tsx index b4d9aa4b2..507732e98 100644 --- a/web/components/issues/issue-layouts/calendar/calendar.tsx +++ b/web/components/issues/issue-layouts/calendar/calendar.tsx @@ -38,7 +38,7 @@ export const CalendarChart: React.FC = observer((props) => {
{calendarLayout === "month" ? ( -
+
{allWeeksOfActiveMonth && Object.values(allWeeksOfActiveMonth).map((week: ICalendarWeek, weekIndex) => ( diff --git a/web/components/issues/issue-layouts/calendar/dropdowns/months-dropdown.tsx b/web/components/issues/issue-layouts/calendar/dropdowns/months-dropdown.tsx index 2b6c43b25..4bb5ebcf0 100644 --- a/web/components/issues/issue-layouts/calendar/dropdowns/months-dropdown.tsx +++ b/web/components/issues/issue-layouts/calendar/dropdowns/months-dropdown.tsx @@ -4,9 +4,10 @@ import { observer } from "mobx-react-lite"; // mobx store import { useMobxStore } from "lib/mobx/store-provider"; +// icons +import { ChevronLeft, ChevronRight } from "lucide-react"; // constants import { MONTHS_LIST } from "constants/calendar"; -import { ChevronLeft, ChevronRight } from "lucide-react"; export const CalendarMonthsDropdown: React.FC = observer(() => { const { calendar: calendarStore, issueFilter: issueFilterStore } = useMobxStore(); @@ -46,73 +47,63 @@ export const CalendarMonthsDropdown: React.FC = observer(() => { return ( - {({ close }) => ( - <> - - {calendarLayout === "month" - ? `${MONTHS_LIST[activeMonthDate.getMonth() + 1].title} ${activeMonthDate.getFullYear()}` - : getWeekLayoutHeader()} - - - -
-
- - {activeMonthDate.getFullYear()} - -
-
- {Object.values(MONTHS_LIST).map((month, index) => ( - - ))} -
-
-
-
- - )} + + {calendarLayout === "month" + ? `${MONTHS_LIST[activeMonthDate.getMonth() + 1].title} ${activeMonthDate.getFullYear()}` + : getWeekLayoutHeader()} + + + +
+
+ + {activeMonthDate.getFullYear()} + +
+
+ {Object.values(MONTHS_LIST).map((month, index) => ( + + ))} +
+
+
+
); }); diff --git a/web/components/issues/issue-layouts/calendar/header.tsx b/web/components/issues/issue-layouts/calendar/header.tsx index 363719920..034be98c4 100644 --- a/web/components/issues/issue-layouts/calendar/header.tsx +++ b/web/components/issues/issue-layouts/calendar/header.tsx @@ -86,7 +86,7 @@ export const CalendarHeader: React.FC = observer(() => {
+ )} + {isViewLessVisible && ( + + )} +
+); + export const FilterSelection: React.FC = observer((props) => { const { filters, handleFiltersUpdate, layoutDisplayFiltersOptions, projectId } = props; @@ -157,25 +180,12 @@ export const FilterSelection: React.FC = observer((props) => { itemsToRender={filtersToRender.priority?.currentLength ?? 0} searchQuery={filtersSearchQuery} viewButtons={ -
- {/* TODO: handle view more and less in a better way */} - {isViewMoreVisible("priority") && ( - - )} - {isViewLessVisible("priority") && ( - - )} -
+ handleViewLess("priority")} + handleMore={() => handleViewMore("priority")} + /> } />
@@ -189,25 +199,15 @@ export const FilterSelection: React.FC = observer((props) => { handleUpdate={(val) => handleFiltersUpdate("state_group", val)} itemsToRender={filtersToRender.state_group?.currentLength ?? 0} searchQuery={filtersSearchQuery} + viewButtons={ + handleViewLess("state_group")} + handleMore={() => handleViewMore("state_group")} + /> + } /> -
- {isViewMoreVisible("state_group") && ( - - )} - {isViewLessVisible("state_group") && ( - - )} -
)} @@ -219,23 +219,16 @@ export const FilterSelection: React.FC = observer((props) => { handleUpdate={(val) => handleFiltersUpdate("state", val)} itemsToRender={filtersToRender.state?.currentLength ?? 0} searchQuery={filtersSearchQuery} - projectId={projectId} + states={projectStore.states?.[projectId]} + viewButtons={ + handleViewLess("state")} + handleMore={() => handleViewMore("state")} + /> + } /> -
- {isViewMoreVisible("state") && ( - - )} - {isViewLessVisible("state") && ( - - )} -
)} @@ -246,27 +239,15 @@ export const FilterSelection: React.FC = observer((props) => { appliedFilters={filters.assignees ?? null} handleUpdate={(val) => handleFiltersUpdate("assignees", val)} itemsToRender={filtersToRender.assignees?.currentLength ?? 0} - projectId={projectId} + members={projectStore.members?.[projectId]?.map((m) => m.member) ?? undefined} searchQuery={filtersSearchQuery} viewButtons={ -
- {isViewMoreVisible("assignees") && ( - - )} - {isViewLessVisible("assignees") && ( - - )} -
+ handleViewLess("assignees")} + handleMore={() => handleViewMore("assignees")} + /> } />
@@ -279,27 +260,15 @@ export const FilterSelection: React.FC = observer((props) => { appliedFilters={filters.created_by ?? null} handleUpdate={(val) => handleFiltersUpdate("created_by", val)} itemsToRender={filtersToRender.created_by?.currentLength ?? 0} - projectId={projectId} + members={projectStore.members?.[projectId]?.map((m) => m.member) ?? undefined} searchQuery={filtersSearchQuery} viewButtons={ -
- {isViewMoreVisible("created_by") && ( - - )} - {isViewLessVisible("created_by") && ( - - )} -
+ handleViewLess("created_by")} + handleMore={() => handleViewMore("created_by")} + /> } /> @@ -312,27 +281,15 @@ export const FilterSelection: React.FC = observer((props) => { appliedFilters={filters.labels ?? null} handleUpdate={(val) => handleFiltersUpdate("labels", val)} itemsToRender={filtersToRender.labels?.currentLength ?? 0} - projectId={projectId} + labels={projectStore.labels?.[projectId] ?? undefined} searchQuery={filtersSearchQuery} viewButtons={ -
- {isViewMoreVisible("labels") && ( - - )} - {isViewLessVisible("labels") && ( - - )} -
+ handleViewLess("labels")} + handleMore={() => handleViewMore("labels")} + /> } /> diff --git a/web/components/issues/issue-layouts/filters/header/filters/labels.tsx b/web/components/issues/issue-layouts/filters/header/filters/labels.tsx index 407bd707f..a41405076 100644 --- a/web/components/issues/issue-layouts/filters/header/filters/labels.tsx +++ b/web/components/issues/issue-layouts/filters/header/filters/labels.tsx @@ -1,12 +1,11 @@ import React, { useState } from "react"; -import { observer } from "mobx-react-lite"; -// mobx store -import { useMobxStore } from "lib/mobx/store-provider"; // components import { FilterHeader, FilterOption } from "components/issues"; // ui import { Loader } from "components/ui"; +// types +import { IIssueLabels } from "types"; const LabelIcons = ({ color }: { color: string }) => ( @@ -16,24 +15,19 @@ type Props = { appliedFilters: string[] | null; handleUpdate: (val: string) => void; itemsToRender: number; - projectId: string; + labels: IIssueLabels[] | undefined; searchQuery: string; viewButtons: React.ReactNode; }; -export const FilterLabels: React.FC = observer((props) => { - const { appliedFilters, handleUpdate, itemsToRender, projectId, searchQuery, viewButtons } = props; +export const FilterLabels: React.FC = (props) => { + const { appliedFilters, handleUpdate, itemsToRender, labels, searchQuery, viewButtons } = props; const [previewEnabled, setPreviewEnabled] = useState(true); - const store = useMobxStore(); - const { project: projectStore } = store; - const appliedFiltersCount = appliedFilters?.length ?? 0; - const filteredOptions = projectStore.labels?.[projectId?.toString() ?? ""]?.filter((label) => - label.name.toLowerCase().includes(searchQuery.toLowerCase()) - ); + const filteredOptions = labels?.filter((label) => label.name.toLowerCase().includes(searchQuery.toLowerCase())); return ( <> @@ -72,4 +66,4 @@ export const FilterLabels: React.FC = observer((props) => { )} ); -}); +}; diff --git a/web/components/issues/issue-layouts/filters/header/filters/start-date.tsx b/web/components/issues/issue-layouts/filters/header/filters/start-date.tsx index ad5ed955a..e93f1fa7d 100644 --- a/web/components/issues/issue-layouts/filters/header/filters/start-date.tsx +++ b/web/components/issues/issue-layouts/filters/header/filters/start-date.tsx @@ -49,15 +49,10 @@ export const FilterStartDate: React.FC = observer((props) => { isChecked={appliedFilters?.includes(option.value) ? true : false} onClick={() => handleUpdate(option.value)} title={option.name} - multiple={false} + multiple /> ))} - setIsDateFilterModalOpen(true)} - title="Custom" - multiple={false} - /> + setIsDateFilterModalOpen(true)} title="Custom" multiple /> ) : (

No matches found

diff --git a/web/components/issues/issue-layouts/filters/header/filters/state-group.tsx b/web/components/issues/issue-layouts/filters/header/filters/state-group.tsx index fd22cd10d..c5551a30d 100644 --- a/web/components/issues/issue-layouts/filters/header/filters/state-group.tsx +++ b/web/components/issues/issue-layouts/filters/header/filters/state-group.tsx @@ -13,10 +13,11 @@ type Props = { handleUpdate: (val: string) => void; itemsToRender: number; searchQuery: string; + viewButtons: React.ReactNode; }; export const FilterStateGroup: React.FC = observer((props) => { - const { appliedFilters, handleUpdate, itemsToRender, searchQuery } = props; + const { appliedFilters, handleUpdate, itemsToRender, searchQuery, viewButtons } = props; const [previewEnabled, setPreviewEnabled] = useState(true); @@ -34,9 +35,8 @@ export const FilterStateGroup: React.FC = observer((props) => { {previewEnabled && (
{filteredOptions.length > 0 ? ( - filteredOptions - .slice(0, itemsToRender) - .map((stateGroup) => ( + <> + {filteredOptions.slice(0, itemsToRender).map((stateGroup) => ( = observer((props) => { icon={} title={stateGroup.title} /> - )) + ))} + {viewButtons} + ) : (

No matches found

)} diff --git a/web/components/issues/issue-layouts/filters/header/filters/state.tsx b/web/components/issues/issue-layouts/filters/header/filters/state.tsx index 6a1232588..ae719758a 100644 --- a/web/components/issues/issue-layouts/filters/header/filters/state.tsx +++ b/web/components/issues/issue-layouts/filters/header/filters/state.tsx @@ -1,8 +1,5 @@ import React, { useState } from "react"; -import { observer } from "mobx-react-lite"; -// mobx store -import { useMobxStore } from "lib/mobx/store-provider"; // components import { FilterHeader, FilterOption } from "components/issues"; // ui @@ -11,25 +8,24 @@ import { Loader } from "components/ui"; import { StateGroupIcon } from "components/icons"; // helpers import { getStatesList } from "helpers/state.helper"; +// types +import { IStateResponse } from "types"; type Props = { appliedFilters: string[] | null; handleUpdate: (val: string) => void; itemsToRender: number; - projectId: string; searchQuery: string; + states: IStateResponse | undefined; + viewButtons: React.ReactNode; }; -export const FilterState: React.FC = observer((props) => { - const { appliedFilters, handleUpdate, itemsToRender, projectId, searchQuery } = props; +export const FilterState: React.FC = (props) => { + const { appliedFilters, handleUpdate, itemsToRender, searchQuery, states, viewButtons } = props; const [previewEnabled, setPreviewEnabled] = useState(true); - const store = useMobxStore(); - const { project: projectStore } = store; - - const statesByGroups = projectStore.states?.[projectId?.toString() ?? ""]; - const statesList = getStatesList(statesByGroups); + const statesList = getStatesList(states); const appliedFiltersCount = appliedFilters?.length ?? 0; @@ -56,6 +52,7 @@ export const FilterState: React.FC = observer((props) => { title={state.name} /> ))} + {viewButtons} ) : (

No matches found

@@ -71,4 +68,4 @@ export const FilterState: React.FC = observer((props) => { )} ); -}); +}; diff --git a/web/components/issues/issue-layouts/filters/header/filters/target-date.tsx b/web/components/issues/issue-layouts/filters/header/filters/target-date.tsx index c6ee45b04..c007aa039 100644 --- a/web/components/issues/issue-layouts/filters/header/filters/target-date.tsx +++ b/web/components/issues/issue-layouts/filters/header/filters/target-date.tsx @@ -49,15 +49,10 @@ export const FilterTargetDate: React.FC = observer((props) => { isChecked={appliedFilters?.includes(option.value) ? true : false} onClick={() => handleUpdate(option.value)} title={option.name} - multiple={false} + multiple /> ))} - setIsDateFilterModalOpen(true)} - title="Custom" - multiple={false} - /> + setIsDateFilterModalOpen(true)} title="Custom" multiple /> ) : (

No matches found