diff --git a/apps/app/components/core/issues-view-filter.tsx b/apps/app/components/core/issues-view-filter.tsx
index f959688af..d449d6e67 100644
--- a/apps/app/components/core/issues-view-filter.tsx
+++ b/apps/app/components/core/issues-view-filter.tsx
@@ -14,7 +14,7 @@ import useIssuesView from "hooks/use-issues-view";
// headless ui
import { Popover, Transition } from "@headlessui/react";
// ui
-import { CustomMenu } from "components/ui";
+import { CustomMenu, MultiLevelDropdown } from "components/ui";
// icons
import { ChevronDownIcon, ListBulletIcon } from "@heroicons/react/24/outline";
import { Squares2X2Icon } from "@heroicons/react/20/solid";
@@ -96,59 +96,69 @@ export const IssuesFilterView: React.FC = () => {
-
- Filters
-
- }
- >
- Status
- {statesList?.map((state) => (
- {
- const filterStates = filters?.state ?? [];
- const newFilterState = filterStates.includes(state.id)
- ? filterStates.filter((id) => id !== state.id)
- : [...filterStates, state.id];
- setFilters({ ...filters, state: newFilterState });
- }}
- >
- <>{state.name}>
-
- ))}
- Members
- {members?.map((member) => (
- {}}>
- <>
- {member.member.first_name && member.member.first_name !== ""
- ? member.member.first_name + " " + member.member.last_name
- : member.member.email}
- >
-
- ))}
- Labels
- {issueLabels?.map((label) => (
- {}}>
- <>{label.name}>
-
- ))}
- Priority
- {PRIORITIES?.map((priority) => (
- {
- if (priority === null) return;
- const filterPriorities = filters?.priority ?? [];
- const newFilterPriority = filterPriorities.includes(priority)
- ? filterPriorities.filter((id) => id !== priority)
- : [...filterPriorities, priority];
- setFilters({ ...filters, priority: newFilterPriority });
- }}
- >
- {priority ?? "None"}
-
- ))}
-
+ {
+ setFilters({
+ ...filters,
+ [option.key]: [
+ ...((filters?.[option.key as keyof typeof filters] as any[]) ?? []),
+ option.value,
+ ],
+ });
+ }}
+ direction="left"
+ options={[
+ {
+ id: "priority",
+ label: "Priority",
+ value: PRIORITIES,
+ children: [
+ ...PRIORITIES.map((priority) => ({
+ id: priority ?? "none",
+ label: priority ?? "None",
+ value: {
+ key: "priority",
+ value: priority,
+ },
+ selected: filters?.priority?.includes(priority ?? "none"),
+ })),
+ ],
+ },
+ {
+ id: "state",
+ label: "State",
+ value: statesList,
+ children: [
+ ...statesList.map((state) => ({
+ id: state.id,
+ label: state.name,
+ value: {
+ key: "state",
+ value: state.id,
+ },
+ selected: filters?.state?.includes(state.id),
+ })),
+ ],
+ },
+ {
+ id: "assignee",
+ label: "Assignee",
+ value: members,
+ children: [
+ ...(members?.map((member) => ({
+ id: member.member.id,
+ label: member.member.first_name,
+ value: {
+ key: "assignee",
+ value: member.member.id,
+ },
+ selected: filters?.assignees?.includes(member.member.id),
+ })) ?? []),
+ ],
+ },
+ ]}
+ />
{({ open }) => (
<>
diff --git a/apps/app/components/core/issues-view.tsx b/apps/app/components/core/issues-view.tsx
index 3f9a64a9f..5e1100f80 100644
--- a/apps/app/components/core/issues-view.tsx
+++ b/apps/app/components/core/issues-view.tsx
@@ -458,6 +458,35 @@ export const IssuesView: React.FC = ({ type = "issue", openIssuesListModa
)
)
+ : key === "assignee"
+ ? (filters[key as keyof IIssueFilterOptions] as any)?.map(
+ (member: any) => (
+
+
+ {
+ members?.find((m) => m.member.id === member)?.member
+ .first_name
+ }
+
+ {
+ setFilters({
+ ...filters,
+ [key as keyof IIssueFilterOptions]: (
+ filters[key as keyof IIssueFilterOptions] as any
+ )?.filter((p: any) => p !== member),
+ });
+ }}
+ >
+
+
+
+ )
+ )
: (filters[key as keyof IIssueFilterOptions] as any)?.join(", ")}
)
diff --git a/apps/app/components/ui/index.ts b/apps/app/components/ui/index.ts
index da97deb65..0e881329b 100644
--- a/apps/app/components/ui/index.ts
+++ b/apps/app/components/ui/index.ts
@@ -18,4 +18,5 @@ export * from "./spinner";
export * from "./tooltip";
export * from "./labels-list";
export * from "./linear-progress-indicator";
-export * from "./empty-state";
\ No newline at end of file
+export * from "./empty-state";
+export * from "./multi-level-dropdown";
diff --git a/apps/app/components/ui/multi-level-dropdown.tsx b/apps/app/components/ui/multi-level-dropdown.tsx
new file mode 100644
index 000000000..b7e437a54
--- /dev/null
+++ b/apps/app/components/ui/multi-level-dropdown.tsx
@@ -0,0 +1,137 @@
+import { Menu, Transition } from "@headlessui/react";
+import { Fragment, useState } from "react";
+import { ChevronDownIcon, ChevronRightIcon, ChevronLeftIcon } from "@heroicons/react/20/solid";
+
+type MultiLevelDropdownProps = {
+ label: string;
+ options: {
+ id: string;
+ label: string;
+ value: any;
+ selected?: boolean;
+ children?: {
+ id: string;
+ label: string;
+ value: any;
+ selected?: boolean;
+ }[];
+ }[];
+ onSelect: (value: any) => void;
+ direction?: "left" | "right";
+};
+
+export const MultiLevelDropdown: React.FC = (props) => {
+ const { label, options, onSelect, direction = "right" } = props;
+
+ const [openChildFor, setOpenChildFor] = useState(null);
+
+ return (
+
+ );
+};