)}
{/* issue type */}
{handleDisplayFilterSectionVisibility("issue_type") && (
-
+
)}
diff --git a/web/components/issue-layouts/filters-preview/assignees.tsx b/web/components/issue-layouts/filters-preview/assignees.tsx
new file mode 100644
index 000000000..80bfbc084
--- /dev/null
+++ b/web/components/issue-layouts/filters-preview/assignees.tsx
@@ -0,0 +1,88 @@
+import React from "react";
+// components
+import { FilterPreviewHeader } from "./helpers/header";
+import { FilterPreviewContent } from "./helpers/content";
+import { FilterPreviewClear } from "./helpers/clear";
+// 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 MemberIcons = ({
+ display_name,
+ avatar,
+}: {
+ display_name: string;
+ avatar: string | null;
+}) => (
+
+ {avatar ? (
+
+ ) : (
+
+ {(display_name ?? "U")[0]}
+
+ )}
+
+);
+
+export const FilterAssignees = observer(() => {
+ const store: RootStore = useMobxStore();
+ const { issueFilters: issueFilterStore } = store;
+
+ const handleFilter = (key: string, value: string) => {
+ let _value =
+ issueFilterStore?.userFilters?.filters?.[key] != null &&
+ issueFilterStore?.userFilters?.filters?.[key].filter((p: string) => p != value);
+ _value = _value && _value.length > 0 ? _value : null;
+ issueFilterStore.handleUserFilter("filters", key, _value);
+ };
+
+ const clearFilter = () => {
+ issueFilterStore.handleUserFilter("filters", "assignees", null);
+ };
+
+ return (
+ <>
+ {issueFilterStore?.userFilters?.filters?.assignees != null && (
+
+
+
+
+
+ {issueFilterStore?.projectMembers &&
+ issueFilterStore?.projectMembers.length > 0 &&
+ issueFilterStore?.projectMembers.map(
+ (_member) =>
+ issueFilterStore?.userFilters?.filters?.assignees != null &&
+ issueFilterStore?.userFilters?.filters?.assignees.includes(
+ _member?.member?.id
+ ) && (
+
+ }
+ title={`${_member?.member?.display_name}`}
+ onClick={() => handleFilter("assignees", _member?.member?.id)}
+ className="border border-custom-border-100 bg-custom-background-100"
+ />
+ )
+ )}
+
+
+
+
+
+ )}
+ >
+ );
+});
diff --git a/web/components/issue-layouts/filters-preview/created-by.tsx b/web/components/issue-layouts/filters-preview/created-by.tsx
new file mode 100644
index 000000000..c69234b7c
--- /dev/null
+++ b/web/components/issue-layouts/filters-preview/created-by.tsx
@@ -0,0 +1,72 @@
+import React from "react";
+// components
+import { MemberIcons } from "./assignees";
+import { FilterPreviewHeader } from "./helpers/header";
+import { FilterPreviewContent } from "./helpers/content";
+import { FilterPreviewClear } from "./helpers/clear";
+// 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 FilterCreatedBy = observer(() => {
+ const store: RootStore = useMobxStore();
+ const { issueFilters: issueFilterStore } = store;
+
+ const handleFilter = (key: string, value: string) => {
+ let _value =
+ issueFilterStore?.userFilters?.filters?.[key] != null &&
+ issueFilterStore?.userFilters?.filters?.[key].filter((p: string) => p != value);
+ _value = _value && _value.length > 0 ? _value : null;
+ issueFilterStore.handleUserFilter("filters", key, _value);
+ };
+
+ const clearFilter = () => {
+ issueFilterStore.handleUserFilter("filters", "created_by", null);
+ };
+
+ return (
+ <>
+ {issueFilterStore?.userFilters?.filters?.created_by != null && (
+
+
+
+
+
+
+ {issueFilterStore?.projectMembers &&
+ issueFilterStore?.projectMembers.length > 0 &&
+ issueFilterStore?.projectMembers.map(
+ (_member) =>
+ issueFilterStore?.userFilters?.filters?.created_by != null &&
+ issueFilterStore?.userFilters?.filters?.created_by.includes(
+ _member?.member?.id
+ ) && (
+
+ }
+ onClick={() => handleFilter("created_by", _member?.member?.id)}
+ className="border border-custom-border-100 bg-custom-background-100"
+ />
+ )
+ )}
+
+
+
+
+
+ )}
+ >
+ );
+});
diff --git a/web/components/issue-layouts/filters-preview/helpers/clear.tsx b/web/components/issue-layouts/filters-preview/helpers/clear.tsx
new file mode 100644
index 000000000..d2cc57a37
--- /dev/null
+++ b/web/components/issue-layouts/filters-preview/helpers/clear.tsx
@@ -0,0 +1,17 @@
+// lucide icons
+import { X } from "lucide-react";
+
+interface IFilterPreviewClear {
+ onClick?: () => void;
+}
+
+export const FilterPreviewClear = ({ onClick }: IFilterPreviewClear) => (
+
{
+ if (onClick) onClick();
+ }}
+ >
+
+
+);
diff --git a/web/components/issue-layouts/filters-preview/helpers/content.tsx b/web/components/issue-layouts/filters-preview/helpers/content.tsx
new file mode 100644
index 000000000..dc56bc391
--- /dev/null
+++ b/web/components/issue-layouts/filters-preview/helpers/content.tsx
@@ -0,0 +1,32 @@
+import { FilterPreviewClear } from "./clear";
+
+interface IFilterPreviewContent {
+ icon?: React.ReactNode;
+ title?: string;
+ onClick?: () => void;
+ className?: string;
+ style?: any;
+}
+
+export const FilterPreviewContent = ({
+ icon,
+ title,
+ onClick,
+ className,
+ style,
+}: IFilterPreviewContent) => (
+
+
{icon}
+
{title}
+
+ {
+ if (onClick) onClick();
+ }}
+ />
+
+
+);
diff --git a/web/components/issue-layouts/filters-preview/helpers/header.tsx b/web/components/issue-layouts/filters-preview/helpers/header.tsx
new file mode 100644
index 000000000..5fc9c9caa
--- /dev/null
+++ b/web/components/issue-layouts/filters-preview/helpers/header.tsx
@@ -0,0 +1,12 @@
+interface IFilterPreviewHeader {
+ title: string;
+}
+
+export const FilterPreviewHeader = ({ title }: IFilterPreviewHeader) => {
+ console.log();
+ return (
+
+ );
+};
diff --git a/web/components/issue-layouts/filters-preview/index copy.tsx b/web/components/issue-layouts/filters-preview/index copy.tsx
new file mode 100644
index 000000000..d83f3f725
--- /dev/null
+++ b/web/components/issue-layouts/filters-preview/index copy.tsx
@@ -0,0 +1,92 @@
+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/issue-views/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" : "others"
+ ]?.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-preview/index.tsx b/web/components/issue-layouts/filters-preview/index.tsx
new file mode 100644
index 000000000..fd202e11b
--- /dev/null
+++ b/web/components/issue-layouts/filters-preview/index.tsx
@@ -0,0 +1,68 @@
+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/issue-views/issue_data";
+
+export const FilterPreview = 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" : "others"
+ ]?.filters?.[issueFilterStore?.issueLayout]?.includes(section_key);
+
+ const validateFiltersAvailability =
+ issueFilterStore?.userFilters?.filters != null &&
+ Object.keys(issueFilterStore?.userFilters?.filters).length > 0 &&
+ Object.keys(issueFilterStore?.userFilters?.filters)
+ .map((key) => issueFilterStore?.userFilters?.filters?.[key]?.length)
+ .filter((v) => v != undefined || v != null).length > 0;
+
+ return (
+ <>
+ {validateFiltersAvailability && (
+
+ {/* 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-preview/labels.tsx b/web/components/issue-layouts/filters-preview/labels.tsx
new file mode 100644
index 000000000..dbe825a7c
--- /dev/null
+++ b/web/components/issue-layouts/filters-preview/labels.tsx
@@ -0,0 +1,75 @@
+import React from "react";
+// components
+import { FilterPreviewHeader } from "./helpers/header";
+import { FilterPreviewContent } from "./helpers/content";
+import { FilterPreviewClear } from "./helpers/clear";
+// 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;
+
+ const stateStyles = (color: any) => ({ color: color, backgroundColor: `${color}20` });
+
+ const handleFilter = (key: string, value: string) => {
+ let _value =
+ issueFilterStore?.userFilters?.filters?.[key] != null &&
+ issueFilterStore?.userFilters?.filters?.[key].filter((p: string) => p != value);
+ _value = _value && _value.length > 0 ? _value : null;
+ issueFilterStore.handleUserFilter("filters", key, _value);
+ };
+
+ const clearFilter = () => {
+ issueFilterStore.handleUserFilter("filters", "labels", null);
+ };
+
+ const handleLabels =
+ issueFilterStore.issueView && issueFilterStore.issueView === "my_issues"
+ ? issueFilterStore?.workspaceLabels
+ : issueFilterStore?.projectLabels;
+
+ return (
+ <>
+ {issueFilterStore?.userFilters?.filters?.labels != null && (
+
+
+
+
+
+
+ {handleLabels &&
+ handleLabels.length > 0 &&
+ handleLabels.map(
+ (_label) =>
+ issueFilterStore?.userFilters?.filters?.labels != null &&
+ issueFilterStore?.userFilters?.filters?.labels.includes(_label?.id) && (
+
handleFilter("labels", _label?.id)}
+ icon={}
+ title={_label.name}
+ style={stateStyles(_label.color)}
+ />
+ )
+ )}
+
+
+
+
+
+ )}
+ >
+ );
+});
diff --git a/web/components/issue-layouts/filters-preview/priority.tsx b/web/components/issue-layouts/filters-preview/priority.tsx
new file mode 100644
index 000000000..44780d81f
--- /dev/null
+++ b/web/components/issue-layouts/filters-preview/priority.tsx
@@ -0,0 +1,79 @@
+import React from "react";
+// lucide icons
+import { AlertCircle, SignalHigh, SignalMedium, SignalLow, Ban } from "lucide-react";
+// components
+import { FilterPreviewHeader } from "./helpers/header";
+import { FilterPreviewContent } from "./helpers/content";
+import { FilterPreviewClear } from "./helpers/clear";
+// mobx react lite
+import { observer } from "mobx-react-lite";
+// mobx store
+import { useMobxStore } from "lib/mobx/store-provider";
+import { RootStore } from "store/root";
+
+const PriorityIcons = ({ priority }: { priority: string }) => {
+ if (priority === "urgent") return
;
+ if (priority === "high") return
;
+ if (priority === "medium") return
;
+ if (priority === "low") return
;
+ return
;
+};
+
+const classNamesStyling = (priority: string) => {
+ if (priority == "urgent") return "bg-red-500/20 text-red-500";
+ if (priority == "high") return "bg-orange-500/20 text-orange-500 !-pt-[30px]";
+ if (priority == "medium") return "bg-orange-500/20 text-orange-500 -pt-2";
+ if (priority == "low") return "bg-green-500/20 text-green-500 -pt-2";
+ return "bg-gray-500/10 text-gray-500";
+};
+
+export const FilterPriority = observer(() => {
+ const store: RootStore = useMobxStore();
+ const { issueFilters: issueFilterStore } = store;
+
+ const handleFilter = (key: string, value: string) => {
+ let _value =
+ issueFilterStore?.userFilters?.filters?.[key] != null &&
+ issueFilterStore?.userFilters?.filters?.[key].filter((p: string) => p != value);
+ _value = _value && _value.length > 0 ? _value : null;
+ issueFilterStore.handleUserFilter("filters", key, _value);
+ };
+
+ const clearFilter = () => {
+ issueFilterStore.handleUserFilter("filters", "priority", null);
+ };
+
+ return (
+ <>
+ {issueFilterStore?.userFilters?.filters?.priority != null && (
+
+
+
+
+
+ {issueFilterStore?.issueRenderFilters?.priority &&
+ issueFilterStore?.issueRenderFilters?.priority.length > 0 &&
+ issueFilterStore?.issueRenderFilters?.priority.map(
+ (_priority) =>
+ issueFilterStore?.userFilters?.filters?.priority != null &&
+ issueFilterStore?.userFilters?.filters?.priority.includes(_priority?.key) && (
+
}
+ title={_priority.title}
+ className={classNamesStyling(_priority?.key)}
+ onClick={() => handleFilter("priority", _priority?.key)}
+ />
+ )
+ )}
+
+
+
+
+
+ )}
+ >
+ );
+});
diff --git a/web/components/issue-layouts/filters-preview/start-date.tsx b/web/components/issue-layouts/filters-preview/start-date.tsx
new file mode 100644
index 000000000..796791762
--- /dev/null
+++ b/web/components/issue-layouts/filters-preview/start-date.tsx
@@ -0,0 +1,56 @@
+import React from "react";
+// components
+import { FilterPreviewHeader } from "./helpers/header";
+import { FilterPreviewContent } from "./helpers/content";
+import { FilterPreviewClear } from "./helpers/clear";
+// 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 FilterStartDate = observer(() => {
+ const store: RootStore = useMobxStore();
+ const { issueFilters: issueFilterStore } = store;
+
+ const handleFilter = (key: string, value: string) => {
+ let _value =
+ issueFilterStore?.userFilters?.filters?.[key] != null &&
+ issueFilterStore?.userFilters?.filters?.[key].filter((p: string) => p != value);
+ _value = _value && _value.length > 0 ? _value : null;
+
+ issueFilterStore.handleUserFilter("filters", key, _value);
+ };
+
+ const clearFilter = () => {
+ issueFilterStore.handleUserFilter("filters", "start_date", null);
+ };
+
+ return (
+ <>
+ {issueFilterStore?.userFilters?.filters?.start_date != null && (
+
+
+
+
+
+
+ {issueFilterStore?.issueRenderFilters?.start_date &&
+ issueFilterStore?.issueRenderFilters?.start_date.length > 0 &&
+ issueFilterStore?.issueRenderFilters?.start_date.map((_startDate) => (
+ handleFilter("start_date", _startDate?.key)}
+ />
+ ))}
+
+
+
+
+
+ )}
+ >
+ );
+});
diff --git a/web/components/issue-layouts/filters-preview/state-group.tsx b/web/components/issue-layouts/filters-preview/state-group.tsx
new file mode 100644
index 000000000..e461f2eb0
--- /dev/null
+++ b/web/components/issue-layouts/filters-preview/state-group.tsx
@@ -0,0 +1,159 @@
+import React from "react";
+import {
+ StateGroupBacklogIcon,
+ StateGroupCancelledIcon,
+ StateGroupCompletedIcon,
+ StateGroupStartedIcon,
+ StateGroupUnstartedIcon,
+} from "components/icons";
+// components
+import { FilterPreviewHeader } from "./helpers/header";
+import { FilterPreviewContent } from "./helpers/content";
+import { FilterPreviewClear } from "./helpers/clear";
+// 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";
+
+export const StateGroupIcons = ({
+ stateGroup,
+ color = null,
+}: {
+ stateGroup: string;
+ color?: string | null;
+}) => {
+ if (stateGroup === "cancelled")
+ return (
+
+ );
+ if (stateGroup === "completed")
+ return (
+
+ );
+ if (stateGroup === "started")
+ return (
+
+ );
+ if (stateGroup === "unstarted")
+ return (
+
+ );
+ if (stateGroup === "backlog")
+ return (
+
+
+
+ );
+ return <>>;
+};
+
+export const stateStyles = (stateGroup: string, color: any) => {
+ if (stateGroup === "cancelled") {
+ return {
+ color: color ? color : STATE_GROUP_COLORS[stateGroup],
+ backgroundColor: `${color ? color : STATE_GROUP_COLORS[stateGroup]}20`,
+ };
+ }
+ if (stateGroup === "completed") {
+ return {
+ color: color ? color : STATE_GROUP_COLORS[stateGroup],
+ backgroundColor: `${color ? color : STATE_GROUP_COLORS[stateGroup]}20`,
+ };
+ }
+ if (stateGroup === "started") {
+ return {
+ color: color ? color : STATE_GROUP_COLORS[stateGroup],
+ backgroundColor: `${color ? color : STATE_GROUP_COLORS[stateGroup]}20`,
+ };
+ }
+ if (stateGroup === "unstarted") {
+ return {
+ color: color ? color : STATE_GROUP_COLORS[stateGroup],
+ backgroundColor: `${color ? color : STATE_GROUP_COLORS[stateGroup]}20`,
+ };
+ }
+ if (stateGroup === "backlog") {
+ return {
+ color: color ? color : STATE_GROUP_COLORS[stateGroup],
+ backgroundColor: `${color ? color : STATE_GROUP_COLORS[stateGroup]}20`,
+ };
+ }
+};
+
+export const FilterStateGroup = observer(() => {
+ const store: RootStore = useMobxStore();
+ const { issueFilters: issueFilterStore } = store;
+
+ const handleFilter = (key: string, value: string) => {
+ let _value =
+ issueFilterStore?.userFilters?.filters?.[key] != null &&
+ issueFilterStore?.userFilters?.filters?.[key].filter((p: string) => p != value);
+ _value = _value && _value.length > 0 ? _value : null;
+ issueFilterStore.handleUserFilter("filters", key, _value);
+ };
+
+ const clearFilter = () => {
+ issueFilterStore.handleUserFilter("filters", "state_group", null);
+ };
+
+ return (
+ <>
+ {issueFilterStore?.userFilters?.filters?.state_group != null && (
+
+
+
+
+
+ {issueFilterStore?.issueRenderFilters?.state_group &&
+ issueFilterStore?.issueRenderFilters?.state_group.length > 0 &&
+ issueFilterStore?.issueRenderFilters?.state_group.map(
+ (_stateGroup) =>
+ issueFilterStore?.userFilters?.filters?.state_group != null &&
+ issueFilterStore?.userFilters?.filters?.state_group.includes(
+ _stateGroup?.key
+ ) && (
+
}
+ title={_stateGroup.title}
+ style={stateStyles(_stateGroup?.key, null)}
+ onClick={() => handleFilter("state_group", _stateGroup?.key)}
+ />
+ )
+ )}
+
+
+
+
+
+ )}
+ >
+ );
+});
diff --git a/web/components/issue-layouts/filters-preview/state.tsx b/web/components/issue-layouts/filters-preview/state.tsx
new file mode 100644
index 000000000..3e4088974
--- /dev/null
+++ b/web/components/issue-layouts/filters-preview/state.tsx
@@ -0,0 +1,68 @@
+import React from "react";
+// components
+import { StateGroupIcons, stateStyles } from "./state-group";
+import { FilterPreviewHeader } from "./helpers/header";
+import { FilterPreviewContent } from "./helpers/content";
+import { FilterPreviewClear } from "./helpers/clear";
+// 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 { issueStateGroupKeys } from "store/issue-views/issue_data";
+
+export const FilterState = observer(() => {
+ const store: RootStore = useMobxStore();
+ const { issueFilters: issueFilterStore } = store;
+
+ const handleFilter = (key: string, value: string) => {
+ let _value =
+ issueFilterStore?.userFilters?.filters?.[key] != null &&
+ issueFilterStore?.userFilters?.filters?.[key].filter((p: string) => p != value);
+ _value = _value && _value.length > 0 ? _value : null;
+ issueFilterStore.handleUserFilter("filters", key, _value);
+ };
+
+ const clearFilter = () => {
+ issueFilterStore.handleUserFilter("filters", "state", null);
+ };
+
+ return (
+ <>
+ {issueFilterStore?.userFilters?.filters?.state != null && (
+
+
+
+
+
+ {issueStateGroupKeys.map(
+ (_stateGroup) =>
+ issueFilterStore?.projectStates &&
+ issueFilterStore?.projectStates[_stateGroup] &&
+ issueFilterStore?.projectStates[_stateGroup].length > 0 &&
+ issueFilterStore?.projectStates[_stateGroup].map(
+ (_state: any) =>
+ issueFilterStore?.userFilters?.filters?.state != null &&
+ issueFilterStore?.userFilters?.filters?.state.includes(_state?.id) && (
+
}
+ title={_state?.name}
+ style={stateStyles(_state?.group, _state?.color)}
+ onClick={() => handleFilter("state", _state?.id)}
+ />
+ )
+ )
+ )}
+
+
+
+
+
+ )}
+ >
+ );
+});
diff --git a/web/components/issue-layouts/filters-preview/target-date.tsx b/web/components/issue-layouts/filters-preview/target-date.tsx
new file mode 100644
index 000000000..866f550b5
--- /dev/null
+++ b/web/components/issue-layouts/filters-preview/target-date.tsx
@@ -0,0 +1,56 @@
+import React from "react";
+// components
+import { FilterPreviewHeader } from "./helpers/header";
+import { FilterPreviewContent } from "./helpers/content";
+import { FilterPreviewClear } from "./helpers/clear";
+// 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 FilterTargetDate = observer(() => {
+ const store: RootStore = useMobxStore();
+ const { issueFilters: issueFilterStore } = store;
+
+ const handleFilter = (key: string, value: string) => {
+ let _value =
+ issueFilterStore?.userFilters?.filters?.[key] != null &&
+ issueFilterStore?.userFilters?.filters?.[key].filter((p: string) => p != value);
+ _value = _value && _value.length > 0 ? _value : null;
+
+ issueFilterStore.handleUserFilter("filters", key, _value);
+ };
+
+ const clearFilter = () => {
+ issueFilterStore.handleUserFilter("filters", "target_date", null);
+ };
+
+ return (
+ <>
+ {issueFilterStore?.userFilters?.filters?.target_date != null && (
+
+
+
+
+
+
+ {issueFilterStore?.issueRenderFilters?.due_date &&
+ issueFilterStore?.issueRenderFilters?.due_date.length > 0 &&
+ issueFilterStore?.issueRenderFilters?.due_date.map((_targetDate) => (
+ handleFilter("target_date", _targetDate?.key)}
+ />
+ ))}
+
+
+
+
+
+ )}
+ >
+ );
+});
diff --git a/web/components/issue-layouts/filters/index.tsx b/web/components/issue-layouts/filters/index.tsx
index 2ad446eb3..d83f3f725 100644
--- a/web/components/issue-layouts/filters/index.tsx
+++ b/web/components/issue-layouts/filters/index.tsx
@@ -22,61 +22,60 @@ export const FilterSelection = observer(() => {
const handleFilterSectionVisibility = (section_key: string) =>
issueFilterStore?.issueView &&
+ issueFilterStore?.issueLayout &&
issueFilterVisibilityData[
issueFilterStore?.issueView === "my_issues" ? "my_issues" : "others"
- ].filters.includes(section_key);
+ ]?.filters?.[issueFilterStore?.issueLayout]?.includes(section_key);
return (
-
-
- Search container
-
-
+
+
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") && (
-
+
)}
diff --git a/web/components/issue-layouts/gantt/index.tsx b/web/components/issue-layouts/gantt/index.tsx
new file mode 100644
index 000000000..b00e20632
--- /dev/null
+++ b/web/components/issue-layouts/gantt/index.tsx
@@ -0,0 +1,6 @@
+import React from "react";
+
+export const IssueGanttViewRoot = () => {
+ console.log();
+ return
IssueGanttViewRoot
;
+};
diff --git a/web/components/issue-layouts/helpers/dropdown.tsx b/web/components/issue-layouts/helpers/dropdown.tsx
index 66b7537e9..988f1050e 100644
--- a/web/components/issue-layouts/helpers/dropdown.tsx
+++ b/web/components/issue-layouts/helpers/dropdown.tsx
@@ -37,7 +37,7 @@ export const IssueDropdown = ({ children, title = "Dropdown" }: IIssueDropdown)
leaveFrom="opacity-100 translate-y-0"
leaveTo="opacity-0 translate-y-1"
>
-
+
{children}
diff --git a/web/components/issue-layouts/layout-selection.tsx b/web/components/issue-layouts/layout-selection.tsx
index f5f3d77fd..87960824c 100644
--- a/web/components/issue-layouts/layout-selection.tsx
+++ b/web/components/issue-layouts/layout-selection.tsx
@@ -52,22 +52,21 @@ export const LayoutSelection = observer(() => {
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("----");
+ // 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("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("----");
+ // console.log("user_filters", issueFilterStore.userFilters);
+ // console.log("issues", issueStore.issues);
+ // console.log("issues", issueStore.getIssues);
+ // console.log("----");
return (
diff --git a/web/components/issue-layouts/list/index.tsx b/web/components/issue-layouts/list/index.tsx
new file mode 100644
index 000000000..826f1b884
--- /dev/null
+++ b/web/components/issue-layouts/list/index.tsx
@@ -0,0 +1,6 @@
+import React from "react";
+
+export const IssueListViewRoot = () => {
+ console.log();
+ return
IssueListViewRoot
;
+};
diff --git a/web/components/issue-layouts/root.tsx b/web/components/issue-layouts/root.tsx
index 660f398f2..897c47121 100644
--- a/web/components/issue-layouts/root.tsx
+++ b/web/components/issue-layouts/root.tsx
@@ -1,17 +1,30 @@
import React from "react";
// components
-import { IssueKanBanViewRoot } from "./kanban";
import { LayoutSelection } from "./layout-selection";
import { IssueDropdown } from "./helpers/dropdown";
import { FilterSelection } from "./filters";
import { DisplayFiltersSelection } from "./display-filters";
-export const IssuesRoot = () => {
- console.log("issue root");
+import { FilterPreview } from "./filters-preview";
+
+import { IssueListViewRoot } from "./list";
+import { IssueKanBanViewRoot } from "./kanban";
+import { IssueCalendarViewRoot } from "./calendar";
+import { IssueSpreadsheetViewRoot } from "./spreadsheet";
+import { IssueGanttViewRoot } from "./gantt";
+// mobx
+import { observer } from "mobx-react-lite";
+// mobx store
+import { useMobxStore } from "lib/mobx/store-provider";
+import { RootStore } from "store/root";
+
+export const IssuesRoot = observer(() => {
+ const store: RootStore = useMobxStore();
+ const { issueFilters: issueFilterStore } = store;
return (
-
+
Filter Header
@@ -27,10 +40,16 @@ export const IssuesRoot = () => {
-
Hello
+
+
+
-
+ {issueFilterStore?.issueLayout === "list" && }
+ {issueFilterStore?.issueLayout === "kanban" && }
+ {issueFilterStore?.issueLayout === "calendar" && }
+ {issueFilterStore?.issueLayout === "spreadsheet" && }
+ {issueFilterStore?.issueLayout === "gantt_chart" && }
);
-};
+});
diff --git a/web/components/issue-layouts/spreadsheet/index.tsx b/web/components/issue-layouts/spreadsheet/index.tsx
new file mode 100644
index 000000000..02313458d
--- /dev/null
+++ b/web/components/issue-layouts/spreadsheet/index.tsx
@@ -0,0 +1,6 @@
+import React from "react";
+
+export const IssueSpreadsheetViewRoot = () => {
+ console.log();
+ return
IssueSpreadsheetViewRoot
;
+};
diff --git a/web/pages/m-store/[workspace_slug]/my-issues.tsx b/web/pages/m-store/[workspace_slug]/my-issues.tsx
index 766381fd2..a5b244446 100644
--- a/web/pages/m-store/[workspace_slug]/my-issues.tsx
+++ b/web/pages/m-store/[workspace_slug]/my-issues.tsx
@@ -1,6 +1,8 @@
import React from "react";
// next imports
import { useRouter } from "next/router";
+// swr
+// import useSWR from "swr";
// components
import { IssuesRoot } from "components/issue-layouts/root";
// mobx store
@@ -14,6 +16,10 @@ const KanBanViewRoot = () => {
const store: RootStore = useMobxStore();
const { issueView: issueViewStore } = store;
+ // useSWR(`REVALIDATE_MY_ISSUES`, async () => {
+ // if (workspace_slug) await issueViewStore.getMyIssuesAsync(workspace_slug);
+ // });
+
React.useEffect(() => {
console.log("request init--->");
const init = async () => await issueViewStore.getMyIssuesAsync(workspace_slug);
diff --git a/web/store/issue-views/Issues.ts b/web/store/issue-views/Issues.ts
index f3b021f00..1eb29188d 100644
--- a/web/store/issue-views/Issues.ts
+++ b/web/store/issue-views/Issues.ts
@@ -48,22 +48,29 @@ export interface IIssueViewStore {
// computed
getIssues: IIssues | null | undefined;
// actions
- getMyIssuesAsync: (workspaceId: string) => null | Promise
;
- getProjectIssuesAsync: (workspaceId: string, projectId: string) => null | Promise;
+ getMyIssuesAsync: (workspaceId: string, fetchFilterToggle: boolean) => null | Promise;
+ getProjectIssuesAsync: (
+ workspaceId: string,
+ projectId: string,
+ fetchFilterToggle: boolean
+ ) => null | Promise;
getIssuesForModulesAsync: (
workspaceId: string,
projectId: string,
- moduleId: string
+ moduleId: string,
+ fetchFilterToggle: boolean
) => null | Promise;
getIssuesForCyclesAsync: (
workspaceId: string,
projectId: string,
- cycleId: string
+ cycleId: string,
+ fetchFilterToggle: boolean
) => null | Promise;
getIssuesForViewsAsync: (
workspaceId: string,
projectId: string,
- viewId: string
+ viewId: string,
+ fetchFilterToggle: boolean
) => null | Promise;
}
@@ -144,12 +151,13 @@ class IssueViewStore implements IIssueViewStore {
}
// fetching my issues
- getMyIssuesAsync = async (workspaceId: string) => {
+ getMyIssuesAsync = async (workspaceId: string, fetchFilterToggle: boolean = true) => {
try {
this.loader = true;
this.error = null;
- await this.rootStore.issueFilters.getWorkspaceMyIssuesFilters(workspaceId);
+ if (fetchFilterToggle)
+ await this.rootStore.issueFilters.getWorkspaceMyIssuesFilters(workspaceId);
const filteredParams = this.rootStore.issueFilters.getComputedFilters(
workspaceId,
null,
@@ -190,12 +198,17 @@ class IssueViewStore implements IIssueViewStore {
};
// fetching project issues
- getProjectIssuesAsync = async (workspaceId: string, projectId: string) => {
+ getProjectIssuesAsync = async (
+ workspaceId: string,
+ projectId: string,
+ fetchFilterToggle: boolean = true
+ ) => {
try {
this.loader = true;
this.error = null;
- await this.rootStore.issueFilters.getProjectIssueFilters(workspaceId, projectId);
+ if (fetchFilterToggle)
+ await this.rootStore.issueFilters.getProjectIssueFilters(workspaceId, projectId);
const filteredParams = this.rootStore.issueFilters.getComputedFilters(
workspaceId,
projectId,
@@ -246,16 +259,22 @@ class IssueViewStore implements IIssueViewStore {
};
// fetching project issues for modules
- getIssuesForModulesAsync = async (workspaceId: string, projectId: string, moduleId: string) => {
+ getIssuesForModulesAsync = async (
+ workspaceId: string,
+ projectId: string,
+ moduleId: string,
+ fetchFilterToggle: boolean = true
+ ) => {
try {
this.loader = true;
this.error = null;
- await this.rootStore.issueFilters.getProjectIssueModuleFilters(
- workspaceId,
- projectId,
- moduleId
- );
+ if (fetchFilterToggle)
+ await this.rootStore.issueFilters.getProjectIssueModuleFilters(
+ workspaceId,
+ projectId,
+ moduleId
+ );
const filteredParams = this.rootStore.issueFilters.getComputedFilters(
workspaceId,
projectId,
@@ -310,16 +329,22 @@ class IssueViewStore implements IIssueViewStore {
};
// fetching project issues for cycles
- getIssuesForCyclesAsync = async (workspaceId: string, projectId: string, cycleId: string) => {
+ getIssuesForCyclesAsync = async (
+ workspaceId: string,
+ projectId: string,
+ cycleId: string,
+ fetchFilterToggle: boolean = true
+ ) => {
try {
this.loader = true;
this.error = null;
- await this.rootStore.issueFilters.getProjectIssueCyclesFilters(
- workspaceId,
- projectId,
- cycleId
- );
+ if (fetchFilterToggle)
+ await this.rootStore.issueFilters.getProjectIssueCyclesFilters(
+ workspaceId,
+ projectId,
+ cycleId
+ );
const filteredParams = this.rootStore.issueFilters.getComputedFilters(
workspaceId,
projectId,
@@ -374,12 +399,22 @@ class IssueViewStore implements IIssueViewStore {
};
// fetching project issues for views
- getIssuesForViewsAsync = async (workspaceId: string, projectId: string, viewId: string) => {
+ getIssuesForViewsAsync = async (
+ workspaceId: string,
+ projectId: string,
+ viewId: string,
+ fetchFilterToggle: boolean = true
+ ) => {
try {
this.loader = true;
this.error = null;
- await this.rootStore.issueFilters.getProjectIssueViewsFilters(workspaceId, projectId, viewId);
+ if (fetchFilterToggle)
+ await this.rootStore.issueFilters.getProjectIssueViewsFilters(
+ workspaceId,
+ projectId,
+ viewId
+ );
const filteredParams = this.rootStore.issueFilters.getComputedFilters(
workspaceId,
projectId,
diff --git a/web/store/issue-views/issue_data.ts b/web/store/issue-views/issue_data.ts
index f4de061e7..7c870e5b5 100644
--- a/web/store/issue-views/issue_data.ts
+++ b/web/store/issue-views/issue_data.ts
@@ -1,3 +1,5 @@
+import { renderDateFormat } from "helpers/date-time.helper";
+
export type TStateGroup = "backlog" | "unstarted" | "started" | "completed" | "cancelled";
export const issueStateGroupKeys: TStateGroup[] = [
"backlog",
@@ -87,7 +89,10 @@ export const extraProperties: { key: string; title: string }[] = [
export const issueFilterVisibilityData: any = {
my_issues: {
layout: ["list", "kanban"],
- filters: ["priority", "state_group", "labels", "start_date", "due_date"],
+ filters: {
+ list: ["priority", "state_group", "labels", "start_date", "due_date"],
+ kanban: ["priority", "state_group", "labels", "start_date", "due_date"],
+ },
display_properties: {
list: true,
kanban: true,
@@ -109,7 +114,29 @@ export const issueFilterVisibilityData: any = {
},
others: {
layout: ["list", "kanban", "calendar", "spreadsheet", "gantt_chart"],
- filters: ["priority", "state", "assignees", "created_by", "labels", "start_date", "due_date"],
+ filters: {
+ list: ["priority", "state", "assignees", "created_by", "labels", "start_date", "due_date"],
+ kanban: ["priority", "state", "assignees", "created_by", "labels", "start_date", "due_date"],
+ calendar: ["priority", "state", "assignees", "created_by", "labels"],
+ spreadsheet: [
+ "priority",
+ "state",
+ "assignees",
+ "created_by",
+ "labels",
+ "start_date",
+ "due_date",
+ ],
+ gantt_chart: [
+ "priority",
+ "state",
+ "assignees",
+ "created_by",
+ "labels",
+ "start_date",
+ "due_date",
+ ],
+ },
display_properties: {
list: true,
kanban: true,
@@ -148,3 +175,31 @@ export const issueFilterVisibilityData: any = {
},
},
};
+
+export const handleIssueParamsDateFormat = (
+ key: string,
+ start_date: any | null,
+ target_date: any | null
+) => {
+ if (key === "last_week")
+ return `${renderDateFormat(
+ new Date(new Date().getTime() - 7 * 24 * 60 * 60 * 1000)
+ )};after,${renderDateFormat(new Date())};before`;
+
+ if (key === "2_weeks_from_now")
+ return `${renderDateFormat(new Date())};after,
+ ${renderDateFormat(new Date(new Date().getTime() + 14 * 24 * 60 * 60 * 1000))};before`;
+
+ if (key === "1_month_from_now")
+ return `${renderDateFormat(new Date())};after,${renderDateFormat(
+ new Date(new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate())
+ )};before`;
+
+ if (key === "2_months_from_now")
+ return `${renderDateFormat(new Date())};after,${renderDateFormat(
+ new Date(new Date().getFullYear(), new Date().getMonth() + 2, new Date().getDate())
+ )};before`;
+
+ if (key === "custom" && start_date && target_date)
+ return `${renderDateFormat(start_date)};after,${renderDateFormat(target_date)};before`;
+};
diff --git a/web/store/issue-views/issue_filters.ts b/web/store/issue-views/issue_filters.ts
index 5dc063711..dda2f0dac 100644
--- a/web/store/issue-views/issue_filters.ts
+++ b/web/store/issue-views/issue_filters.ts
@@ -1,4 +1,4 @@
-import { observable, action, computed, makeObservable, runInAction } from "mobx";
+import { observable, action, computed, makeObservable, runInAction, autorun } from "mobx";
// types
import { RootStore } from "../root";
// services
@@ -24,6 +24,22 @@ import {
export type TIssueViews = "my_issues" | "issues" | "modules" | "views" | "cycles";
export type TIssueLayouts = "list" | "kanban" | "calendar" | "spreadsheet" | "gantt_chart";
+export type TIssueParams =
+ | "priority"
+ | "state_group"
+ | "state"
+ | "assignees"
+ | "created_by"
+ | "labels"
+ | "start_date"
+ | "target_date"
+ | "group_by"
+ | "order_by"
+ | "type"
+ | "sub_issue"
+ | "show_empty_groups"
+ | "calendar_date_range"
+ | "start_target_date";
export interface IIssueFilter {
priority: string[] | undefined;
@@ -649,6 +665,32 @@ class IssueFilterStore implements IIssueFilterStore {
);
}
}
+
+ if (this.issueView === "my_issues")
+ this.rootStore?.issueView?.getProjectIssuesAsync(this.workspaceId, this.projectId, false);
+ if (this.issueView === "issues")
+ this.rootStore?.issueView?.getProjectIssuesAsync(this.workspaceId, this.projectId, false);
+ if (this.issueView === "modules" && this.moduleId)
+ this.rootStore?.issueView?.getIssuesForModulesAsync(
+ this.workspaceId,
+ this.projectId,
+ this.moduleId,
+ false
+ );
+ if (this.issueView === "cycles" && this.cycleId)
+ this.rootStore?.issueView?.getIssuesForCyclesAsync(
+ this.workspaceId,
+ this.projectId,
+ this.cycleId,
+ false
+ );
+ if (this.issueView === "views" && this.viewId)
+ this.rootStore?.issueView?.getIssuesForViewsAsync(
+ this.workspaceId,
+ this.projectId,
+ this.viewId,
+ false
+ );
};
computedFilter = (filters: any, filteredParams: any) => {
@@ -699,8 +741,11 @@ class IssueFilterStore implements IIssueFilterStore {
};
// start date and target date we have to construct the format here
+ // in calendar view calendar_date_range send as target_date
+ // in spreadsheet sub issue is false for sure
+ // in gantt start_target_date is true for sure
- let filteredParams: any = {};
+ let filteredParams: TIssueParams[] = [];
if (_layout === "list")
filteredParams = [
"priority",
@@ -727,10 +772,11 @@ class IssueFilterStore implements IIssueFilterStore {
"labels",
"start_date",
"target_date",
- "type",
"group_by",
"order_by",
+ "type",
"sub_issue",
+ "show_empty_groups",
];
if (_layout === "calendar")
filteredParams = [
@@ -756,7 +802,7 @@ class IssueFilterStore implements IIssueFilterStore {
"start_date",
"target_date",
"type",
- "sub_issues",
+ "sub_issue",
];
if (_layout === "gantt_chart")
filteredParams = [
@@ -769,14 +815,12 @@ class IssueFilterStore implements IIssueFilterStore {
"target_date",
"order_by",
"type",
- "sub_issue_id",
+ "sub_issue",
"start_target_date",
];
filteredRouteParams = this.computedFilter(filteredRouteParams, filteredParams);
- // remove few attributes from the object when we are in workspace issues
-
return filteredRouteParams;
};