diff --git a/web/components/core/filters/issues-view-filter.tsx b/web/components/core/filters/issues-view-filter.tsx index 2a8f8c1c6..06f78a792 100644 --- a/web/components/core/filters/issues-view-filter.tsx +++ b/web/components/core/filters/issues-view-filter.tsx @@ -25,11 +25,11 @@ import { import { replaceUnderscoreIfSnakeCase } from "helpers/string.helper"; import { checkIfArraysHaveSameElements } from "helpers/array.helper"; // types -import { Properties, TIssueViewOptions } from "types"; +import { Properties, TIssueLayouts } from "types"; // constants import { ISSUE_GROUP_BY_OPTIONS, ISSUE_ORDER_BY_OPTIONS, ISSUE_FILTER_OPTIONS } from "constants/issue"; -const issueViewOptions: { type: TIssueViewOptions; Icon: any }[] = [ +const issueViewOptions: { type: TIssueLayouts; Icon: any }[] = [ { type: "list", Icon: FormatListBulletedOutlined, @@ -52,7 +52,7 @@ const issueViewOptions: { type: TIssueViewOptions; Icon: any }[] = [ }, ]; -const issueViewForDraftIssues: { type: TIssueViewOptions; Icon: any }[] = [ +const issueViewForDraftIssues: { type: TIssueLayouts; Icon: any }[] = [ { type: "list", Icon: FormatListBulletedOutlined, diff --git a/web/components/core/views/board-view/all-boards.tsx b/web/components/core/views/board-view/all-boards.tsx index 058eafdf8..4c42ae166 100644 --- a/web/components/core/views/board-view/all-boards.tsx +++ b/web/components/core/views/board-view/all-boards.tsx @@ -65,28 +65,21 @@ export const AllBoards: React.FC = ({ const { displayFilters, groupedIssues } = viewProps; - console.log("viewProps", viewProps); - return ( <> - isMyIssue ? mutateMyIssues() : isProfileIssue ? mutateProfileIssues() : mutateIssues() - } + handleMutation={() => (isMyIssue ? mutateMyIssues() : isProfileIssue ? mutateProfileIssues() : mutateIssues())} projectId={myIssueProjectId ? myIssueProjectId : projectId?.toString() ?? ""} workspaceSlug={workspaceSlug?.toString() ?? ""} readOnly={disableUserActions} /> {groupedIssues ? ( -
+
{Object.keys(groupedIssues).map((singleGroup, index) => { const currentState = - displayFilters?.group_by === "state" - ? states?.find((s) => s.id === singleGroup) - : null; + displayFilters?.group_by === "state" ? states?.find((s) => s.id === singleGroup) : null; - if (!displayFilters?.show_empty_groups && groupedIssues[singleGroup].length === 0) - return null; + if (!displayFilters?.show_empty_groups && groupedIssues[singleGroup].length === 0) return null; return ( = ({
{Object.keys(groupedIssues).map((singleGroup, index) => { const currentState = - displayFilters?.group_by === "state" - ? states?.find((s) => s.id === singleGroup) - : null; + displayFilters?.group_by === "state" ? states?.find((s) => s.id === singleGroup) : null; if (groupedIssues[singleGroup].length === 0) return (
{currentState && ( diff --git a/web/components/core/views/issues-view.tsx b/web/components/core/views/issues-view.tsx index 521318e40..2ba81cc25 100644 --- a/web/components/core/views/issues-view.tsx +++ b/web/components/core/views/issues-view.tsx @@ -490,6 +490,7 @@ export const IssuesView: React.FC = ({ openIssuesListModal, disableUserAc labels: null, priority: null, state: null, + state_group: null, start_date: null, target_date: null, }) diff --git a/web/components/core/views/list-view/single-issue.tsx b/web/components/core/views/list-view/single-issue.tsx index 54ef1a15b..b1eedce69 100644 --- a/web/components/core/views/list-view/single-issue.tsx +++ b/web/components/core/views/list-view/single-issue.tsx @@ -255,8 +255,6 @@ export const SingleListIssue: React.FC = ({ const isNotAllowed = userAuth.isGuest || userAuth.isViewer || disableUserActions || isArchivedIssues; - console.log("properties", properties); - return ( <> { + const router = useRouter(); + const { workspaceSlug, projectId } = router.query; + + const { issueFilter: issueFilterStore } = useMobxStore(); + + const handleLayoutChange = (layout: TIssueLayouts) => { + if (!workspaceSlug || !projectId) return; + + issueFilterStore.updateUserFilters(workspaceSlug.toString(), projectId.toString(), { + display_filters: { + layout, + }, + }); + }; + + return ( +
+ handleLayoutChange(layout)} + selectedLayout={issueFilterStore.userDisplayFilters.layout ?? "list"} + /> + + + + + + +
+ ); +}); diff --git a/web/components/issue-layouts/display-filters/display-filters-selection.tsx b/web/components/issue-layouts/display-filters/display-filters-selection.tsx new file mode 100644 index 000000000..64d6ad0df --- /dev/null +++ b/web/components/issue-layouts/display-filters/display-filters-selection.tsx @@ -0,0 +1,67 @@ +import React from "react"; + +// mobx +import { observer } from "mobx-react-lite"; +import { useMobxStore } from "lib/mobx/store-provider"; +// components +import { + FilterDisplayProperties, + FilterExtraOptions, + FilterGroupBy, + FilterIssueType, + FilterOrderBy, +} from "components/issue-layouts"; +// helpers +import { issueFilterVisibilityData } from "helpers/issue.helper"; + +export const DisplayFiltersSelection = observer(() => { + const { issueFilter: issueFilterStore } = useMobxStore(); + + const isDisplayFilterEnabled = (displayFilter: string) => + issueFilterVisibilityData.issues.display_filters[issueFilterStore.userDisplayFilters.layout ?? "list"].includes( + displayFilter + ); + + return ( +
+ {/*
Search container
*/} +
+ {/* display properties */} + {issueFilterVisibilityData.issues.display_properties[issueFilterStore.userDisplayFilters.layout ?? "list"] && ( +
+ +
+ )} + + {/* group by */} + {isDisplayFilterEnabled("group_by") && ( +
+ +
+ )} + + {/* order by */} + {isDisplayFilterEnabled("order_by") && ( +
+ +
+ )} + + {/* issue type */} + {isDisplayFilterEnabled("issue_type") && ( +
+ +
+ )} + + {/* Options */} + {issueFilterVisibilityData.issues.extra_options[issueFilterStore.userDisplayFilters.layout ?? "list"] + .access && ( +
+ +
+ )} +
+
+ ); +}); diff --git a/web/components/issue-layouts/display-filters/display-properties.tsx b/web/components/issue-layouts/display-filters/display-properties.tsx index 402c5064f..f7fb87d2c 100644 --- a/web/components/issue-layouts/display-filters/display-properties.tsx +++ b/web/components/issue-layouts/display-filters/display-properties.tsx @@ -1,49 +1,58 @@ import React from "react"; + +import { useRouter } from "next/router"; + +// mobx +import { observer } from "mobx-react-lite"; +import { useMobxStore } from "lib/mobx/store-provider"; // components import { FilterHeader } from "../helpers/filter-header"; -// mobx react lite -import { observer } from "mobx-react-lite"; -// mobx store -import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; +// types +import { IIssueDisplayProperties } from "types"; +// constants import { ISSUE_DISPLAY_PROPERTIES } from "constants/issue"; export const FilterDisplayProperties = observer(() => { - const store: RootStore = useMobxStore(); + const router = useRouter(); + const { workspaceSlug, projectId } = router.query; + + const store = useMobxStore(); const { issueFilter: issueFilterStore } = store; const [previewEnabled, setPreviewEnabled] = React.useState(true); - const handleDisplayProperties = (key: string, value: boolean) => { - // issueFilterStore.handleUserFilter("display_properties", key, !value); + const handleDisplayProperties = (property: Partial) => { + if (!workspaceSlug || !projectId) return; + + issueFilterStore.updateDisplayProperties(workspaceSlug.toString(), projectId.toString(), property); }; return (
setPreviewEnabled(!previewEnabled)} /> {previewEnabled && ( -
+
{ISSUE_DISPLAY_PROPERTIES.map((displayProperty) => ( -
{ - handleDisplayProperties( - displayProperty?.key, - issueFilterStore?.userDisplayProperties?.[displayProperty?.key] - ); - }} + onClick={() => + handleDisplayProperties({ + [displayProperty.key]: !issueFilterStore?.userDisplayProperties?.[displayProperty.key], + }) + } > - {displayProperty?.title} -
+ {displayProperty.title} + ))}
)} diff --git a/web/components/issue-layouts/display-filters/extra-options.tsx b/web/components/issue-layouts/display-filters/extra-options.tsx index d05703c9b..a321c6793 100644 --- a/web/components/issue-layouts/display-filters/extra-options.tsx +++ b/web/components/issue-layouts/display-filters/extra-options.tsx @@ -1,53 +1,47 @@ -import React from "react"; -// components -import { FilterHeader } from "../helpers/filter-header"; -import { FilterOption } from "../helpers/filter-option"; -// mobx react lite +import React, { useState } from "react"; + +// mobx import { observer } from "mobx-react-lite"; -// mobx store import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; -import { ISSUE_EXTRA_PROPERTIES } from "constants/issue"; -// default data -// import { issueFilterVisibilityData } from "helpers/issue.helper"; + +// components +import { FilterHeader, FilterOption } from "components/issue-layouts"; +// helpers +import { issueFilterVisibilityData } from "helpers/issue.helper"; +// constants +import { ISSUE_EXTRA_OPTIONS } from "constants/issue"; export const FilterExtraOptions = observer(() => { - const store: RootStore = useMobxStore(); + const [previewEnabled, setPreviewEnabled] = useState(true); + + const store = useMobxStore(); const { issueFilter: issueFilterStore } = store; - const [previewEnabled, setPreviewEnabled] = React.useState(true); - - const handleExtraOptions = (key: string, value: boolean) => { - // issueFilterStore.handleUserFilter("display_filters", key, !value); - }; - - const handleExtraOptionsSectionVisibility = (key: string) => { - // issueFilterStore?.issueView && - // issueFilterStore?.issueLayout && - // issueFilterVisibilityData[issueFilterStore?.issueView === "my_issues" ? "my_issues" : "issues"]?.extra_options?.[ - // issueFilterStore?.issueLayout - // ].values?.includes(key); - }; + const isExtraOptionEnabled = (option: string) => + issueFilterVisibilityData.issues.extra_options[ + issueFilterStore.userDisplayFilters.layout ?? "list" + ].values.includes(option); return (
setPreviewEnabled(!previewEnabled)} /> {previewEnabled && (
- {ISSUE_EXTRA_PROPERTIES.map((_extraProperties) => ( - - handleExtraOptions(_extraProperties?.key, issueFilterStore?.userDisplayFilters?.[_extraProperties?.key]) - } - title={_extraProperties.title} - /> - ))} + {ISSUE_EXTRA_OPTIONS.map((option) => { + if (!isExtraOptionEnabled(option.key)) return null; + + return ( + + ); + })}
)}
diff --git a/web/components/issue-layouts/display-filters/group-by.tsx b/web/components/issue-layouts/display-filters/group-by.tsx index 676717adc..5b95c61b1 100644 --- a/web/components/issue-layouts/display-filters/group-by.tsx +++ b/web/components/issue-layouts/display-filters/group-by.tsx @@ -1,39 +1,52 @@ import React from "react"; + +import { useRouter } from "next/router"; + +// mobx +import { observer } from "mobx-react-lite"; +import { useMobxStore } from "lib/mobx/store-provider"; // components import { FilterHeader } from "../helpers/filter-header"; import { FilterOption } from "../helpers/filter-option"; -// mobx react lite -import { observer } from "mobx-react-lite"; -// mobx store -import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; +// types +import { TIssueGroupByOptions } from "types"; +// constants import { ISSUE_GROUP_BY_OPTIONS } from "constants/issue"; export const FilterGroupBy = observer(() => { - const store: RootStore = useMobxStore(); + const router = useRouter(); + const { workspaceSlug, projectId } = router.query; + + const store = useMobxStore(); const { issueFilter: issueFilterStore } = store; const [previewEnabled, setPreviewEnabled] = React.useState(true); - const handleGroupBy = (key: string, value: string) => { - // issueFilterStore.handleUserFilter("display_filters", key, value); + const handleGroupBy = (value: TIssueGroupByOptions) => { + if (!workspaceSlug || !projectId) return; + + issueFilterStore.updateUserFilters(workspaceSlug.toString(), projectId.toString(), { + display_filters: { + group_by: value, + }, + }); }; return (
setPreviewEnabled(!previewEnabled)} /> {previewEnabled && ( -
- {ISSUE_GROUP_BY_OPTIONS.map((_groupBy) => ( +
+ {ISSUE_GROUP_BY_OPTIONS.map((groupBy) => ( handleGroupBy("group_by", _groupBy?.key)} - title={_groupBy.title} + key={groupBy?.key} + isChecked={issueFilterStore?.userDisplayFilters?.group_by === groupBy?.key ? true : false} + onClick={() => handleGroupBy(groupBy.key)} + title={groupBy.title} multiple={false} /> ))} diff --git a/web/components/issue-layouts/display-filters/index.ts b/web/components/issue-layouts/display-filters/index.ts new file mode 100644 index 000000000..27ed9943b --- /dev/null +++ b/web/components/issue-layouts/display-filters/index.ts @@ -0,0 +1,6 @@ +export * from "./display-filters-selection"; +export * from "./display-properties"; +export * from "./extra-options"; +export * from "./group-by"; +export * from "./issue-type"; +export * from "./order-by"; diff --git a/web/components/issue-layouts/display-filters/index.tsx b/web/components/issue-layouts/display-filters/index.tsx deleted file mode 100644 index 708d52241..000000000 --- a/web/components/issue-layouts/display-filters/index.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import React from "react"; -// components -import { FilterDisplayProperties } from "./display-properties"; -import { FilterGroupBy } from "./group-by"; -import { FilterOrderBy } from "./order-by"; -import { FilterIssueType } from "./issue-type"; -import { FilterExtraOptions } from "./extra-options"; -// mobx react lite -import { observer } from "mobx-react-lite"; -// mobx store -import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; -// default data -// import { issueFilterVisibilityData } from "store/helpers/issue-data"; - -export const DisplayFiltersSelection = observer(() => { - const store: RootStore = useMobxStore(); - const { issueFilter: issueFilterStore } = store; - - // const handleDisplayPropertiesSectionVisibility = - // issueFilterStore?.issueView && - // issueFilterStore?.issueLayout && - // issueFilterVisibilityData[issueFilterStore?.issueView === "my_issues" ? "my_issues" : "issues"] - // ?.display_properties?.[issueFilterStore?.issueLayout]; - - const handleDisplayFilterSectionVisibility = (section_key: string) => { - // issueFilterStore?.issueView && - // issueFilterStore?.issueLayout && - // issueFilterVisibilityData[ - // issueFilterStore?.issueView === "my_issues" ? "my_issues" : "issues" - // ]?.display_filters?.[issueFilterStore?.issueLayout].includes(section_key); - }; - - // const handleExtraOptionsSectionVisibility = - // issueFilterStore?.issueView && - // issueFilterStore?.issueLayout && - // issueFilterVisibilityData[issueFilterStore?.issueView === "my_issues" ? "my_issues" : "issues"]?.extra_options?.[ - // issueFilterStore?.issueLayout - // ].access; - - return ( -
-
Search container
-
- {/* display properties */} - {/* {handleDisplayPropertiesSectionVisibility && ( -
- -
- )} */} - - {/* group by */} - {/* {handleDisplayFilterSectionVisibility("group_by") && ( -
- -
- )} */} - - {/* order by */} - {/* {handleDisplayFilterSectionVisibility("order_by") && ( -
- -
- )} */} - - {/* issue type */} - {/* {handleDisplayFilterSectionVisibility("issue_type") && ( -
- -
- )} */} - - {/* Options */} - {/* {handleExtraOptionsSectionVisibility && ( -
- -
- )} */} -
-
- ); -}); diff --git a/web/components/issue-layouts/display-filters/issue-type.tsx b/web/components/issue-layouts/display-filters/issue-type.tsx index b9c3ace84..6af37c8d5 100644 --- a/web/components/issue-layouts/display-filters/issue-type.tsx +++ b/web/components/issue-layouts/display-filters/issue-type.tsx @@ -1,38 +1,52 @@ import React from "react"; + +import { useRouter } from "next/router"; + +// mobx import { observer } from "mobx-react-lite"; +import { useMobxStore } from "lib/mobx/store-provider"; // components import { FilterHeader } from "../helpers/filter-header"; import { FilterOption } from "../helpers/filter-option"; -// mobx store -import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; +// types +import { TIssueTypeFilters } from "types"; +// constants import { ISSUE_FILTER_OPTIONS } from "constants/issue"; export const FilterIssueType = observer(() => { - const store: RootStore = useMobxStore(); + const router = useRouter(); + const { workspaceSlug, projectId } = router.query; + + const store = useMobxStore(); const { issueFilter: issueFilterStore } = store; const [previewEnabled, setPreviewEnabled] = React.useState(true); - const handleIssueType = (key: string, value: string) => { - // issueFilterStore.handleUserFilter("display_filters", key, value); + const handleIssueType = (value: TIssueTypeFilters) => { + if (!workspaceSlug || !projectId) return; + + issueFilterStore.updateUserFilters(workspaceSlug.toString(), projectId.toString(), { + display_filters: { + type: value, + }, + }); }; return (
setPreviewEnabled(!previewEnabled)} /> {previewEnabled && ( -
- {ISSUE_FILTER_OPTIONS.map((_issueType) => ( +
+ {ISSUE_FILTER_OPTIONS.map((issueType) => ( handleIssueType("type", _issueType?.key)} - title={_issueType.title} + key={issueType?.key} + isChecked={issueFilterStore?.userDisplayFilters?.type === issueType?.key ? true : false} + onClick={() => handleIssueType(issueType?.key)} + title={issueType.title} multiple={false} /> ))} diff --git a/web/components/issue-layouts/display-filters/order-by.tsx b/web/components/issue-layouts/display-filters/order-by.tsx index 8159dc641..59993456c 100644 --- a/web/components/issue-layouts/display-filters/order-by.tsx +++ b/web/components/issue-layouts/display-filters/order-by.tsx @@ -1,22 +1,35 @@ import React from "react"; + +import { useRouter } from "next/router"; + +// mobx +import { observer } from "mobx-react-lite"; +import { useMobxStore } from "lib/mobx/store-provider"; // components import { FilterHeader } from "../helpers/filter-header"; import { FilterOption } from "../helpers/filter-option"; -// mobx react lite -import { observer } from "mobx-react-lite"; -// mobx store -import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; +// types +import { TIssueOrderByOptions } from "types"; +// constants import { ISSUE_ORDER_BY_OPTIONS } from "constants/issue"; export const FilterOrderBy = observer(() => { - const store: RootStore = useMobxStore(); + const router = useRouter(); + const { workspaceSlug, projectId } = router.query; + + const store = useMobxStore(); const { issueFilter: issueFilterStore } = store; const [previewEnabled, setPreviewEnabled] = React.useState(true); - const handleOrderBy = (key: string, value: string) => { - // issueFilterStore.handleUserFilter("display_filters", key, value); + const handleOrderBy = (value: TIssueOrderByOptions) => { + if (!workspaceSlug || !projectId) return; + + issueFilterStore.updateUserFilters(workspaceSlug.toString(), projectId.toString(), { + display_filters: { + order_by: value, + }, + }); }; return ( @@ -28,12 +41,12 @@ export const FilterOrderBy = observer(() => { /> {previewEnabled && (
- {ISSUE_ORDER_BY_OPTIONS.map((_orderBy) => ( + {ISSUE_ORDER_BY_OPTIONS.map((orderBy) => ( handleOrderBy("order_by", _orderBy?.key)} - title={_orderBy.title} + key={orderBy?.key} + isChecked={issueFilterStore?.userDisplayFilters?.order_by === orderBy?.key ? true : false} + onClick={() => handleOrderBy(orderBy.key)} + title={orderBy.title} multiple={false} /> ))} diff --git a/web/components/issue-layouts/filters/assignees.tsx b/web/components/issue-layouts/filters/assignees.tsx index 7c2d44993..b60686ea3 100644 --- a/web/components/issue-layouts/filters/assignees.tsx +++ b/web/components/issue-layouts/filters/assignees.tsx @@ -1,67 +1,62 @@ -import React from "react"; -// components -import { FilterHeader } from "../helpers/filter-header"; -import { FilterOption } from "../helpers/filter-option"; -// mobx react lite +import React, { useState } from "react"; + +// mobx import { observer } from "mobx-react-lite"; -// mobx store import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; +// components +import { FilterHeader, FilterOption } from "components/issue-layouts"; +// ui +import { Avatar } from "components/ui"; -export const MemberIcons = ({ display_name, avatar }: { display_name: string; avatar: string | null }) => ( -
- {avatar ? ( - {display_name - ) : ( -
- {(display_name ?? "U")[0]} -
- )} -
-); +type Props = { + workspaceSlug: string; + projectId: string; +}; -export const FilterAssignees = observer(() => { - const store: RootStore = useMobxStore(); - const { issueFilter: issueFilterStore } = store; +export const FilterAssignees: React.FC = observer((props) => { + const { workspaceSlug, projectId } = props; - const [previewEnabled, setPreviewEnabled] = React.useState(true); + const [previewEnabled, setPreviewEnabled] = useState(true); - const handleFilter = (key: string, value: string) => { - // let _value = - // issueFilterStore?.userFilters?.filters?.[key] != null - // ? issueFilterStore?.userFilters?.filters?.[key].includes(value) - // ? issueFilterStore?.userFilters?.filters?.[key].filter((p: string) => p != value) - // : [...issueFilterStore?.userFilters?.filters?.[key], value] - // : [value]; - // _value = _value && _value.length > 0 ? _value : null; - // issueFilterStore.handleUserFilter("filters", key, _value); + const store = useMobxStore(); + const { issueFilter: issueFilterStore, project: projectStore } = store; + + const handleUpdateAssignees = (value: string) => { + const newValues = issueFilterStore.userFilters?.assignees ?? []; + + if (issueFilterStore.userFilters?.assignees?.includes(value)) newValues.splice(newValues.indexOf(value), 1); + else newValues.push(value); + + issueFilterStore.updateUserFilters(workspaceSlug.toString(), projectId.toString(), { + filters: { + assignees: newValues, + }, + }); }; return (
setPreviewEnabled(!previewEnabled)} /> {previewEnabled && (
- {issueFilterStore?.projectMembers && - issueFilterStore?.projectMembers.length > 0 && - issueFilterStore?.projectMembers.map((_member) => ( - handleFilter("assignees", _member?.member?.id)} - icon={} - title={`${_member?.member?.display_name} (${_member?.member?.first_name} ${_member?.member?.last_name})`} - /> - ))} + {projectStore.members?.[projectId?.toString() ?? ""]?.map((member) => ( + handleUpdateAssignees(member.member?.id)} + icon={} + title={member.member?.display_name} + /> + ))}
)}
diff --git a/web/components/issue-layouts/filters/created-by.tsx b/web/components/issue-layouts/filters/created-by.tsx index 35693de2f..42fb8082e 100644 --- a/web/components/issue-layouts/filters/created-by.tsx +++ b/web/components/issue-layouts/filters/created-by.tsx @@ -1,56 +1,57 @@ -import React from "react"; -// components -import { MemberIcons } from "./assignees"; -import { FilterHeader } from "../helpers/filter-header"; -import { FilterOption } from "../helpers/filter-option"; -// mobx react lite +import React, { useState } from "react"; + +// mobx import { observer } from "mobx-react-lite"; -// mobx store import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; +// components +import { FilterHeader, FilterOption } from "components/issue-layouts"; +// ui +import { Avatar } from "components/ui"; -export const FilterCreatedBy = observer(() => { - const store: RootStore = useMobxStore(); - const { issueFilters: issueFilterStore } = store; +type Props = { + workspaceSlug: string; + projectId: string; +}; - const [previewEnabled, setPreviewEnabled] = React.useState(true); +export const FilterCreatedBy: React.FC = observer((props) => { + const { workspaceSlug, projectId } = props; - const handleFilter = (key: string, value: string) => { - let _value = - issueFilterStore?.userFilters?.filters?.[key] != null - ? issueFilterStore?.userFilters?.filters?.[key].includes(value) - ? issueFilterStore?.userFilters?.filters?.[key].filter((p: string) => p != value) - : [...issueFilterStore?.userFilters?.filters?.[key], value] - : [value]; - _value = _value && _value.length > 0 ? _value : null; - issueFilterStore.handleUserFilter("filters", key, _value); + const [previewEnabled, setPreviewEnabled] = useState(true); + + const store = useMobxStore(); + const { issueFilter: issueFilterStore, project: projectStore } = store; + + const handleUpdateCreatedBy = (value: string) => { + const newValues = issueFilterStore.userFilters?.created_by ?? []; + + if (issueFilterStore.userFilters?.created_by?.includes(value)) newValues.splice(newValues.indexOf(value), 1); + else newValues.push(value); + + issueFilterStore.updateUserFilters(workspaceSlug.toString(), projectId.toString(), { + filters: { + created_by: newValues, + }, + }); }; return (
setPreviewEnabled(!previewEnabled)} /> {previewEnabled && ( -
- {issueFilterStore?.projectMembers && - issueFilterStore?.projectMembers.length > 0 && - issueFilterStore?.projectMembers.map((_member) => ( - handleFilter("created_by", _member?.member?.id)} - icon={} - title={`${_member?.member?.display_name} (${_member?.member?.first_name} ${_member?.member?.last_name})`} - /> - ))} +
+ {projectStore.members?.[projectId?.toString() ?? ""]?.map((member) => ( + handleUpdateCreatedBy(member.member?.id)} + icon={} + title={member.member?.display_name} + /> + ))}
)}
diff --git a/web/components/issue-layouts/filters/filter-selection.tsx b/web/components/issue-layouts/filters/filter-selection.tsx new file mode 100644 index 000000000..5e20d384a --- /dev/null +++ b/web/components/issue-layouts/filters/filter-selection.tsx @@ -0,0 +1,71 @@ +import React from "react"; + +// components +import { + FilterAssignees, + FilterCreatedBy, + FilterLabels, + FilterPriority, + FilterState, + FilterStateGroup, +} from "components/issue-layouts"; + +type Props = { + workspaceSlug: string; + projectId: string; +}; + +export const FilterSelection: React.FC = (props) => { + const { workspaceSlug, projectId } = props; + + return ( +
+ {/*
Search container
*/} +
+ {/* priority */} +
+ +
+ + {/* state group */} +
+ +
+ + {/* state */} +
+ +
+ + {/* assignees */} +
+ +
+ + {/* created_by */} +
+ +
+ + {/* labels */} +
+ +
+ + {/* start_date */} + {/* {handleFilterSectionVisibility("start_date") && ( +
+ +
+ )} */} + + {/* due_date */} + {/* {handleFilterSectionVisibility("due_date") && ( +
+ +
+ )} */} +
+
+ ); +}; diff --git a/web/components/issue-layouts/filters/index.ts b/web/components/issue-layouts/filters/index.ts new file mode 100644 index 000000000..e804899d2 --- /dev/null +++ b/web/components/issue-layouts/filters/index.ts @@ -0,0 +1,9 @@ +export * from "./assignees"; +export * from "./created-by"; +export * from "./filter-selection"; +export * from "./labels"; +export * from "./priority"; +export * from "./start-date"; +export * from "./state-group"; +export * from "./state"; +export * from "./target-date"; diff --git a/web/components/issue-layouts/filters/index.tsx b/web/components/issue-layouts/filters/index.tsx deleted file mode 100644 index c52cf5be1..000000000 --- a/web/components/issue-layouts/filters/index.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import React from "react"; -// components -import { FilterPriority } from "./priority"; -import { FilterState } from "./state"; -import { FilterStateGroup } from "./state-group"; -import { FilterAssignees } from "./assignees"; -import { FilterCreatedBy } from "./created-by"; -import { FilterLabels } from "./labels"; -import { FilterStartDate } from "./start-date"; -import { FilterTargetDate } from "./target-date"; -// mobx react lite -import { observer } from "mobx-react-lite"; -// mobx store -import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; -// default data -import { issueFilterVisibilityData } from "store/helpers/issue-data"; - -export const FilterSelection = observer(() => { - const store: RootStore = useMobxStore(); - const { issueFilters: issueFilterStore } = store; - - const handleFilterSectionVisibility = (section_key: string) => - issueFilterStore?.issueView && - issueFilterStore?.issueLayout && - issueFilterVisibilityData[issueFilterStore?.issueView === "my_issues" ? "my_issues" : "issues"]?.filters?.[ - issueFilterStore?.issueLayout - ]?.includes(section_key); - - return ( -
-
Search container
-
- {/* priority */} - {handleFilterSectionVisibility("priority") && ( -
- -
- )} - - {/* state group */} - {handleFilterSectionVisibility("state_group") && ( -
- -
- )} - - {/* state */} - {handleFilterSectionVisibility("state") && ( -
- -
- )} - - {/* assignees */} - {handleFilterSectionVisibility("assignees") && ( -
- -
- )} - - {/* created_by */} - {handleFilterSectionVisibility("created_by") && ( -
- -
- )} - - {/* labels */} - {handleFilterSectionVisibility("labels") && ( -
- -
- )} - - {/* start_date */} - {handleFilterSectionVisibility("start_date") && ( -
- -
- )} - - {/* due_date */} - {handleFilterSectionVisibility("due_date") && ( -
- -
- )} -
-
- ); -}); diff --git a/web/components/issue-layouts/filters/labels.tsx b/web/components/issue-layouts/filters/labels.tsx index 4c42e8af9..52191b1bf 100644 --- a/web/components/issue-layouts/filters/labels.tsx +++ b/web/components/issue-layouts/filters/labels.tsx @@ -1,66 +1,60 @@ -import React from "react"; +import React, { useState } from "react"; + // components -import { FilterHeader } from "../helpers/filter-header"; -import { FilterOption } from "../helpers/filter-option"; +import { FilterHeader, FilterOption } from "components/issue-layouts"; // mobx react lite import { observer } from "mobx-react-lite"; // mobx store import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; const LabelIcons = ({ color }: { color: string }) => ( -
-
-
+ ); -export const FilterLabels = observer(() => { - const store: RootStore = useMobxStore(); - const { issueFilters: issueFilterStore } = store; +type Props = { + workspaceSlug: string; + projectId: string; +}; - const [previewEnabled, setPreviewEnabled] = React.useState(true); +export const FilterLabels: React.FC = observer((props) => { + const { workspaceSlug, projectId } = props; - const handleFilter = (key: string, value: string) => { - let _value = - issueFilterStore?.userFilters?.filters?.[key] != null - ? issueFilterStore?.userFilters?.filters?.[key].includes(value) - ? issueFilterStore?.userFilters?.filters?.[key].filter((p: string) => p != value) - : [...issueFilterStore?.userFilters?.filters?.[key], value] - : [value]; - _value = _value && _value.length > 0 ? _value : null; - issueFilterStore.handleUserFilter("filters", key, _value); + const [previewEnabled, setPreviewEnabled] = useState(true); + + const store = useMobxStore(); + const { issueFilter: issueFilterStore, project: projectStore } = store; + + const handleUpdateLabels = (value: string) => { + const newValues = issueFilterStore.userFilters?.labels ?? []; + + if (issueFilterStore.userFilters?.labels?.includes(value)) newValues.splice(newValues.indexOf(value), 1); + else newValues.push(value); + + issueFilterStore.updateUserFilters(workspaceSlug.toString(), projectId.toString(), { + filters: { + labels: newValues, + }, + }); }; - const handleLabels = - issueFilterStore.issueView && issueFilterStore.issueView === "my_issues" - ? issueFilterStore?.workspaceLabels - : issueFilterStore?.projectLabels; - return (
setPreviewEnabled(!previewEnabled)} /> {previewEnabled && (
- {handleLabels && - handleLabels.length > 0 && - handleLabels.map((_label) => ( - handleFilter("labels", _label?.id)} - icon={} - title={_label.name} - /> - ))} + {projectStore.labels?.[projectId?.toString() ?? ""]?.map((label) => ( + handleUpdateLabels(label?.id)} + icon={} + title={label.name} + /> + ))}
)}
diff --git a/web/components/issue-layouts/filters/priority.tsx b/web/components/issue-layouts/filters/priority.tsx index 2bbcce8f7..8260154e9 100644 --- a/web/components/issue-layouts/filters/priority.tsx +++ b/web/components/issue-layouts/filters/priority.tsx @@ -1,19 +1,19 @@ -import React from "react"; -// lucide icons -import { AlertCircle, SignalHigh, SignalMedium, SignalLow, Ban } from "lucide-react"; -// components -import { FilterHeader } from "../helpers/filter-header"; -import { FilterOption } from "../helpers/filter-option"; -// mobx react lite +import React, { useState } from "react"; + +// mobx import { observer } from "mobx-react-lite"; -// mobx store import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; +// components +import { FilterHeader, FilterOption } from "components/issue-layouts"; +// icons +import { AlertCircle, SignalHigh, SignalMedium, SignalLow, Ban } from "lucide-react"; +// constants +import { ISSUE_PRIORITIES } from "constants/issue"; const PriorityIcons = ({ priority, - size = 14, - strokeWidth = 2, + size = 12, + strokeWidth = 1.5, }: { priority: string; size?: number; @@ -21,84 +21,78 @@ const PriorityIcons = ({ }) => { if (priority === "urgent") return ( -
+
); if (priority === "high") return ( -
+
); if (priority === "medium") return ( -
+
); if (priority === "low") return ( -
+
); return ( -
+
); }; -export const FilterPriority = observer(() => { - const store: RootStore = useMobxStore(); - const { issueFilters: issueFilterStore } = store; +type Props = { workspaceSlug: string; projectId: string }; - const [previewEnabled, setPreviewEnabled] = React.useState(true); +export const FilterPriority: React.FC = observer((props) => { + const { workspaceSlug, projectId } = props; - const handleFilter = (key: string, value: string) => { - let _value = - issueFilterStore?.userFilters?.filters?.[key] != null - ? issueFilterStore?.userFilters?.filters?.[key].includes(value) - ? issueFilterStore?.userFilters?.filters?.[key].filter((p: string) => p != value) - : [...issueFilterStore?.userFilters?.filters?.[key], value] - : [value]; - _value = _value && _value.length > 0 ? _value : null; - issueFilterStore.handleUserFilter("filters", key, _value); + const [previewEnabled, setPreviewEnabled] = useState(true); + + const store = useMobxStore(); + const { issueFilter: issueFilterStore } = store; + + const handleUpdatePriority = (value: string) => { + const newValues = issueFilterStore.userFilters?.priority ?? []; + + if (issueFilterStore.userFilters?.priority?.includes(value)) newValues.splice(newValues.indexOf(value), 1); + else newValues.push(value); + + issueFilterStore.updateUserFilters(workspaceSlug.toString(), projectId.toString(), { + filters: { + priority: newValues, + }, + }); }; return ( -
+ <> setPreviewEnabled(!previewEnabled)} /> {previewEnabled && ( -
- {issueFilterStore?.issueRenderFilters?.priority && - issueFilterStore?.issueRenderFilters?.priority.length > 0 && - issueFilterStore?.issueRenderFilters?.priority.map((_priority) => ( - handleFilter("priority", _priority?.key)} - icon={} - title={_priority.title} - /> - ))} -
-
View less
-
View more
- {/* TODO:
View all
*/} -
+
+ {ISSUE_PRIORITIES.map((priority) => ( + handleUpdatePriority(priority.key)} + icon={} + title={priority.title} + /> + ))}
)} -
+ ); }); diff --git a/web/components/issue-layouts/filters/start-date.tsx b/web/components/issue-layouts/filters/start-date.tsx index 8c92518af..c2e038100 100644 --- a/web/components/issue-layouts/filters/start-date.tsx +++ b/web/components/issue-layouts/filters/start-date.tsx @@ -1,45 +1,32 @@ import React from "react"; -// components -import { FilterHeader } from "../helpers/filter-header"; -import { FilterOption } from "../helpers/filter-option"; -// mobx react lite + +// mobx import { observer } from "mobx-react-lite"; -// mobx store import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; +// components +import { FilterHeader, FilterOption } from "components/issue-layouts"; export const FilterStartDate = observer(() => { - const store: RootStore = useMobxStore(); - const { issueFilters: issueFilterStore } = store; + const store = useMobxStore(); + const { issueFilter: issueFilterStore } = store; const [previewEnabled, setPreviewEnabled] = React.useState(true); - const handleFilter = (key: string, value: string) => { - const _value = [value]; - issueFilterStore.handleUserFilter("filters", key, _value); - }; - return (
setPreviewEnabled(!previewEnabled)} /> {previewEnabled && ( -
- {issueFilterStore?.issueRenderFilters?.start_date && - issueFilterStore?.issueRenderFilters?.start_date.length > 0 && - issueFilterStore?.issueRenderFilters?.start_date.map((_startDate) => ( +
+ {issueFilterStore?.userFilters?.start_date && + issueFilterStore?.userFilters?.start_date.length > 0 && + issueFilterStore?.userFilters?.start_date.map((_startDate) => ( handleFilter("start_date", _startDate?.key)} + isChecked={issueFilterStore?.userFilters?.start_date?.includes(_startDate?.key) ? true : false} title={_startDate.title} multiple={false} /> diff --git a/web/components/issue-layouts/filters/state-group.tsx b/web/components/issue-layouts/filters/state-group.tsx index dcfd71cbf..7b1613896 100644 --- a/web/components/issue-layouts/filters/state-group.tsx +++ b/web/components/issue-layouts/filters/state-group.tsx @@ -1,108 +1,59 @@ -import React from "react"; -import { - StateGroupBacklogIcon, - StateGroupCancelledIcon, - StateGroupCompletedIcon, - StateGroupStartedIcon, - StateGroupUnstartedIcon, -} from "components/icons"; -// components -import { FilterHeader } from "../helpers/filter-header"; -import { FilterOption } from "../helpers/filter-option"; -// mobx react lite -import { observer } from "mobx-react-lite"; -// mobx store -import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; -// constants -import { STATE_GROUP_COLORS } from "constants/state"; +import React, { useState } from "react"; -export const StateGroupIcons = ({ - stateGroup, - width = "14px", - height = "14px", - color = null, -}: { - stateGroup: string; - width?: string | undefined; - height?: string | undefined; - color?: string | null; -}) => { - if (stateGroup === "cancelled") - return ( -
- -
- ); - if (stateGroup === "completed") - return ( -
- -
- ); - if (stateGroup === "started") - return ( -
- -
- ); - if (stateGroup === "unstarted") - return ( -
- -
- ); - if (stateGroup === "backlog") - return ( -
- -
- ); - return <>; +// mobx +import { observer } from "mobx-react-lite"; +import { useMobxStore } from "lib/mobx/store-provider"; +// components +import { FilterHeader, FilterOption } from "components/issue-layouts"; +// icons +import { StateGroupIcon } from "components/icons"; +// constants +import { ISSUE_STATE_GROUPS } from "constants/issue"; + +type Props = { + workspaceSlug: string; + projectId: string; }; -export const FilterStateGroup = observer(() => { - const store: RootStore = useMobxStore(); - const { issueFilters: issueFilterStore } = store; +export const FilterStateGroup: React.FC = observer((props) => { + const { workspaceSlug, projectId } = props; - const [previewEnabled, setPreviewEnabled] = React.useState(true); + const [previewEnabled, setPreviewEnabled] = useState(true); - const handleFilter = (key: string, value: string) => { - let _value = - issueFilterStore?.userFilters?.filters?.[key] != null - ? issueFilterStore?.userFilters?.filters?.[key].includes(value) - ? issueFilterStore?.userFilters?.filters?.[key].filter((p: string) => p != value) - : [...issueFilterStore?.userFilters?.filters?.[key], value] - : [value]; - _value = _value && _value.length > 0 ? _value : null; - issueFilterStore.handleUserFilter("filters", key, _value); + const store = useMobxStore(); + const { issueFilter: issueFilterStore } = store; + + const handleUpdateStateGroup = (value: string) => { + const newValues = issueFilterStore.userFilters?.state_group ?? []; + + if (issueFilterStore.userFilters?.state_group?.includes(value)) newValues.splice(newValues.indexOf(value), 1); + else newValues.push(value); + + issueFilterStore.updateUserFilters(workspaceSlug.toString(), projectId.toString(), { + filters: { + state_group: newValues, + }, + }); }; return (
setPreviewEnabled(!previewEnabled)} /> {previewEnabled && ( -
- {issueFilterStore?.issueRenderFilters?.state_group && - issueFilterStore?.issueRenderFilters?.state_group.length > 0 && - issueFilterStore?.issueRenderFilters?.state_group.map((_stateGroup) => ( - handleFilter("state_group", _stateGroup?.key)} - icon={} - title={_stateGroup.title} - /> - ))} +
+ {ISSUE_STATE_GROUPS.map((stateGroup) => ( + handleUpdateStateGroup(stateGroup.key)} + icon={} + title={stateGroup.title} + /> + ))}
)}
diff --git a/web/components/issue-layouts/filters/state.tsx b/web/components/issue-layouts/filters/state.tsx index ef59fa0ca..410541806 100644 --- a/web/components/issue-layouts/filters/state.tsx +++ b/web/components/issue-layouts/filters/state.tsx @@ -1,68 +1,62 @@ import React from "react"; -// components -import { StateGroupIcons } from "./state-group"; -import { FilterHeader } from "../helpers/filter-header"; -import { FilterOption } from "../helpers/filter-option"; -// mobx react lite -import { observer } from "mobx-react-lite"; -// mobx store -import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; -// store default data -import { stateGroups } from "store/helpers/issue-data"; -export const FilterState = observer(() => { - const store: RootStore = useMobxStore(); - const { issueFilters: issueFilterStore } = store; +// mobx +import { observer } from "mobx-react-lite"; +import { useMobxStore } from "lib/mobx/store-provider"; +// components +import { FilterHeader, FilterOption } from "components/issue-layouts"; +// icons +import { StateGroupIcon } from "components/icons"; +// helpers +import { getStatesList } from "helpers/state.helper"; + +type Props = { + workspaceSlug: string; + projectId: string; +}; + +export const FilterState: React.FC = observer((props) => { + const { workspaceSlug, projectId } = props; + + const store = useMobxStore(); + const { issueFilter: issueFilterStore, project: projectStore } = store; const [previewEnabled, setPreviewEnabled] = React.useState(true); - const handleFilter = (key: string, value: string) => { - let _value = - issueFilterStore?.userFilters?.filters?.[key] != null - ? issueFilterStore?.userFilters?.filters?.[key].includes(value) - ? issueFilterStore?.userFilters?.filters?.[key].filter((p: string) => p != value) - : [...issueFilterStore?.userFilters?.filters?.[key], value] - : [value]; - _value = _value && _value.length > 0 ? _value : null; - issueFilterStore.handleUserFilter("filters", key, _value); + const statesByGroups = projectStore.states?.[projectId?.toString() ?? ""]; + const statesList = getStatesList(statesByGroups); + + const handleUpdateState = (value: string) => { + const newValues = issueFilterStore.userFilters?.state ?? []; + + if (issueFilterStore.userFilters?.state?.includes(value)) newValues.splice(newValues.indexOf(value), 1); + else newValues.push(value); + + issueFilterStore.updateUserFilters(workspaceSlug.toString(), projectId.toString(), { + filters: { + state: newValues, + }, + }); }; - const countAllState = stateGroups - .map((_stateGroup) => issueFilterStore?.projectStates?.[_stateGroup?.key].length || 0) - .reduce((sum: number, currentValue: number) => sum + currentValue, 0); - - console.log("countAllState", countAllState); - return (
setPreviewEnabled(!previewEnabled)} /> {previewEnabled && ( -
- {stateGroups.map( - (_stateGroup) => - issueFilterStore?.projectStates && - issueFilterStore?.projectStates[_stateGroup?.key] && - issueFilterStore?.projectStates[_stateGroup?.key].length > 0 && - issueFilterStore?.projectStates[_stateGroup?.key].map((_state: any) => ( - handleFilter("state", _state?.id)} - icon={} - title={_state?.name} - /> - )) - )} +
+ {statesList?.map((state) => ( + handleUpdateState(state?.id)} + icon={} + title={state?.name} + /> + ))}
)}
diff --git a/web/components/issue-layouts/filters/target-date.tsx b/web/components/issue-layouts/filters/target-date.tsx index cec765b05..44a54f7aa 100644 --- a/web/components/issue-layouts/filters/target-date.tsx +++ b/web/components/issue-layouts/filters/target-date.tsx @@ -1,46 +1,32 @@ import React from "react"; -// components -import { FilterHeader } from "../helpers/filter-header"; -import { FilterOption } from "../helpers/filter-option"; -// mobx react lite +// mobx import { observer } from "mobx-react-lite"; -// mobx store import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; +// components +import { FilterHeader, FilterOption } from "components/issue-layouts"; export const FilterTargetDate = observer(() => { - const store: RootStore = useMobxStore(); - const { issueFilters: issueFilterStore } = store; + const store = useMobxStore(); + const { issueFilter: issueFilterStore } = store; const [previewEnabled, setPreviewEnabled] = React.useState(true); - const handleFilter = (key: string, value: string) => { - const _value = [value]; - issueFilterStore.handleUserFilter("filters", key, _value); - }; - return (
setPreviewEnabled(!previewEnabled)} /> {previewEnabled && (
- {issueFilterStore?.issueRenderFilters?.due_date && - issueFilterStore?.issueRenderFilters?.due_date.length > 0 && - issueFilterStore?.issueRenderFilters?.due_date.map((_targetDate) => ( + {issueFilterStore?.userFilters?.target_date && + issueFilterStore?.userFilters?.target_date.length > 0 && + issueFilterStore?.userFilters?.target_date.map((_targetDate) => ( handleFilter("target_date", _targetDate?.key)} + isChecked={issueFilterStore?.userFilters?.target_date?.includes(_targetDate?.key) ? true : false} title={_targetDate.title} multiple={false} /> diff --git a/web/components/issue-layouts/helpers/dropdown.tsx b/web/components/issue-layouts/helpers/dropdown.tsx index 4e12c2bc0..1358b787c 100644 --- a/web/components/issue-layouts/helpers/dropdown.tsx +++ b/web/components/issue-layouts/helpers/dropdown.tsx @@ -1,8 +1,9 @@ import { Fragment } from "react"; + // headless ui import { Popover, Transition } from "@headlessui/react"; -// lucide icons -import { ChevronDown, ChevronUp } from "lucide-react"; +// icons +import { ChevronUp } from "lucide-react"; interface IIssueDropdown { children: React.ReactNode; @@ -17,11 +18,13 @@ export const IssueDropdown = ({ children, title = "Dropdown" }: IIssueDropdown) return ( <>
{title}
-
- {open ? : } +
+
- -
- {children} -
+ + {children}
diff --git a/web/components/issue-layouts/helpers/filter-header.tsx b/web/components/issue-layouts/helpers/filter-header.tsx index 9a077bc01..909e4026c 100644 --- a/web/components/issue-layouts/helpers/filter-header.tsx +++ b/web/components/issue-layouts/helpers/filter-header.tsx @@ -9,13 +9,14 @@ interface IFilterHeader { } export const FilterHeader = ({ title, isPreviewEnabled, handleIsPreviewEnabled }: IFilterHeader) => ( -
-
{title}
-
+
{title}
+
+
); diff --git a/web/components/issue-layouts/helpers/filter-option.tsx b/web/components/issue-layouts/helpers/filter-option.tsx index 63abda72f..a67c1142f 100644 --- a/web/components/issue-layouts/helpers/filter-option.tsx +++ b/web/components/issue-layouts/helpers/filter-option.tsx @@ -2,27 +2,34 @@ import React from "react"; // lucide icons import { Check } from "lucide-react"; -interface IFilterOption { - isChecked: boolean; +type Props = { icon?: React.ReactNode; - title: string; - multiple?: boolean; + isChecked: boolean; + title: React.ReactNode; onClick?: () => void; -} + multiple?: boolean; +}; -export const FilterOption = ({ isChecked, icon, title, multiple = true, onClick }: IFilterOption) => ( -
-
= (props) => { + const { icon, isChecked, multiple = true, onClick, title } = props; + + return ( +
- {icon} -
{title}
-
-); +
+ {isChecked && } +
+
+
{icon}
+
{title}
+
+ + ); +}; diff --git a/web/components/issue-layouts/helpers/index.ts b/web/components/issue-layouts/helpers/index.ts new file mode 100644 index 000000000..ef38d9884 --- /dev/null +++ b/web/components/issue-layouts/helpers/index.ts @@ -0,0 +1,3 @@ +export * from "./dropdown"; +export * from "./filter-header"; +export * from "./filter-option"; diff --git a/web/components/issue-layouts/index.ts b/web/components/issue-layouts/index.ts new file mode 100644 index 000000000..61375f0ff --- /dev/null +++ b/web/components/issue-layouts/index.ts @@ -0,0 +1,4 @@ +export * from "./display-filters"; +export * from "./filters"; +export * from "./helpers"; +export * from "./layout-selection"; diff --git a/web/components/issue-layouts/layout-selection.tsx b/web/components/issue-layouts/layout-selection.tsx index a6629a2aa..335ea6208 100644 --- a/web/components/issue-layouts/layout-selection.tsx +++ b/web/components/issue-layouts/layout-selection.tsx @@ -1,97 +1,37 @@ import React from "react"; -// lucide icons -import { Columns, Grid3x3, Calendar, GanttChart, List } from "lucide-react"; -// mobx react lite -import { observer } from "mobx-react-lite"; -// mobx store -import { RootStore } from "store/root"; -import { useMobxStore } from "lib/mobx/store-provider"; -// types and default data -import { TIssueLayouts } from "store/issue_filters.legacy"; -import { issueFilterVisibilityData } from "store/helpers/issue-data"; -export const LayoutSelection = observer(() => { - const store: RootStore = useMobxStore(); - const { issueFilters: issueFilterStore, issueView: issueStore } = store; +// types +import { TIssueLayouts } from "types"; +// constants +import { ISSUE_LAYOUTS } from "constants/issue"; - const layoutSelectionFilters: { key: TIssueLayouts; title: string; icon: any }[] = [ - { - key: "list", - title: "List", - icon: List, - }, - { - key: "kanban", - title: "Kanban", - icon: Grid3x3, - }, - { - key: "calendar", - title: "Calendar", - icon: Calendar, - }, - { - key: "spreadsheet", - title: "Spreadsheet", - icon: Columns, - }, - { - key: "gantt_chart", - title: "Gantt", - icon: GanttChart, - }, - ]; +type Props = { + layouts: TIssueLayouts[]; + onChange: (layout: TIssueLayouts) => void; + selectedLayout: TIssueLayouts; +}; - const handleLayoutSectionVisibility = (layout_key: string) => - issueFilterStore?.issueView && - issueFilterVisibilityData[issueFilterStore?.issueView === "my_issues" ? "my_issues" : "issues"].layout.includes( - layout_key - ); - - const handleLayoutSelection = (_layoutKey: string) => { - issueFilterStore.handleUserFilter("display_filters", "layout", _layoutKey); - }; - - // console.log("----"); - // console.log("my_user_id", issueFilterStore.myUserId); - // console.log("workspace_id", issueFilterStore.workspaceId); - // console.log("project_id", issueFilterStore.projectId); - // console.log("module_id", issueFilterStore.moduleId); - // console.log("cycle_id", issueFilterStore.cycleId); - // console.log("view_id", issueFilterStore.viewId); - - // console.log("issue_view", issueFilterStore.issueView); - // console.log("issue_layout", issueFilterStore.issueLayout); - - // console.log("user_filters", issueFilterStore.userFilters); - // console.log("issues", issueStore.issues); - // console.log("issues", issueStore.getIssues); - // console.log("----"); +export const LayoutSelection: React.FC = (props) => { + const { layouts, onChange, selectedLayout } = props; return ( -
- {layoutSelectionFilters.map( - (_layout) => - handleLayoutSectionVisibility(_layout?.key) && ( -
handleLayoutSelection(_layout?.key)} - > - <_layout.icon - size={14} - strokeWidth={2} - className={`${ - issueFilterStore?.issueLayout == _layout?.key - ? `text-custom-text-100` - : `text-custom-text-100 group-hover:text-custom-text-200` - }`} - /> -
- ) - )} +
+ {ISSUE_LAYOUTS.filter((l) => layouts.includes(l.key)).map((layout) => ( + + ))}
); -}); +}; diff --git a/web/components/issue-layouts/root.tsx b/web/components/issue-layouts/root.tsx index 1db144bd9..1c5752af0 100644 --- a/web/components/issue-layouts/root.tsx +++ b/web/components/issue-layouts/root.tsx @@ -2,7 +2,7 @@ import React from "react"; // components import { LayoutSelection } from "./layout-selection"; import { IssueDropdown } from "./helpers/dropdown"; -import { FilterSelection } from "./filters"; +import { FilterSelection } from "./filters/filter-selection"; import { DisplayFiltersSelection } from "./display-filters"; import { FilterPreview } from "./filters-preview"; diff --git a/web/components/issues/my-issues/my-issues-view-options.tsx b/web/components/issues/my-issues/my-issues-view-options.tsx index 90d9b8971..f9aa62c2f 100644 --- a/web/components/issues/my-issues/my-issues-view-options.tsx +++ b/web/components/issues/my-issues/my-issues-view-options.tsx @@ -18,11 +18,11 @@ import { FormatListBulletedOutlined, GridViewOutlined } from "@mui/icons-materia import { replaceUnderscoreIfSnakeCase } from "helpers/string.helper"; import { checkIfArraysHaveSameElements } from "helpers/array.helper"; // types -import { Properties, TIssueViewOptions } from "types"; +import { Properties, TIssueLayouts } from "types"; // constants import { GROUP_BY_OPTIONS, ORDER_BY_OPTIONS, FILTER_ISSUE_OPTIONS } from "constants/issue"; -const issueViewOptions: { type: TIssueViewOptions; Icon: any }[] = [ +const issueViewOptions: { type: TIssueLayouts; Icon: any }[] = [ { type: "list", Icon: FormatListBulletedOutlined, @@ -37,8 +37,9 @@ export const MyIssuesViewOptions: React.FC = () => { const router = useRouter(); const { workspaceSlug } = router.query; - const { displayFilters, setDisplayFilters, properties, setProperty, filters, setFilters } = - useMyIssuesFilters(workspaceSlug?.toString()); + const { displayFilters, setDisplayFilters, properties, setProperty, filters, setFilters } = useMyIssuesFilters( + workspaceSlug?.toString() + ); const { isEstimateActive } = useEstimateOption(); @@ -48,9 +49,7 @@ export const MyIssuesViewOptions: React.FC = () => { {issueViewOptions.map((option) => ( {replaceUnderscoreIfSnakeCase(option.type)} View - } + tooltipContent={{replaceUnderscoreIfSnakeCase(option.type)} View} position="bottom" >