From 0ec0ad6abafa1d109eb381099d691625a1347453 Mon Sep 17 00:00:00 2001 From: gurusainath Date: Wed, 13 Sep 2023 19:40:35 +0530 Subject: [PATCH] chore: implemented filters and views in kanaban --- .../display-filters/display-properties.tsx | 43 ++ .../display-filters/extra-options.tsx | 43 ++ .../display-filters/group-by.tsx | 44 ++ .../issue-layouts/display-filters/index.tsx | 52 ++- .../display-filters/issue-type.tsx | 44 ++ .../display-filters/order-by.tsx | 44 ++ .../issue-layouts/filters/assignees.tsx | 13 +- .../issue-layouts/filters/created-by.tsx | 11 +- .../issue-layouts/filters/index.tsx | 43 +- .../issue-layouts/filters/labels.tsx | 13 +- .../issue-layouts/filters/priority.tsx | 18 +- .../issue-layouts/filters/start-date.tsx | 4 +- .../issue-layouts/filters/state-group.tsx | 11 +- .../issue-layouts/filters/state.tsx | 11 +- .../issue-layouts/filters/target-date.tsx | 4 +- .../issue-layouts/helpers/dropdown.tsx | 50 +++ .../issue-layouts/helpers/filter-header.tsx | 10 +- .../issue-layouts/helpers/filter-option.tsx | 4 +- web/components/issue-layouts/kanban/index.tsx | 22 - .../issue-layouts/layout-selection.tsx | 4 +- web/pages/kanban.tsx | 22 +- web/store/issue-views/Issues.ts | 4 +- web/store/issue-views/issue_data.ts | 13 +- web/store/issue-views/issue_filters.ts | 401 +++++++++++------- 24 files changed, 667 insertions(+), 261 deletions(-) create mode 100644 web/components/issue-layouts/display-filters/display-properties.tsx create mode 100644 web/components/issue-layouts/display-filters/extra-options.tsx create mode 100644 web/components/issue-layouts/display-filters/group-by.tsx create mode 100644 web/components/issue-layouts/display-filters/issue-type.tsx create mode 100644 web/components/issue-layouts/display-filters/order-by.tsx create mode 100644 web/components/issue-layouts/helpers/dropdown.tsx diff --git a/web/components/issue-layouts/display-filters/display-properties.tsx b/web/components/issue-layouts/display-filters/display-properties.tsx new file mode 100644 index 000000000..40be9345b --- /dev/null +++ b/web/components/issue-layouts/display-filters/display-properties.tsx @@ -0,0 +1,43 @@ +import React from "react"; +// 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"; + +export const FilterDisplayProperties = observer(() => { + const store: RootStore = useMobxStore(); + const { issueFilters: issueFilterStore, issueView: issueStore } = store; + + const [previewEnabled, setPreviewEnabled] = React.useState(true); + + return ( +
+ setPreviewEnabled(!previewEnabled)} + /> + {previewEnabled && ( +
+ {issueFilterStore?.issueRenderFilters?.display_properties && + issueFilterStore?.issueRenderFilters?.display_properties.length > 0 && + issueFilterStore?.issueRenderFilters?.display_properties.map((_displayProperties) => ( +
+ {_displayProperties?.title} +
+ ))} +
+ )} +
+ ); +}); diff --git a/web/components/issue-layouts/display-filters/extra-options.tsx b/web/components/issue-layouts/display-filters/extra-options.tsx new file mode 100644 index 000000000..3e74e91d3 --- /dev/null +++ b/web/components/issue-layouts/display-filters/extra-options.tsx @@ -0,0 +1,43 @@ +import React from "react"; +// 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"; + +export const FilterExtraOptions = observer(() => { + const store: RootStore = useMobxStore(); + const { issueFilters: issueFilterStore, issueView: issueStore } = store; + + const [previewEnabled, setPreviewEnabled] = React.useState(true); + + return ( +
+ setPreviewEnabled(!previewEnabled)} + /> + {previewEnabled && ( +
+ {issueFilterStore?.issueRenderFilters?.extra_properties && + issueFilterStore?.issueRenderFilters?.extra_properties.length > 0 && + issueFilterStore?.issueRenderFilters?.extra_properties.map((_extraProperties) => ( + + ))} +
+ )} +
+ ); +}); diff --git a/web/components/issue-layouts/display-filters/group-by.tsx b/web/components/issue-layouts/display-filters/group-by.tsx new file mode 100644 index 000000000..43ee083e0 --- /dev/null +++ b/web/components/issue-layouts/display-filters/group-by.tsx @@ -0,0 +1,44 @@ +import React from "react"; +// 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"; + +export const FilterGroupBy = observer(() => { + const store: RootStore = useMobxStore(); + const { issueFilters: issueFilterStore, issueView: issueStore } = store; + + const [previewEnabled, setPreviewEnabled] = React.useState(true); + + return ( +
+ setPreviewEnabled(!previewEnabled)} + /> + {previewEnabled && ( +
+ {issueFilterStore?.issueRenderFilters?.group_by && + issueFilterStore?.issueRenderFilters?.group_by.length > 0 && + issueFilterStore?.issueRenderFilters?.group_by.map((_groupBy) => ( + + ))} +
+ )} +
+ ); +}); diff --git a/web/components/issue-layouts/display-filters/index.tsx b/web/components/issue-layouts/display-filters/index.tsx index 33561c0ae..5a3fb3a08 100644 --- a/web/components/issue-layouts/display-filters/index.tsx +++ b/web/components/issue-layouts/display-filters/index.tsx @@ -1,15 +1,45 @@ import React from "react"; -// mobx store -import { useMobxStore } from "lib/mobx/store-provider"; -import { RootStore } from "store/root"; +// 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"; -export const DisplayPropertiesSelection = () => { - const store: RootStore = useMobxStore(); - const { issueFilters: issueFilterStore, issueView: issueStore } = store; +// const store: RootStore = useMobxStore(); +// const { issueFilters: issueFilterStore, issueView: issueViewStore } = store; - return ( -
-
Filter Selection
+export const DisplayFiltersSelection = () => ( +
+
+ Search container
- ); -}; +
+ {/* display properties */} +
+ +
+ {/* group by */} +
+ +
+ {/* order by */} +
+ +
+ {/* issue type */} +
+ +
+ {/* Options */} +
+ +
+
+
+); diff --git a/web/components/issue-layouts/display-filters/issue-type.tsx b/web/components/issue-layouts/display-filters/issue-type.tsx new file mode 100644 index 000000000..7171162c7 --- /dev/null +++ b/web/components/issue-layouts/display-filters/issue-type.tsx @@ -0,0 +1,44 @@ +import React from "react"; +// 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"; + +export const FilterIssueType = observer(() => { + const store: RootStore = useMobxStore(); + const { issueFilters: issueFilterStore, issueView: issueStore } = store; + + const [previewEnabled, setPreviewEnabled] = React.useState(true); + + return ( +
+ setPreviewEnabled(!previewEnabled)} + /> + {previewEnabled && ( +
+ {issueFilterStore?.issueRenderFilters?.issue_type && + issueFilterStore?.issueRenderFilters?.issue_type.length > 0 && + issueFilterStore?.issueRenderFilters?.issue_type.map((_issueType) => ( + + ))} +
+ )} +
+ ); +}); diff --git a/web/components/issue-layouts/display-filters/order-by.tsx b/web/components/issue-layouts/display-filters/order-by.tsx new file mode 100644 index 000000000..7ada18cab --- /dev/null +++ b/web/components/issue-layouts/display-filters/order-by.tsx @@ -0,0 +1,44 @@ +import React from "react"; +// 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"; + +export const FilterOrderBy = observer(() => { + const store: RootStore = useMobxStore(); + const { issueFilters: issueFilterStore, issueView: issueStore } = store; + + const [previewEnabled, setPreviewEnabled] = React.useState(true); + + return ( +
+ setPreviewEnabled(!previewEnabled)} + /> + {previewEnabled && ( +
+ {issueFilterStore?.issueRenderFilters?.order_by && + issueFilterStore?.issueRenderFilters?.order_by.length > 0 && + issueFilterStore?.issueRenderFilters?.order_by.map((_orderBy) => ( + + ))} +
+ )} +
+ ); +}); diff --git a/web/components/issue-layouts/filters/assignees.tsx b/web/components/issue-layouts/filters/assignees.tsx index 2e5c96a47..e8e222aa8 100644 --- a/web/components/issue-layouts/filters/assignees.tsx +++ b/web/components/issue-layouts/filters/assignees.tsx @@ -17,7 +17,7 @@ export const MemberIcons = ({ display_name: string; avatar: string | null; }) => ( -
+
{avatar ? ( {display_name ) : ( @@ -32,14 +32,14 @@ export const FilterAssignees = observer(() => { const store: RootStore = useMobxStore(); const { issueFilters: issueFilterStore, issueView: issueStore } = store; - const [previewEnabled, setPreviewEnabled] = React.useState(false); + const [previewEnabled, setPreviewEnabled] = React.useState(true); return (
setPreviewEnabled(!previewEnabled)} /> {previewEnabled && (
@@ -48,7 +48,12 @@ export const FilterAssignees = observer(() => { issueFilterStore?.projectMembers.map((_member) => ( { const store: RootStore = useMobxStore(); const { issueFilters: issueFilterStore, issueView: issueStore } = store; - const [previewEnabled, setPreviewEnabled] = React.useState(false); + const [previewEnabled, setPreviewEnabled] = React.useState(true); return (
setPreviewEnabled(!previewEnabled)} /> {previewEnabled && (
@@ -31,7 +31,12 @@ export const FilterCreatedBy = observer(() => { issueFilterStore?.projectMembers.map((_member) => ( { - const store: RootStore = useMobxStore(); - const { issueFilters: issueFilterStore, issueView: issueStore } = store; +// const store: RootStore = useMobxStore(); +// const { issueFilters: issueFilterStore, issueView: issueViewStore } = store; - return ( -
+export const FilterSelection = () => ( +
+
+ Search container +
+
{/* priority */} -
+
{/* state group */} -
+
{/* state */} -
+
{/* assignees */} -
+
{/* created_by */} -
+
{/* labels */} -
+
{/* start_date */} -
+
{/* due_date */} -
+
- ); -}); +
+); diff --git a/web/components/issue-layouts/filters/labels.tsx b/web/components/issue-layouts/filters/labels.tsx index 6ebebdd51..f7497f5d8 100644 --- a/web/components/issue-layouts/filters/labels.tsx +++ b/web/components/issue-layouts/filters/labels.tsx @@ -20,14 +20,14 @@ export const FilterLabels = observer(() => { const store: RootStore = useMobxStore(); const { issueFilters: issueFilterStore, issueView: issueStore } = store; - const [previewEnabled, setPreviewEnabled] = React.useState(false); + const [previewEnabled, setPreviewEnabled] = React.useState(true); return (
setPreviewEnabled(!previewEnabled)} /> {previewEnabled && (
@@ -35,8 +35,13 @@ export const FilterLabels = observer(() => { issueFilterStore?.projectLabels.length > 0 && issueFilterStore?.projectLabels.map((_label) => ( } title={_label.name} /> diff --git a/web/components/issue-layouts/filters/priority.tsx b/web/components/issue-layouts/filters/priority.tsx index 8baeb20fd..d2f48ab9b 100644 --- a/web/components/issue-layouts/filters/priority.tsx +++ b/web/components/issue-layouts/filters/priority.tsx @@ -1,6 +1,6 @@ import React from "react"; // lucide icons -import { AlertCircle, SignalHigh, SignalMedium, SignalLow, Ban, Check } from "lucide-react"; +import { AlertCircle, SignalHigh, SignalMedium, SignalLow, Ban } from "lucide-react"; // components import { FilterHeader } from "../helpers/filter-header"; import { FilterOption } from "../helpers/filter-option"; @@ -54,14 +54,14 @@ export const FilterPriority = observer(() => { const store: RootStore = useMobxStore(); const { issueFilters: issueFilterStore, issueView: issueStore } = store; - const [previewEnabled, setPreviewEnabled] = React.useState(false); + const [previewEnabled, setPreviewEnabled] = React.useState(true); return (
setPreviewEnabled(!previewEnabled)} /> {previewEnabled && (
@@ -70,11 +70,21 @@ export const FilterPriority = observer(() => { issueFilterStore?.issueRenderFilters?.priority.map((_priority) => ( } title={_priority.title} /> ))} +
+
View more
+
View less
+
View all
+
)}
diff --git a/web/components/issue-layouts/filters/start-date.tsx b/web/components/issue-layouts/filters/start-date.tsx index 4f731ffd9..2f62785ab 100644 --- a/web/components/issue-layouts/filters/start-date.tsx +++ b/web/components/issue-layouts/filters/start-date.tsx @@ -14,14 +14,14 @@ export const FilterStartDate = observer(() => { const store: RootStore = useMobxStore(); const { issueFilters: issueFilterStore, issueView: issueStore } = store; - const [previewEnabled, setPreviewEnabled] = React.useState(false); + const [previewEnabled, setPreviewEnabled] = React.useState(true); return (
setPreviewEnabled(!previewEnabled)} /> {previewEnabled && (
diff --git a/web/components/issue-layouts/filters/state-group.tsx b/web/components/issue-layouts/filters/state-group.tsx index 9f2066725..be739d459 100644 --- a/web/components/issue-layouts/filters/state-group.tsx +++ b/web/components/issue-layouts/filters/state-group.tsx @@ -87,14 +87,14 @@ export const FilterStateGroup = observer(() => { const store: RootStore = useMobxStore(); const { issueFilters: issueFilterStore, issueView: issueStore } = store; - const [previewEnabled, setPreviewEnabled] = React.useState(false); + const [previewEnabled, setPreviewEnabled] = React.useState(true); return (
setPreviewEnabled(!previewEnabled)} /> {previewEnabled && (
@@ -103,7 +103,12 @@ export const FilterStateGroup = observer(() => { issueFilterStore?.issueRenderFilters?.state_group.map((_stateGroup) => ( } title={_stateGroup.title} /> diff --git a/web/components/issue-layouts/filters/state.tsx b/web/components/issue-layouts/filters/state.tsx index 21f2fde0b..340080a4c 100644 --- a/web/components/issue-layouts/filters/state.tsx +++ b/web/components/issue-layouts/filters/state.tsx @@ -17,14 +17,14 @@ export const FilterState = observer(() => { const store: RootStore = useMobxStore(); const { issueFilters: issueFilterStore, issueView: issueStore } = store; - const [previewEnabled, setPreviewEnabled] = React.useState(false); + const [previewEnabled, setPreviewEnabled] = React.useState(true); return (
setPreviewEnabled(!previewEnabled)} /> {previewEnabled && (
@@ -36,7 +36,12 @@ export const FilterState = observer(() => { issueFilterStore?.projectStates[_stateGroup].map((_state: any) => ( } title={_state?.name} /> diff --git a/web/components/issue-layouts/filters/target-date.tsx b/web/components/issue-layouts/filters/target-date.tsx index 04f5cb2db..f886b70c4 100644 --- a/web/components/issue-layouts/filters/target-date.tsx +++ b/web/components/issue-layouts/filters/target-date.tsx @@ -14,14 +14,14 @@ export const FilterTargetDate = observer(() => { const store: RootStore = useMobxStore(); const { issueFilters: issueFilterStore, issueView: issueStore } = store; - const [previewEnabled, setPreviewEnabled] = React.useState(false); + const [previewEnabled, setPreviewEnabled] = React.useState(true); return (
setPreviewEnabled(!previewEnabled)} /> {previewEnabled && (
diff --git a/web/components/issue-layouts/helpers/dropdown.tsx b/web/components/issue-layouts/helpers/dropdown.tsx new file mode 100644 index 000000000..66b7537e9 --- /dev/null +++ b/web/components/issue-layouts/helpers/dropdown.tsx @@ -0,0 +1,50 @@ +import { Fragment } from "react"; +// headless ui +import { Popover, Transition } from "@headlessui/react"; +// lucide icons +import { ChevronDown, ChevronUp } from "lucide-react"; + +interface IIssueDropdown { + children: React.ReactNode; + title?: string; +} + +export const IssueDropdown = ({ children, title = "Dropdown" }: IIssueDropdown) => ( + + {({ open }) => { + if (open) { + } + return ( + <> + +
{title}
+
+ {open ? ( + + ) : ( + + )} +
+
+ + +
+ {children} +
+
+
+ + ); + }} +
+); diff --git a/web/components/issue-layouts/helpers/filter-header.tsx b/web/components/issue-layouts/helpers/filter-header.tsx index 79e76501e..3cae74001 100644 --- a/web/components/issue-layouts/helpers/filter-header.tsx +++ b/web/components/issue-layouts/helpers/filter-header.tsx @@ -5,7 +5,7 @@ import { ChevronDown, ChevronUp } from "lucide-react"; interface IFilterHeader { title: string; isPreviewEnabled: boolean; - handleIsPreviewEnabled: (isPreviewEnabled: boolean) => void; + handleIsPreviewEnabled: () => void; } export const FilterHeader = ({ @@ -13,11 +13,11 @@ export const FilterHeader = ({ isPreviewEnabled, handleIsPreviewEnabled, }: IFilterHeader) => ( -
-
{title}
+
+
{title}
handleIsPreviewEnabled(!isPreviewEnabled)} + className="flex-shrink-0 w-[20px] h-[20px] flex justify-center items-center rounded transition-all hover:bg-custom-background-80 cursor-pointer" + onClick={handleIsPreviewEnabled} > {isPreviewEnabled ? : }
diff --git a/web/components/issue-layouts/helpers/filter-option.tsx b/web/components/issue-layouts/helpers/filter-option.tsx index 6989156f5..34ed036a0 100644 --- a/web/components/issue-layouts/helpers/filter-option.tsx +++ b/web/components/issue-layouts/helpers/filter-option.tsx @@ -10,7 +10,7 @@ interface IFilterOption { } export const FilterOption = ({ isChecked, icon, title, multiple = true }: IFilterOption) => ( -
+
}
{icon} -
{title}
+
{title}
); diff --git a/web/components/issue-layouts/kanban/index.tsx b/web/components/issue-layouts/kanban/index.tsx index 51828ae99..22a79c08a 100644 --- a/web/components/issue-layouts/kanban/index.tsx +++ b/web/components/issue-layouts/kanban/index.tsx @@ -28,28 +28,6 @@ export const IssueKanBanViewRoot = observer(() => { console.log("result", result); }; - console.log("------"); - 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("<-- workspace level -->"); - console.log("workspace projects -->", issueFilterStore?.workspaceProjects); - console.log("workspace labels -->", issueFilterStore?.workspaceLabels); - - console.log("<-- project level -->"); - console.log("project states -->", issueFilterStore?.projectStates); - console.log("project labels -->", issueFilterStore?.projectLabels); - console.log("project members -->", issueFilterStore?.projectMembers); - - console.log("project display properties -->", issueFilterStore?.projectDisplayProperties); - - console.log("issue layout -->", issueFilterStore?.issueLayout); - console.log("issues -->", issueViewStore?.getIssues); - console.log("------"); - return (
{issueViewStore.loader || issueViewStore?.getIssues === null ? ( diff --git a/web/components/issue-layouts/layout-selection.tsx b/web/components/issue-layouts/layout-selection.tsx index b2bf6184c..a32595def 100644 --- a/web/components/issue-layouts/layout-selection.tsx +++ b/web/components/issue-layouts/layout-selection.tsx @@ -94,7 +94,7 @@ export const LayoutSelection = observer(() => { {layoutSelectionFilters.map((_layout) => (
{ onClick={() => handleLayoutSelection(_layout?.key)} > <_layout.icon - size={15} + size={14} strokeWidth={2} className={`${ issueFilterStore?.issueLayout == _layout?.key diff --git a/web/pages/kanban.tsx b/web/pages/kanban.tsx index db533b2c4..08c4fe667 100644 --- a/web/pages/kanban.tsx +++ b/web/pages/kanban.tsx @@ -4,7 +4,11 @@ import useSWR from "swr"; // components import { IssueKanBanViewRoot } from "components/issue-layouts/kanban"; import { LayoutSelection } from "components/issue-layouts/layout-selection"; +// issue dropdowns +import { IssueDropdown } from "components/issue-layouts/helpers/dropdown"; +// filter components import { FilterSelection } from "components/issue-layouts/filters"; +import { DisplayFiltersSelection } from "components/issue-layouts/display-filters"; // mobx store import { useMobxStore } from "lib/mobx/store-provider"; import { RootStore } from "store/root"; @@ -29,8 +33,8 @@ const KanBanViewRoot = () => { // await issueViewStore.getMyIssuesAsync(workspaceSlug, "my_issues", "spreadsheet"); // await issueViewStore.getMyIssuesAsync(workspaceSlug, "my_issues", "gantt"); // project issues under and workspace and project - await issueViewStore.getProjectIssuesAsync(workspaceSlug, projectSlug, "issues", "list"); - // await issueViewStore.getProjectIssuesAsync(workspaceSlug, projectSlug, "issues", "kanban"); + // await issueViewStore.getProjectIssuesAsync(workspaceSlug, projectSlug, "issues", "list"); + await issueViewStore.getProjectIssuesAsync(workspaceSlug, projectSlug, "issues", "kanban"); // await issueViewStore.getProjectIssuesAsync(workspaceSlug, projectSlug, "issues", "calendar"); // await issueViewStore.getProjectIssuesAsync( // workspaceSlug, @@ -165,16 +169,18 @@ const KanBanViewRoot = () => {
Filter Header
-
{/* */}
-
- -
+ + + + + + +
- - {/* */} +
diff --git a/web/store/issue-views/Issues.ts b/web/store/issue-views/Issues.ts index b839cfeec..e5cb82422 100644 --- a/web/store/issue-views/Issues.ts +++ b/web/store/issue-views/Issues.ts @@ -131,9 +131,9 @@ class IssueViewStore implements IIssueViewStore { const currentLayout: TIssueLayouts = currentProjectId ? this.rootStore.issueFilters.issueFilters?.[currentWorkspaceId] - ?.project_issue_properties?.[currentProjectId]?.renderLayout + ?.project_issue_properties?.[currentProjectId]?.issues?.display_filters?.layout : this.rootStore.issueFilters.issueFilters?.[currentWorkspaceId]?.my_issue_properties - ?.renderLayout; + ?.display_filters?.layout; if (currentView === "my_issues") return this.issues?.[currentWorkspaceId]?.my_issues?.[currentLayout]; diff --git a/web/store/issue-views/issue_data.ts b/web/store/issue-views/issue_data.ts index bfa17146e..ab369f732 100644 --- a/web/store/issue-views/issue_data.ts +++ b/web/store/issue-views/issue_data.ts @@ -12,7 +12,7 @@ export const filtersPriority: { key: string; title: string }[] = [ { key: "high", title: "High" }, { key: "medium", title: "Medium" }, { key: "low", title: "Low" }, - { key: "null", title: "None" }, + { key: "none", title: "None" }, ]; export const filterStateGroup: { key: TStateGroup; title: string }[] = [ @@ -43,7 +43,7 @@ export const displayPropertyGroupBy: { key: string; title: string }[] = [ { key: "state", title: "States" }, { key: "state_detail.group", title: "State Groups" }, { key: "priority", title: "Priority" }, - { key: "Project", title: "project" }, // required this on my issues + { key: "Project", title: "Project" }, // required this on my issues { key: "labels", title: "Labels" }, { key: "assignees", title: "Assignees" }, { key: "created_by", title: "Created By" }, @@ -67,7 +67,7 @@ export const displayProperties: { key: string; title: string }[] = [ { key: "assignee", title: "Assignee" }, { key: "start_date", title: "Start Date" }, { key: "due_date", title: "Due Date" }, - { key: "key", title: "Id" }, + { key: "key", title: "ID" }, { key: "labels", title: "Labels" }, { key: "priority", title: "Priority" }, { key: "state", title: "State" }, @@ -76,3 +76,10 @@ export const displayProperties: { key: string; title: string }[] = [ { key: "link", title: "Link" }, { key: "estimate", title: "Estimate" }, ]; + +export const extraProperties: { key: string; title: string }[] = [ + { key: "sub_issues", title: "Show sub-issues" }, // in spreadsheet its always false + { key: "show_empty_groups", title: "Show empty states" }, // filter on front-end + { key: "calendar_date_range", title: "Calendar Date Range" }, // calendar date range yyyy-mm-dd;before range yyyy-mm-dd;after + { key: "start_target_date", title: "Start target Date" }, // gantt always be true +]; diff --git a/web/store/issue-views/issue_filters.ts b/web/store/issue-views/issue_filters.ts index 5138c413a..ee37f1f48 100644 --- a/web/store/issue-views/issue_filters.ts +++ b/web/store/issue-views/issue_filters.ts @@ -16,6 +16,7 @@ import { displayPropertyOrderBy, displayPropertyIssueType, displayProperties, + extraProperties, } from "./issue_data"; export type TIssueViews = "my_issues" | "issues" | "modules" | "views" | "cycles"; @@ -70,6 +71,7 @@ export interface IIssueRenderFilters { order_by: { key: string; title: string }[]; issue_type: { key: string; title: string }[]; display_properties: { key: string; title: string }[]; + extra_properties: { key: string; title: string }[]; workspace_properties: { [key: string]: { projects: any[]; @@ -91,7 +93,6 @@ export interface IIssueFilters { filters: IIssueFilter; display_filters: IIssueDisplayFilters; display_properties: IIssueDisplayProperties; - renderLayout: TIssueLayouts; }; project_issue_properties: { [key: string]: { @@ -99,11 +100,22 @@ export interface IIssueFilters { filters: IIssueFilter; display_filters: IIssueDisplayFilters; }; - cycles: { filters: IIssueFilter; display_filters: IIssueDisplayFilters }; - modules: { filters: IIssueFilter; display_filters: IIssueDisplayFilters }; - views: { filters: IIssueFilter; display_filters: IIssueDisplayFilters }; + cycles: { + [key: string]: { + filters: IIssueFilter; + }; + }; + modules: { + [key: string]: { + filters: IIssueFilter; + }; + }; + views: { + [key: string]: { + filters: IIssueFilter; + }; + }; display_properties: IIssueDisplayProperties; - renderLayout: TIssueLayouts; }; }; }; @@ -124,6 +136,16 @@ export interface IIssueFilterStore { issueRenderFilters: IIssueRenderFilters; issueFilters: IIssueFilters; + filterRenderProperties: + | { + [key: string]: { + isPreviewEnabled: boolean; + totalElements: number; + elementsVisible: number; + }; + }[] + | null; + // actions getWorkspaceMyIssuesFilters: (workspaceId: string) => Promise; updateWorkspaceMyIssuesFilters: () => any | Promise; @@ -173,10 +195,21 @@ class IssueFilterStore implements IIssueFilterStore { order_by: displayPropertyOrderBy, issue_type: displayPropertyIssueType, display_properties: displayProperties, + extra_properties: extraProperties, workspace_properties: {}, }; issueFilters: IIssueFilters = {}; + filterRenderProperties: + | { + [key: string]: { + isPreviewEnabled: boolean; + totalElements: number; + elementsVisible: number; + }; + }[] + | null = null; + // root store rootStore; // service @@ -211,6 +244,8 @@ class IssueFilterStore implements IIssueFilterStore { projectMembers: computed, projectDisplayProperties: computed, + userFilters: computed, + // action setWorkspaceId: action, setProjectId: action, @@ -253,12 +288,11 @@ class IssueFilterStore implements IIssueFilterStore { // computed get issueLayout() { if (!this.workspaceId) return null; - if (!this.projectId) - return this.issueFilters?.[this.workspaceId]?.my_issue_properties?.renderLayout; + return this.issueFilters?.[this.workspaceId]?.my_issue_properties?.display_filters?.layout; if (this.projectId) return this.issueFilters?.[this.workspaceId]?.project_issue_properties?.[this.projectId] - ?.renderLayout; + ?.issues?.display_filters?.layout; } get workspaceProjects() { @@ -291,9 +325,68 @@ class IssueFilterStore implements IIssueFilterStore { get projectDisplayProperties() { if (!this.workspaceId || !this.projectId) return null; return this.issueFilters?.[this.workspaceId]?.project_issue_properties?.[this.projectId] - ?.display_properties; + ?.display_properties as any; } + get userFilters() { + if (!this.workspaceId) return null; + if (this.issueView === "my_issues") + return this.issueFilters?.[this.workspaceId]?.my_issue_properties; + + if (!this.projectId) return null; + let _issueFilters: { + filters: IIssueFilter | null; + display_filters: IIssueDisplayFilters; + display_properties: IIssueDisplayProperties; + } = { + filters: null, + display_filters: + this.issueFilters?.[this.workspaceId]?.project_issue_properties?.[this.projectId]?.issues + ?.display_filters, + display_properties: + this.issueFilters?.[this.workspaceId]?.project_issue_properties?.[this.projectId] + ?.display_properties, + }; + if (this.issueView === "issues") { + _issueFilters = { + ..._issueFilters, + filters: + this.issueFilters?.[this.workspaceId]?.project_issue_properties?.[this.projectId]?.issues + ?.filters, + }; + return _issueFilters; + } + if (this.issueView === "modules" && this.moduleId) { + _issueFilters = { + ..._issueFilters, + filters: + this.issueFilters?.[this.workspaceId]?.project_issue_properties?.[this.projectId] + ?.modules?.[this.moduleId]?.filters, + }; + return _issueFilters; + } + if (this.issueView === "cycles" && this.cycleId) { + _issueFilters = { + ..._issueFilters, + filters: + this.issueFilters?.[this.workspaceId]?.project_issue_properties?.[this.projectId] + ?.cycles?.[this.cycleId]?.filters, + }; + return _issueFilters; + } + if (this.issueView === "views" && this.viewId) { + _issueFilters = { + ..._issueFilters, + filters: + this.issueFilters?.[this.workspaceId]?.project_issue_properties?.[this.projectId] + ?.views?.[this.viewId]?.filters, + }; + return _issueFilters; + } + return null; + } + handleUserFilter = () => {}; + computedFilter = (filters: any, filteredParams: any) => { const computedFilters: any = {}; Object.keys(filters).map((key) => { @@ -322,53 +415,51 @@ class IssueFilterStore implements IIssueFilterStore { this.setViewId(_viewId); this.setIssueView(_issueView); - if (_workspaceId) { - if (!_projectId) - this.issueFilters = { - ...this.issueFilters, - [_workspaceId]: { - ...this.issueFilters[_workspaceId], - my_issue_properties: { - ...this.issueFilters[_workspaceId]?.my_issue_properties, - renderLayout: _issueLayout, - }, - }, - }; - else - this.issueFilters = { - ...this.issueFilters, - [_workspaceId]: { - ...this.issueFilters[_workspaceId], - project_issue_properties: { - ...this.issueFilters[_workspaceId]?.project_issue_properties, - [_projectId]: { - ...this.issueFilters[_workspaceId]?.project_issue_properties?.[_projectId], - renderLayout: _issueLayout, - }, - }, - }, - }; - } + const _layout = this.userFilters?.display_filters?.layout; let filteredRouteParams: any = { - priority: [] || undefined, - state: [] || undefined, - assignees: [] || undefined, // ['user_id', 'user_id'] - created_by: [] || undefined, // ['user_id', 'user_id'] - labels: [] || undefined, // ['label_id', 'label_id'] - start_date: [] || undefined, // ['yyyy-mm-dd:after/before', 'yyyy-mm-dd:after/before'] - target_date: [] || undefined, // [yyyy-mm-dd:after, yyyy-mm-dd:before] - type: "" || undefined, // 'active' (started, un_started) || 'backlog' || 'null' (all_the_issues) - group_by: "state", // TIssueGroupByOptions - order_by: "-created_at", // TIssueOrderByOptions - sub_issue: true, // true for all other views except spreadsheet + priority: this.userFilters?.filters?.priority || undefined, + state_group: this.userFilters?.filters?.state_group || undefined, + state: this.userFilters?.filters?.state || undefined, + assignees: this.userFilters?.filters?.assignees || undefined, + created_by: this.userFilters?.filters?.created_by || undefined, + labels: this.userFilters?.filters?.labels || undefined, + start_date: this.userFilters?.filters?.start_date || undefined, + target_date: this.userFilters?.filters?.target_date || undefined, + type: this.userFilters?.display_filters?.type || undefined, + group_by: this.userFilters?.display_filters?.group_by || "state", + order_by: this.userFilters?.display_filters?.order_by || "-created_at", + sub_issue: this.userFilters?.display_filters?.sub_issue || true, + show_empty_groups: this.userFilters?.display_filters?.show_empty_groups || true, + calendar_date_range: this.userFilters?.display_filters?.calendar_date_range || undefined, + start_target_date: this.userFilters?.display_filters?.start_target_date || true, }; - let filteredParams: any = {}; + console.log("filteredRouteParams", filteredRouteParams); - if (_issueLayout === "list") + // start date and target date we have to construct the format here + + let filteredParams: any = {}; + if (_layout === "list") filteredParams = [ "priority", + "state_group", + "state", + "assignees", + "created_by", + "labels", + "start_date", + "target_date", + "group_by", + "order_by", + "type", + "sub_issue", + "show_empty_groups", + ]; + if (_layout === "kanban") + filteredParams = [ + "priority", + "state_group", "state", "assignees", "created_by", @@ -380,7 +471,33 @@ class IssueFilterStore implements IIssueFilterStore { "order_by", "sub_issue", ]; - if (_issueLayout === "kanban") + if (_layout === "calendar") + filteredParams = [ + "priority", + "state_group", + "state", + "assignees", + "created_by", + "labels", + "start_date", + "target_date", + "type", + "calendar_date_range", + ]; + if (_layout === "spreadsheet") + filteredParams = [ + "priority", + "state_group", + "state", + "assignees", + "created_by", + "labels", + "start_date", + "target_date", + "type", + "sub_issues", + ]; + if (_layout === "gantt") filteredParams = [ "priority", "state", @@ -389,49 +506,17 @@ class IssueFilterStore implements IIssueFilterStore { "labels", "start_date", "target_date", - "type", - "group_by", "order_by", - "sub_issue", - ]; - if (_issueLayout === "calendar") - filteredParams = [ - "priority", - "state", - "assignees", - "created_by", - "labels", - "start_date", - "target_date", "type", - ]; - if (_issueLayout === "spreadsheet") - filteredParams = [ - "priority", - "state", - "assignees", - "created_by", - "labels", - "start_date", - "target_date", - "type", - ]; - if (_issueLayout === "gantt") - filteredParams = [ - "priority", - "state", - "assignees", - "created_by", - "labels", - "start_date", - "target_date", - "type", - "order_by", "sub_issue_id", + "start_target_date", ]; filteredRouteParams = this.computedFilter(filteredRouteParams, filteredParams); + // remove few attributes from the object when we are in workspace issues + console.log("filteredRouteParams", filteredRouteParams); + return filteredRouteParams; }; @@ -470,7 +555,6 @@ class IssueFilterStore implements IIssueFilterStore { return error; } }; - getWorkspaceMyIssuesLabels = async (workspaceId: string) => { try { this.loader = true; @@ -523,40 +607,48 @@ class IssueFilterStore implements IIssueFilterStore { my_issue_properties: { ...this?.issueFilters?.[workspaceId]?.my_issue_properties, filters: { - priority: undefined, - state: undefined, - state_group: undefined, - assignees: undefined, - created_by: undefined, - labels: undefined, - start_date: undefined, - target_date: undefined, - subscriber: undefined, + priority: issuesFiltersResponse?.view_props?.filters?.priority ?? null, + state: issuesFiltersResponse?.view_props?.filters?.state ?? null, + state_group: issuesFiltersResponse?.view_props?.filters?.state_group ?? null, + assignees: issuesFiltersResponse?.view_props?.filters?.assignees ?? null, + created_by: issuesFiltersResponse?.view_props?.filters?.created_by ?? null, + labels: issuesFiltersResponse?.view_props?.filters?.labels ?? null, + start_date: issuesFiltersResponse?.view_props?.filters?.start_date ?? null, + target_date: issuesFiltersResponse?.view_props?.filters?.target_date ?? null, + subscriber: issuesFiltersResponse?.view_props?.filters?.subscriber ?? null, }, display_filters: { - group_by: undefined, - order_by: undefined, - type: undefined, - sub_issue: undefined, - show_empty_groups: undefined, - layout: undefined, - calendar_date_range: undefined, - start_target_date: undefined, + group_by: issuesFiltersResponse?.view_props?.display_filters?.group_by ?? null, + order_by: issuesFiltersResponse?.view_props?.display_filters?.order_by ?? null, + type: issuesFiltersResponse?.view_props?.display_filters?.type ?? null, + sub_issue: issuesFiltersResponse?.view_props?.display_filters?.sub_issue ?? false, + show_empty_groups: + issuesFiltersResponse?.view_props?.display_filters?.show_empty_groups ?? false, + layout: issuesFiltersResponse?.view_props?.display_filters?.layout ?? "list", + calendar_date_range: + issuesFiltersResponse?.view_props?.display_filters?.calendar_date_range ?? false, + start_target_date: + issuesFiltersResponse?.view_props?.display_filters?.start_target_date ?? true, }, display_properties: { - assignee: false, - attachment_count: false, - created_on: false, - due_date: false, - estimate: false, - key: false, - labels: false, - link: false, - priority: false, - start_date: false, - state: false, - sub_issue_count: false, - updated_on: false, + assignee: issuesFiltersResponse?.view_props?.display_properties?.assignee ?? false, + attachment_count: + issuesFiltersResponse?.view_props?.display_properties?.attachment_count ?? false, + created_on: + issuesFiltersResponse?.view_props?.display_properties?.created_on ?? false, + due_date: issuesFiltersResponse?.view_props?.display_properties?.due_date ?? false, + estimate: issuesFiltersResponse?.view_props?.display_properties?.estimate ?? false, + key: issuesFiltersResponse?.view_props?.display_properties?.key ?? false, + labels: issuesFiltersResponse?.view_props?.display_properties?.labels ?? false, + link: issuesFiltersResponse?.view_props?.display_properties?.link ?? false, + priority: issuesFiltersResponse?.view_props?.display_properties?.priority ?? false, + start_date: + issuesFiltersResponse?.view_props?.display_properties?.start_date ?? false, + state: issuesFiltersResponse?.view_props?.display_properties?.state ?? false, + sub_issue_count: + issuesFiltersResponse?.view_props?.display_properties?.sub_issue_count ?? false, + updated_on: + issuesFiltersResponse?.view_props?.display_properties?.updated_on ?? false, }, }, }, @@ -652,7 +744,6 @@ class IssueFilterStore implements IIssueFilterStore { return error; } }; - getProjectLevelLabels = async (workspaceId: string, projectId: string) => { try { this.loader = true; @@ -692,7 +783,6 @@ class IssueFilterStore implements IIssueFilterStore { return error; } }; - getProjectLevelMembers = async (workspaceId: string, projectId: string) => { try { this.loader = true; @@ -755,7 +845,7 @@ class IssueFilterStore implements IIssueFilterStore { ...this?.issueFilters[workspaceId]?.project_issue_properties, [projectId]: { ...this?.issueFilters[workspaceId]?.project_issue_properties?.[projectId], - display_properties: issuesDisplayPropertiesResponse, + display_properties: issuesDisplayPropertiesResponse?.properties, }, }, }, @@ -822,25 +912,35 @@ class IssueFilterStore implements IIssueFilterStore { this.loader = true; this.error = null; - const workspaceId = "1"; + const issuesDisplayFiltersResponse = await this.projectService.projectMemberMe( + workspaceId, + projectId + ); - const issuesFiltersResponse = await this.workspaceService.workspaceMemberMe(workspaceId); + if (issuesDisplayFiltersResponse) { + const _filters = { ...issuesDisplayFiltersResponse?.view_props?.filters }; + const _displayFilters = { ...issuesDisplayFiltersResponse?.view_props?.display_filters }; - if (issuesFiltersResponse) { - // const _issuesFiltersResponse = this.issueFilters; - // const _issuesFiltersResponse: any = { - // ...this.issues, - // [workspaceId]: { - // ...this?.issues[workspaceId], - // my_issues: { - // ...this?.issues[workspaceId]?.my_issues, - // [_layout as string]: issuesResponse, - // }, - // }, - // }; + const _issuesDisplayFiltersResponse: any = { + ...this.issueFilters, + [workspaceId]: { + ...this?.issueFilters[workspaceId], + project_issue_properties: { + ...this?.issueFilters[workspaceId]?.project_issue_properties, + [projectId]: { + ...this?.issueFilters[workspaceId]?.project_issue_properties?.[projectId], + issues: { + ...this?.issueFilters[workspaceId]?.project_issue_properties?.[projectId]?.issues, + filters: _filters, + display_filters: _displayFilters, + }, + }, + }, + }, + }; runInAction(() => { - // this.issueFilters = _issuesFiltersResponse; + this.issueFilters = _issuesDisplayFiltersResponse; this.loader = false; this.error = null; }); @@ -901,28 +1001,12 @@ class IssueFilterStore implements IIssueFilterStore { await this.getProjectLevelLabels(workspaceId, projectId); await this.getProjectLevelMembers(workspaceId, projectId); await this.getProjectDisplayProperties(workspaceId, projectId); + await this.getProjectDisplayFilters(workspaceId, projectId); - const issuesFiltersResponse = await this.workspaceService.workspaceMemberMe(workspaceId); - - if (issuesFiltersResponse) { - // const _issuesFiltersResponse = this.issueFilters; - // const _issuesFiltersResponse: any = { - // ...this.issues, - // [workspaceId]: { - // ...this?.issues[workspaceId], - // my_issues: { - // ...this?.issues[workspaceId]?.my_issues, - // [_layout as string]: issuesResponse, - // }, - // }, - // }; - - runInAction(() => { - // this.issueFilters = _issuesFiltersResponse; - this.loader = false; - this.error = null; - }); - } + runInAction(() => { + this.loader = false; + this.error = null; + }); // return issuesResponse; } catch (error) { @@ -937,11 +1021,6 @@ class IssueFilterStore implements IIssueFilterStore { this.loader = true; this.error = null; - await this.getProjectLevelStates(workspaceId, projectId); - await this.getProjectLevelLabels(workspaceId, projectId); - await this.getProjectLevelMembers(workspaceId, projectId); - // await this.getProjectDisplayProperties(workspaceId, projectId); - const issuesFiltersResponse = await this.workspaceService.workspaceMemberMe(workspaceId); if (issuesFiltersResponse) {