chore: filter render UI and Functionality implementation

This commit is contained in:
gurusainath 2023-09-14 22:28:42 +05:30
parent 28ce96aaca
commit 3c9e62d308
26 changed files with 1129 additions and 76 deletions

View File

@ -0,0 +1,6 @@
import React from "react";
export const IssueCalendarViewRoot = () => {
console.log();
return <div>IssueCalendarViewRoot</div>;
};

View File

@ -37,35 +37,33 @@ export const DisplayFiltersSelection = observer(() => {
?.extra_options?.[issueFilterStore?.issueLayout].access; ?.extra_options?.[issueFilterStore?.issueLayout].access;
return ( return (
<div className="w-full h-full overflow-hidden select-none relative flex flex-col"> <div className="w-full h-full overflow-hidden select-none relative flex flex-col divide-y divide-custom-border-200">
<div className="flex-shrink-0 p-2 text-sm border-b border-custom-border-200"> <div className="flex-shrink-0 p-2 text-sm">Search container</div>
Search container <div className="w-full h-full overflow-hidden overflow-y-auto relative pb-2 divide-y divide-custom-border-200">
</div>
<div className="w-full h-full overflow-hidden overflow-y-auto relative pb-2">
{/* display properties */} {/* display properties */}
{handleDisplayPropertiesSectionVisibility && ( {handleDisplayPropertiesSectionVisibility && (
<div className="pb-2 px-2 border-b border-custom-border-200"> <div className="pb-2 px-2">
<FilterDisplayProperties /> <FilterDisplayProperties />
</div> </div>
)} )}
{/* group by */} {/* group by */}
{handleDisplayFilterSectionVisibility("group_by") && ( {handleDisplayFilterSectionVisibility("group_by") && (
<div className="py-1 px-2 border-b border-custom-border-200"> <div className="py-1 px-2">
<FilterGroupBy /> <FilterGroupBy />
</div> </div>
)} )}
{/* order by */} {/* order by */}
{handleDisplayFilterSectionVisibility("order_by") && ( {handleDisplayFilterSectionVisibility("order_by") && (
<div className="py-1 px-2 border-b border-custom-border-200"> <div className="py-1 px-2">
<FilterOrderBy /> <FilterOrderBy />
</div> </div>
)} )}
{/* issue type */} {/* issue type */}
{handleDisplayFilterSectionVisibility("issue_type") && ( {handleDisplayFilterSectionVisibility("issue_type") && (
<div className="py-1 px-2 border-b border-custom-border-200"> <div className="py-1 px-2">
<FilterIssueType /> <FilterIssueType />
</div> </div>
)} )}

View File

@ -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;
}) => (
<div className="flex-shrink-0 rounded-sm overflow-hidden w-[16px] h-[16px] flex justify-center items-center">
{avatar ? (
<img src={avatar} alt={display_name || ""} className="" />
) : (
<div className="text-xs w-full h-full flex justify-center items-center capitalize font-medium bg-gray-700 text-white">
{(display_name ?? "U")[0]}
</div>
)}
</div>
);
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 && (
<div className="border border-custom-border-200 bg-custom-background-80 rounded-full overflow-hidden flex items-center gap-2 px-2 py-1">
<div className="flex-shrink-0">
<FilterPreviewHeader
title={`Assignees (${
issueFilterStore?.userFilters?.filters?.assignees?.length || 0
})`}
/>
</div>
<div className="relative flex items-center flex-wrap gap-2">
{issueFilterStore?.projectMembers &&
issueFilterStore?.projectMembers.length > 0 &&
issueFilterStore?.projectMembers.map(
(_member) =>
issueFilterStore?.userFilters?.filters?.assignees != null &&
issueFilterStore?.userFilters?.filters?.assignees.includes(
_member?.member?.id
) && (
<FilterPreviewContent
key={`assignees-${_member?.member?.id}`}
icon={
<MemberIcons
display_name={_member?.member.display_name}
avatar={_member?.member.avatar}
/>
}
title={`${_member?.member?.display_name}`}
onClick={() => handleFilter("assignees", _member?.member?.id)}
className="border border-custom-border-100 bg-custom-background-100"
/>
)
)}
<div className="flex-shrink-0">
<FilterPreviewClear onClick={clearFilter} />
</div>
</div>
</div>
)}
</>
);
});

View File

@ -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 && (
<div className="border border-custom-border-200 bg-custom-background-80 rounded-full overflow-hidden flex items-center gap-2 px-2 py-1">
<div className="flex-shrink-0">
<FilterPreviewHeader
title={`Created By (${
issueFilterStore?.userFilters?.filters?.created_by?.length || 0
})`}
/>
</div>
<div className="relative flex items-center flex-wrap gap-2">
{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
) && (
<FilterPreviewContent
key={`create-by-${_member?.member?.id}`}
title={`${_member?.member?.display_name}`}
icon={
<MemberIcons
display_name={_member?.member.display_name}
avatar={_member?.member.avatar}
/>
}
onClick={() => handleFilter("created_by", _member?.member?.id)}
className="border border-custom-border-100 bg-custom-background-100"
/>
)
)}
<div className="flex-shrink-0">
<FilterPreviewClear onClick={clearFilter} />
</div>
</div>
</div>
)}
</>
);
});

View File

@ -0,0 +1,17 @@
// lucide icons
import { X } from "lucide-react";
interface IFilterPreviewClear {
onClick?: () => void;
}
export const FilterPreviewClear = ({ onClick }: IFilterPreviewClear) => (
<div
className="cursor-pointer"
onClick={() => {
if (onClick) onClick();
}}
>
<X width={12} strokeWidth={2} />
</div>
);

View File

@ -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) => (
<div
className={`flex-shrink-0 flex items-center gap-1.5 rounded-full px-[8px] transition-all ${className}`}
style={style ? style : {}}
>
<div className="flex-shrink-0">{icon}</div>
<div className="text-xs w-full whitespace-nowrap font-medium">{title}</div>
<div className="flex-shrink-0">
<FilterPreviewClear
onClick={() => {
if (onClick) onClick();
}}
/>
</div>
</div>
);

View File

@ -0,0 +1,12 @@
interface IFilterPreviewHeader {
title: string;
}
export const FilterPreviewHeader = ({ title }: IFilterPreviewHeader) => {
console.log();
return (
<div className="flex items-center justify-between gap-2">
<div className="text-gray-500 text-xs text-custom-text-300 font-medium">{title}</div>
</div>
);
};

View File

@ -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 (
<div className="w-full h-full overflow-hidden select-none relative flex flex-col divide-y divide-custom-border-200">
<div className="flex-shrink-0 p-2 text-sm ">Search container</div>
<div className="w-full h-full overflow-hidden overflow-y-auto relative pb-2 divide-y divide-custom-border-200">
{/* priority */}
{handleFilterSectionVisibility("priority") && (
<div className="pb-1 px-2">
<FilterPriority />
</div>
)}
{/* state group */}
{handleFilterSectionVisibility("state_group") && (
<div className="py-1 px-2">
<FilterStateGroup />
</div>
)}
{/* state */}
{handleFilterSectionVisibility("state") && (
<div className="py-1 px-2">
<FilterState />
</div>
)}
{/* assignees */}
{handleFilterSectionVisibility("assignees") && (
<div className="py-1 px-2">
<FilterAssignees />
</div>
)}
{/* created_by */}
{handleFilterSectionVisibility("created_by") && (
<div className="py-1 px-2">
<FilterCreatedBy />
</div>
)}
{/* labels */}
{handleFilterSectionVisibility("labels") && (
<div className="py-1 px-2">
<FilterLabels />
</div>
)}
{/* start_date */}
{handleFilterSectionVisibility("start_date") && (
<div className="py-1 px-2">
<FilterStartDate />
</div>
)}
{/* due_date */}
{handleFilterSectionVisibility("due_date") && (
<div className="pt-1 px-2">
<FilterTargetDate />
</div>
)}
</div>
</div>
);
});

View File

@ -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 && (
<div className="w-full h-full overflow-hidden overflow-y-auto relative max-h-[500px] flex flex-wrap p-2 border-b border-custom-border-80 shadow-sm">
{/* priority */}
{handleFilterSectionVisibility("priority") && <FilterPriority />}
{/* state group */}
{handleFilterSectionVisibility("state_group") && <FilterStateGroup />}
{/* state */}
{handleFilterSectionVisibility("state") && <FilterState />}
{/* assignees */}
{handleFilterSectionVisibility("assignees") && <FilterAssignees />}
{/* created_by */}
{handleFilterSectionVisibility("created_by") && <FilterCreatedBy />}
{/* labels */}
{handleFilterSectionVisibility("labels") && <FilterLabels />}
{/* start_date */}
{handleFilterSectionVisibility("start_date") && <FilterStartDate />}
{/* due_date */}
{handleFilterSectionVisibility("due_date") && <FilterTargetDate />}
</div>
)}
</>
);
});

View File

@ -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 }) => (
<div className="flex-shrink-0 rounded-sm overflow-hidden w-[20px] h-[20px] flex justify-center items-center">
<div className={`w-[12px] h-[12px] rounded-full`} style={{ backgroundColor: color }} />
</div>
);
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 && (
<div className="border border-custom-border-200 bg-custom-background-80 rounded-full overflow-hidden flex items-center gap-2 px-2 py-1">
<div className="flex-shrink-0">
<FilterPreviewHeader
title={`Labels (${issueFilterStore?.userFilters?.filters?.labels?.length || 0})`}
/>
</div>
<div className="relative flex items-center flex-wrap gap-2">
{handleLabels &&
handleLabels.length > 0 &&
handleLabels.map(
(_label) =>
issueFilterStore?.userFilters?.filters?.labels != null &&
issueFilterStore?.userFilters?.filters?.labels.includes(_label?.id) && (
<FilterPreviewContent
key={_label?.id}
onClick={() => handleFilter("labels", _label?.id)}
icon={<LabelIcons color={_label.color} />}
title={_label.name}
style={stateStyles(_label.color)}
/>
)
)}
<div className="flex-shrink-0">
<FilterPreviewClear onClick={clearFilter} />
</div>
</div>
</div>
)}
</>
);
});

View File

@ -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 <AlertCircle size={12} strokeWidth={2} />;
if (priority === "high") return <SignalHigh size={12} strokeWidth={4} />;
if (priority === "medium") return <SignalMedium size={12} strokeWidth={4} />;
if (priority === "low") return <SignalLow size={12} strokeWidth={4} />;
return <Ban size={12} strokeWidth={2} />;
};
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 && (
<div className="border border-custom-border-200 bg-custom-background-80 rounded-full overflow-hidden flex items-center gap-2 px-2 py-1">
<div className="flex-shrink-0">
<FilterPreviewHeader
title={`Priority (${issueFilterStore?.userFilters?.filters?.priority?.length || 0})`}
/>
</div>
<div className="relative flex items-center flex-wrap gap-2">
{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) && (
<FilterPreviewContent
key={_priority?.key}
icon={<PriorityIcons priority={_priority.key} />}
title={_priority.title}
className={classNamesStyling(_priority?.key)}
onClick={() => handleFilter("priority", _priority?.key)}
/>
)
)}
<div className="flex-shrink-0">
<FilterPreviewClear onClick={clearFilter} />
</div>
</div>
</div>
)}
</>
);
});

View File

@ -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 && (
<div className="border border-custom-border-200 bg-custom-background-80 rounded-full overflow-hidden flex items-center gap-2 px-2 py-1">
<div className="flex-shrink-0">
<FilterPreviewHeader title={`Start Date`} />
</div>
<div className="relative flex items-center flex-wrap gap-2">
{issueFilterStore?.issueRenderFilters?.start_date &&
issueFilterStore?.issueRenderFilters?.start_date.length > 0 &&
issueFilterStore?.issueRenderFilters?.start_date.map((_startDate) => (
<FilterPreviewContent
key={_startDate?.key}
title={_startDate.title}
className="border border-custom-border-100 bg-custom-background-100"
onClick={() => handleFilter("start_date", _startDate?.key)}
/>
))}
</div>
<div className="flex-shrink-0">
<FilterPreviewClear onClick={clearFilter} />
</div>
</div>
)}
</>
);
});

View File

@ -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 (
<StateGroupCancelledIcon
width={"12px"}
height={"12px"}
color={color ? color : STATE_GROUP_COLORS[stateGroup]}
/>
);
if (stateGroup === "completed")
return (
<StateGroupCompletedIcon
width={"12px"}
height={"12px"}
color={color ? color : STATE_GROUP_COLORS[stateGroup]}
/>
);
if (stateGroup === "started")
return (
<StateGroupStartedIcon
width={"12px"}
height={"12px"}
color={color ? color : STATE_GROUP_COLORS[stateGroup]}
/>
);
if (stateGroup === "unstarted")
return (
<StateGroupUnstartedIcon
width={"12px"}
height={"12px"}
color={color ? color : STATE_GROUP_COLORS[stateGroup]}
/>
);
if (stateGroup === "backlog")
return (
<div className="flex-shrink-0 rounded-sm overflow-hidden w-[20px] h-[20px] flex justify-center items-center">
<StateGroupBacklogIcon
width={"12px"}
height={"12px"}
color={color ? color : STATE_GROUP_COLORS[stateGroup]}
/>
</div>
);
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 && (
<div className="border border-custom-border-200 bg-custom-background-80 rounded-full overflow-hidden flex items-center gap-2 px-2 py-1">
<div className="flex-shrink-0">
<FilterPreviewHeader
title={`State Group (${
issueFilterStore?.userFilters?.filters?.state_group?.length || 0
})`}
/>
</div>
<div className="relative flex items-center flex-wrap gap-2">
{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
) && (
<FilterPreviewContent
key={_stateGroup?.key}
icon={<StateGroupIcons stateGroup={_stateGroup.key} />}
title={_stateGroup.title}
style={stateStyles(_stateGroup?.key, null)}
onClick={() => handleFilter("state_group", _stateGroup?.key)}
/>
)
)}
<div className="flex-shrink-0">
<FilterPreviewClear onClick={clearFilter} />
</div>
</div>
</div>
)}
</>
);
});

View File

@ -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 && (
<div className="border border-custom-border-200 bg-custom-background-80 rounded-full overflow-hidden flex items-center gap-2 px-2 py-1">
<div className="flex-shrink-0">
<FilterPreviewHeader
title={`State (${issueFilterStore?.userFilters?.filters?.state?.length || 0})`}
/>
</div>
<div className="relative flex items-center flex-wrap gap-2">
{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) && (
<FilterPreviewContent
key={_state?.id}
icon={<StateGroupIcons stateGroup={_stateGroup} color={_state?.color} />}
title={_state?.name}
style={stateStyles(_state?.group, _state?.color)}
onClick={() => handleFilter("state", _state?.id)}
/>
)
)
)}
<div className="flex-shrink-0">
<FilterPreviewClear onClick={clearFilter} />
</div>
</div>
</div>
)}
</>
);
});

View File

@ -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 && (
<div className="border border-custom-border-200 bg-custom-background-80 rounded-full overflow-hidden flex items-center gap-2 px-2 py-1">
<div className="flex-shrink-0">
<FilterPreviewHeader title={`Target Date`} />
</div>
<div className="relative flex items-center flex-wrap gap-2">
{issueFilterStore?.issueRenderFilters?.due_date &&
issueFilterStore?.issueRenderFilters?.due_date.length > 0 &&
issueFilterStore?.issueRenderFilters?.due_date.map((_targetDate) => (
<FilterPreviewContent
key={_targetDate?.key}
title={_targetDate.title}
className="border border-custom-border-100 bg-custom-background-100"
onClick={() => handleFilter("target_date", _targetDate?.key)}
/>
))}
</div>
<div className="flex-shrink-0">
<FilterPreviewClear onClick={clearFilter} />
</div>
</div>
)}
</>
);
});

View File

@ -22,61 +22,60 @@ export const FilterSelection = observer(() => {
const handleFilterSectionVisibility = (section_key: string) => const handleFilterSectionVisibility = (section_key: string) =>
issueFilterStore?.issueView && issueFilterStore?.issueView &&
issueFilterStore?.issueLayout &&
issueFilterVisibilityData[ issueFilterVisibilityData[
issueFilterStore?.issueView === "my_issues" ? "my_issues" : "others" issueFilterStore?.issueView === "my_issues" ? "my_issues" : "others"
].filters.includes(section_key); ]?.filters?.[issueFilterStore?.issueLayout]?.includes(section_key);
return ( return (
<div className="w-full h-full overflow-hidden select-none relative flex flex-col"> <div className="w-full h-full overflow-hidden select-none relative flex flex-col divide-y divide-custom-border-200">
<div className="flex-shrink-0 p-2 text-sm border-b border-custom-border-200"> <div className="flex-shrink-0 p-2 text-sm ">Search container</div>
Search container <div className="w-full h-full overflow-hidden overflow-y-auto relative pb-2 divide-y divide-custom-border-200">
</div>
<div className="w-full h-full overflow-hidden overflow-y-auto relative pb-2">
{/* priority */} {/* priority */}
{handleFilterSectionVisibility("priority") && ( {handleFilterSectionVisibility("priority") && (
<div className="pb-1 px-2 border-b border-custom-border-200"> <div className="pb-1 px-2">
<FilterPriority /> <FilterPriority />
</div> </div>
)} )}
{/* state group */} {/* state group */}
{handleFilterSectionVisibility("state_group") && ( {handleFilterSectionVisibility("state_group") && (
<div className="py-1 px-2 border-b border-custom-border-200"> <div className="py-1 px-2">
<FilterStateGroup /> <FilterStateGroup />
</div> </div>
)} )}
{/* state */} {/* state */}
{handleFilterSectionVisibility("state") && ( {handleFilterSectionVisibility("state") && (
<div className="py-1 px-2 border-b border-custom-border-200"> <div className="py-1 px-2">
<FilterState /> <FilterState />
</div> </div>
)} )}
{/* assignees */} {/* assignees */}
{handleFilterSectionVisibility("assignees") && ( {handleFilterSectionVisibility("assignees") && (
<div className="py-1 px-2 border-b border-custom-border-200"> <div className="py-1 px-2">
<FilterAssignees /> <FilterAssignees />
</div> </div>
)} )}
{/* created_by */} {/* created_by */}
{handleFilterSectionVisibility("created_by") && ( {handleFilterSectionVisibility("created_by") && (
<div className="py-1 px-2 border-b border-custom-border-200"> <div className="py-1 px-2">
<FilterCreatedBy /> <FilterCreatedBy />
</div> </div>
)} )}
{/* labels */} {/* labels */}
{handleFilterSectionVisibility("labels") && ( {handleFilterSectionVisibility("labels") && (
<div className="py-1 px-2 border-b border-custom-border-200"> <div className="py-1 px-2">
<FilterLabels /> <FilterLabels />
</div> </div>
)} )}
{/* start_date */} {/* start_date */}
{handleFilterSectionVisibility("start_date") && ( {handleFilterSectionVisibility("start_date") && (
<div className="py-1 px-2 border-b border-custom-border-200"> <div className="py-1 px-2">
<FilterStartDate /> <FilterStartDate />
</div> </div>
)} )}

View File

@ -0,0 +1,6 @@
import React from "react";
export const IssueGanttViewRoot = () => {
console.log();
return <div>IssueGanttViewRoot</div>;
};

View File

@ -37,7 +37,7 @@ export const IssueDropdown = ({ children, title = "Dropdown" }: IIssueDropdown)
leaveFrom="opacity-100 translate-y-0" leaveFrom="opacity-100 translate-y-0"
leaveTo="opacity-0 translate-y-1" leaveTo="opacity-0 translate-y-1"
> >
<Popover.Panel className="absolute right-0 z-10 mt-1 w-[300px] h-[700px]"> <Popover.Panel className="absolute right-0 z-10 mt-1 w-[300px] h-[600px]">
<div className="w-full h-full overflow-hidden rounded border border-custom-border-200 bg-custom-background-100 shadow-xl"> <div className="w-full h-full overflow-hidden rounded border border-custom-border-200 bg-custom-background-100 shadow-xl">
{children} {children}
</div> </div>

View File

@ -52,22 +52,21 @@ export const LayoutSelection = observer(() => {
issueFilterStore.handleUserFilter("display_filters", "layout", _layoutKey); issueFilterStore.handleUserFilter("display_filters", "layout", _layoutKey);
}; };
console.log("----"); // console.log("----");
console.log("my_user_id", issueFilterStore.myUserId); // console.log("my_user_id", issueFilterStore.myUserId);
console.log("workspace_id", issueFilterStore.workspaceId); // console.log("workspace_id", issueFilterStore.workspaceId);
console.log("project_id", issueFilterStore.projectId); // console.log("project_id", issueFilterStore.projectId);
console.log("module_id", issueFilterStore.moduleId); // console.log("module_id", issueFilterStore.moduleId);
console.log("cycle_id", issueFilterStore.cycleId); // console.log("cycle_id", issueFilterStore.cycleId);
console.log("view_id", issueFilterStore.viewId); // console.log("view_id", issueFilterStore.viewId);
console.log("issue_view", issueFilterStore.issueView); // console.log("issue_view", issueFilterStore.issueView);
console.log("issue_layout", issueFilterStore.issueLayout); // console.log("issue_layout", issueFilterStore.issueLayout);
console.log("user_filters", issueFilterStore.userFilters); // console.log("user_filters", issueFilterStore.userFilters);
console.log("issues", issueStore.issues); // console.log("issues", issueStore.issues);
console.log("issues", issueStore.getIssues); // console.log("issues", issueStore.getIssues);
// console.log("----");
console.log("----");
return ( return (
<div className="relative flex items-center p-1 rounded gap-1 bg-custom-background-80"> <div className="relative flex items-center p-1 rounded gap-1 bg-custom-background-80">

View File

@ -0,0 +1,6 @@
import React from "react";
export const IssueListViewRoot = () => {
console.log();
return <div>IssueListViewRoot</div>;
};

View File

@ -1,17 +1,30 @@
import React from "react"; import React from "react";
// components // components
import { IssueKanBanViewRoot } from "./kanban";
import { LayoutSelection } from "./layout-selection"; import { LayoutSelection } from "./layout-selection";
import { IssueDropdown } from "./helpers/dropdown"; import { IssueDropdown } from "./helpers/dropdown";
import { FilterSelection } from "./filters"; import { FilterSelection } from "./filters";
import { DisplayFiltersSelection } from "./display-filters"; import { DisplayFiltersSelection } from "./display-filters";
export const IssuesRoot = () => { import { FilterPreview } from "./filters-preview";
console.log("issue root");
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 ( return (
<div className="w-full h-full relative flex flex-col overflow-hidden"> <div className="w-full h-full relative flex flex-col overflow-hidden">
<div className="flex-shrink-0 h-[60px] border-b border-gray-200"> <div className="flex-shrink-0 h-[60px] border-b border-custom-border-80 shadow-sm">
<div className="w-full h-full p-2 px-5 relative flex justify-between items-center gap-2"> <div className="w-full h-full p-2 px-5 relative flex justify-between items-center gap-2">
<div> <div>
<div>Filter Header</div> <div>Filter Header</div>
@ -27,10 +40,16 @@ export const IssuesRoot = () => {
</div> </div>
</div> </div>
</div> </div>
<div className="flex-shrink-0 border-b border-gray-200">Hello</div> <div className="flex-shrink-0">
<FilterPreview />
</div>
<div className="w-full h-full relative overflow-hidden"> <div className="w-full h-full relative overflow-hidden">
<IssueKanBanViewRoot /> {issueFilterStore?.issueLayout === "list" && <IssueListViewRoot />}
{issueFilterStore?.issueLayout === "kanban" && <IssueKanBanViewRoot />}
{issueFilterStore?.issueLayout === "calendar" && <IssueCalendarViewRoot />}
{issueFilterStore?.issueLayout === "spreadsheet" && <IssueSpreadsheetViewRoot />}
{issueFilterStore?.issueLayout === "gantt_chart" && <IssueGanttViewRoot />}
</div> </div>
</div> </div>
); );
}; });

View File

@ -0,0 +1,6 @@
import React from "react";
export const IssueSpreadsheetViewRoot = () => {
console.log();
return <div>IssueSpreadsheetViewRoot</div>;
};

View File

@ -1,6 +1,8 @@
import React from "react"; import React from "react";
// next imports // next imports
import { useRouter } from "next/router"; import { useRouter } from "next/router";
// swr
// import useSWR from "swr";
// components // components
import { IssuesRoot } from "components/issue-layouts/root"; import { IssuesRoot } from "components/issue-layouts/root";
// mobx store // mobx store
@ -14,6 +16,10 @@ const KanBanViewRoot = () => {
const store: RootStore = useMobxStore(); const store: RootStore = useMobxStore();
const { issueView: issueViewStore } = store; const { issueView: issueViewStore } = store;
// useSWR(`REVALIDATE_MY_ISSUES`, async () => {
// if (workspace_slug) await issueViewStore.getMyIssuesAsync(workspace_slug);
// });
React.useEffect(() => { React.useEffect(() => {
console.log("request init--->"); console.log("request init--->");
const init = async () => await issueViewStore.getMyIssuesAsync(workspace_slug); const init = async () => await issueViewStore.getMyIssuesAsync(workspace_slug);

View File

@ -48,22 +48,29 @@ export interface IIssueViewStore {
// computed // computed
getIssues: IIssues | null | undefined; getIssues: IIssues | null | undefined;
// actions // actions
getMyIssuesAsync: (workspaceId: string) => null | Promise<any>; getMyIssuesAsync: (workspaceId: string, fetchFilterToggle: boolean) => null | Promise<any>;
getProjectIssuesAsync: (workspaceId: string, projectId: string) => null | Promise<any>; getProjectIssuesAsync: (
workspaceId: string,
projectId: string,
fetchFilterToggle: boolean
) => null | Promise<any>;
getIssuesForModulesAsync: ( getIssuesForModulesAsync: (
workspaceId: string, workspaceId: string,
projectId: string, projectId: string,
moduleId: string moduleId: string,
fetchFilterToggle: boolean
) => null | Promise<any>; ) => null | Promise<any>;
getIssuesForCyclesAsync: ( getIssuesForCyclesAsync: (
workspaceId: string, workspaceId: string,
projectId: string, projectId: string,
cycleId: string cycleId: string,
fetchFilterToggle: boolean
) => null | Promise<any>; ) => null | Promise<any>;
getIssuesForViewsAsync: ( getIssuesForViewsAsync: (
workspaceId: string, workspaceId: string,
projectId: string, projectId: string,
viewId: string viewId: string,
fetchFilterToggle: boolean
) => null | Promise<any>; ) => null | Promise<any>;
} }
@ -144,12 +151,13 @@ class IssueViewStore implements IIssueViewStore {
} }
// fetching my issues // fetching my issues
getMyIssuesAsync = async (workspaceId: string) => { getMyIssuesAsync = async (workspaceId: string, fetchFilterToggle: boolean = true) => {
try { try {
this.loader = true; this.loader = true;
this.error = null; this.error = null;
await this.rootStore.issueFilters.getWorkspaceMyIssuesFilters(workspaceId); if (fetchFilterToggle)
await this.rootStore.issueFilters.getWorkspaceMyIssuesFilters(workspaceId);
const filteredParams = this.rootStore.issueFilters.getComputedFilters( const filteredParams = this.rootStore.issueFilters.getComputedFilters(
workspaceId, workspaceId,
null, null,
@ -190,12 +198,17 @@ class IssueViewStore implements IIssueViewStore {
}; };
// fetching project issues // fetching project issues
getProjectIssuesAsync = async (workspaceId: string, projectId: string) => { getProjectIssuesAsync = async (
workspaceId: string,
projectId: string,
fetchFilterToggle: boolean = true
) => {
try { try {
this.loader = true; this.loader = true;
this.error = null; 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( const filteredParams = this.rootStore.issueFilters.getComputedFilters(
workspaceId, workspaceId,
projectId, projectId,
@ -246,16 +259,22 @@ class IssueViewStore implements IIssueViewStore {
}; };
// fetching project issues for modules // 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 { try {
this.loader = true; this.loader = true;
this.error = null; this.error = null;
await this.rootStore.issueFilters.getProjectIssueModuleFilters( if (fetchFilterToggle)
workspaceId, await this.rootStore.issueFilters.getProjectIssueModuleFilters(
projectId, workspaceId,
moduleId projectId,
); moduleId
);
const filteredParams = this.rootStore.issueFilters.getComputedFilters( const filteredParams = this.rootStore.issueFilters.getComputedFilters(
workspaceId, workspaceId,
projectId, projectId,
@ -310,16 +329,22 @@ class IssueViewStore implements IIssueViewStore {
}; };
// fetching project issues for cycles // 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 { try {
this.loader = true; this.loader = true;
this.error = null; this.error = null;
await this.rootStore.issueFilters.getProjectIssueCyclesFilters( if (fetchFilterToggle)
workspaceId, await this.rootStore.issueFilters.getProjectIssueCyclesFilters(
projectId, workspaceId,
cycleId projectId,
); cycleId
);
const filteredParams = this.rootStore.issueFilters.getComputedFilters( const filteredParams = this.rootStore.issueFilters.getComputedFilters(
workspaceId, workspaceId,
projectId, projectId,
@ -374,12 +399,22 @@ class IssueViewStore implements IIssueViewStore {
}; };
// fetching project issues for views // 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 { try {
this.loader = true; this.loader = true;
this.error = null; 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( const filteredParams = this.rootStore.issueFilters.getComputedFilters(
workspaceId, workspaceId,
projectId, projectId,

View File

@ -1,3 +1,5 @@
import { renderDateFormat } from "helpers/date-time.helper";
export type TStateGroup = "backlog" | "unstarted" | "started" | "completed" | "cancelled"; export type TStateGroup = "backlog" | "unstarted" | "started" | "completed" | "cancelled";
export const issueStateGroupKeys: TStateGroup[] = [ export const issueStateGroupKeys: TStateGroup[] = [
"backlog", "backlog",
@ -87,7 +89,10 @@ export const extraProperties: { key: string; title: string }[] = [
export const issueFilterVisibilityData: any = { export const issueFilterVisibilityData: any = {
my_issues: { my_issues: {
layout: ["list", "kanban"], 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: { display_properties: {
list: true, list: true,
kanban: true, kanban: true,
@ -109,7 +114,29 @@ export const issueFilterVisibilityData: any = {
}, },
others: { others: {
layout: ["list", "kanban", "calendar", "spreadsheet", "gantt_chart"], 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: { display_properties: {
list: true, list: true,
kanban: 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`;
};

View File

@ -1,4 +1,4 @@
import { observable, action, computed, makeObservable, runInAction } from "mobx"; import { observable, action, computed, makeObservable, runInAction, autorun } from "mobx";
// types // types
import { RootStore } from "../root"; import { RootStore } from "../root";
// services // services
@ -24,6 +24,22 @@ import {
export type TIssueViews = "my_issues" | "issues" | "modules" | "views" | "cycles"; export type TIssueViews = "my_issues" | "issues" | "modules" | "views" | "cycles";
export type TIssueLayouts = "list" | "kanban" | "calendar" | "spreadsheet" | "gantt_chart"; 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 { export interface IIssueFilter {
priority: string[] | undefined; 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) => { 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 // 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") if (_layout === "list")
filteredParams = [ filteredParams = [
"priority", "priority",
@ -727,10 +772,11 @@ class IssueFilterStore implements IIssueFilterStore {
"labels", "labels",
"start_date", "start_date",
"target_date", "target_date",
"type",
"group_by", "group_by",
"order_by", "order_by",
"type",
"sub_issue", "sub_issue",
"show_empty_groups",
]; ];
if (_layout === "calendar") if (_layout === "calendar")
filteredParams = [ filteredParams = [
@ -756,7 +802,7 @@ class IssueFilterStore implements IIssueFilterStore {
"start_date", "start_date",
"target_date", "target_date",
"type", "type",
"sub_issues", "sub_issue",
]; ];
if (_layout === "gantt_chart") if (_layout === "gantt_chart")
filteredParams = [ filteredParams = [
@ -769,14 +815,12 @@ class IssueFilterStore implements IIssueFilterStore {
"target_date", "target_date",
"order_by", "order_by",
"type", "type",
"sub_issue_id", "sub_issue",
"start_target_date", "start_target_date",
]; ];
filteredRouteParams = this.computedFilter(filteredRouteParams, filteredParams); filteredRouteParams = this.computedFilter(filteredRouteParams, filteredParams);
// remove few attributes from the object when we are in workspace issues
return filteredRouteParams; return filteredRouteParams;
}; };