diff --git a/web/components/icons/module/cancelled.tsx b/web/components/icons/module/cancelled.tsx index 9bfc02943..6ea5fd694 100644 --- a/web/components/icons/module/cancelled.tsx +++ b/web/components/icons/module/cancelled.tsx @@ -20,7 +20,7 @@ export const ModuleCancelledIcon: React.FC = ({ fill="none" xmlns="http://www.w3.org/2000/svg" > - + = ({ width = "20", height = "20", fill="none" xmlns="http://www.w3.org/2000/svg" > - + = ({ fill="none" xmlns="http://www.w3.org/2000/svg" > - + ); diff --git a/web/components/icons/state/cancelled.tsx b/web/components/icons/state/cancelled.tsx index 1c3c4e3d2..4b06d80ba 100644 --- a/web/components/icons/state/cancelled.tsx +++ b/web/components/icons/state/cancelled.tsx @@ -19,7 +19,7 @@ export const StateGroupCancelledIcon: React.FC = ({ fill="none" xmlns="http://www.w3.org/2000/svg" > - + = ({ viewBox="0 0 12 12" fill="none" > - - + + ); diff --git a/web/components/icons/state/unstarted.tsx b/web/components/icons/state/unstarted.tsx index 61a782b1f..aa0d44935 100644 --- a/web/components/icons/state/unstarted.tsx +++ b/web/components/icons/state/unstarted.tsx @@ -19,6 +19,6 @@ export const StateGroupUnstartedIcon: React.FC = ({ fill="none" xmlns="http://www.w3.org/2000/svg" > - + ); diff --git a/web/components/issue-layouts/header/filters/assignees.tsx b/web/components/issue-layouts/header/filters/assignees.tsx index 66aa66e79..f8627c937 100644 --- a/web/components/issue-layouts/header/filters/assignees.tsx +++ b/web/components/issue-layouts/header/filters/assignees.tsx @@ -1,90 +1,65 @@ import React from "react"; // lucide icons -import { - AlertCircleIcon, - SignalHighIcon, - SignalMediumIcon, - SignalLowIcon, - BanIcon, - CheckIcon, - ChevronDown, - ChevronUp, -} from "lucide-react"; +import { Check, ChevronDown, ChevronUp } from "lucide-react"; +// components +import { FilterHeader } from "./filter-header"; +import { FilterCard } from "./filter-card"; // 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 + ) : ( +
+ {(display_name ?? "U")[0]} +
+ )} +
+); + export const FilterAssignees = observer(() => { const store: RootStore = useMobxStore(); const { issueFilters: issueFilterStore, issueView: issueStore } = store; - const [allFiltersToggle, setAllFiltersToggle] = React.useState(false); - - const PriorityIcons = ({ priority }: { priority: string }) => { - if (priority === "urgent") - return ( -
- -
- ); - if (priority === "high") - return ( -
- -
- ); - if (priority === "medium") - return ( -
- -
- ); - if (priority === "low") - return ( -
- -
- ); - return ( -
- -
- ); - }; + const [previewEnabled, setPreviewEnabled] = React.useState(false); return (
-
-
Assignees
-
setAllFiltersToggle(!allFiltersToggle)} - > - {allFiltersToggle ? : } + + {previewEnabled && ( +
+ {issueFilterStore?.projectMembers && + issueFilterStore?.projectMembers.length > 0 && + issueFilterStore?.projectMembers.map((_member) => ( + + } + title={`${_member?.member?.display_name} (${_member?.member?.first_name} ${_member?.member?.last_name})`} + /> + ))}
-
-
- {issueFilterStore?.issueRenderFilters?.priority && - issueFilterStore?.issueRenderFilters?.priority.length > 0 && - issueFilterStore?.issueRenderFilters?.priority.map((priority) => ( -
- -
- {priority.title} -
-
- -
-
- ))} -
+ )}
); }); diff --git a/web/components/issue-layouts/header/filters/created-by.tsx b/web/components/issue-layouts/header/filters/created-by.tsx index f1d28dad5..af6ea0151 100644 --- a/web/components/issue-layouts/header/filters/created-by.tsx +++ b/web/components/issue-layouts/header/filters/created-by.tsx @@ -1,15 +1,10 @@ import React from "react"; // lucide icons -import { - AlertCircleIcon, - SignalHighIcon, - SignalMediumIcon, - SignalLowIcon, - BanIcon, - CheckIcon, - ChevronDown, - ChevronUp, -} from "lucide-react"; +import { Check, ChevronDown, ChevronUp } from "lucide-react"; +// components +import { MemberIcons } from "./assignees"; +import { FilterHeader } from "./filter-header"; +import { FilterCard } from "./filter-card"; // mobx react lite import { observer } from "mobx-react-lite"; // mobx store @@ -20,71 +15,34 @@ export const FilterCreatedBy = observer(() => { const store: RootStore = useMobxStore(); const { issueFilters: issueFilterStore, issueView: issueStore } = store; - const [allFiltersToggle, setAllFiltersToggle] = React.useState(false); - - const PriorityIcons = ({ priority }: { priority: string }) => { - if (priority === "urgent") - return ( -
- -
- ); - if (priority === "high") - return ( -
- -
- ); - if (priority === "medium") - return ( -
- -
- ); - if (priority === "low") - return ( -
- -
- ); - return ( -
- -
- ); - }; + const [previewEnabled, setPreviewEnabled] = React.useState(false); return (
-
-
Created By
-
setAllFiltersToggle(!allFiltersToggle)} - > - {allFiltersToggle ? : } + + {previewEnabled && ( +
+ {issueFilterStore?.projectMembers && + issueFilterStore?.projectMembers.length > 0 && + issueFilterStore?.projectMembers.map((_member) => ( + + } + title={`${_member?.member?.display_name} (${_member?.member?.first_name} ${_member?.member?.last_name})`} + /> + ))}
-
-
- {issueFilterStore?.issueRenderFilters?.priority && - issueFilterStore?.issueRenderFilters?.priority.length > 0 && - issueFilterStore?.issueRenderFilters?.priority.map((priority) => ( -
- -
- {priority.title} -
-
- -
-
- ))} -
+ )}
); }); diff --git a/web/components/issue-layouts/header/filters/filter-card.tsx b/web/components/issue-layouts/header/filters/filter-card.tsx new file mode 100644 index 000000000..3133e65aa --- /dev/null +++ b/web/components/issue-layouts/header/filters/filter-card.tsx @@ -0,0 +1,23 @@ +import React from "react"; +// lucide icons +import { Check } from "lucide-react"; + +interface IFilterCard { + isChecked: boolean; + icon?: React.ReactNode; + title: string; +} + +export const FilterCard = ({ isChecked, icon, title }: IFilterCard) => ( +
+
+ {isChecked && } +
+ {icon} +
{title}
+
+); diff --git a/web/components/issue-layouts/header/filters/filter-header.tsx b/web/components/issue-layouts/header/filters/filter-header.tsx new file mode 100644 index 000000000..b619d57ae --- /dev/null +++ b/web/components/issue-layouts/header/filters/filter-header.tsx @@ -0,0 +1,25 @@ +import React from "react"; +// lucide icons +import { ChevronDown, ChevronUp } from "lucide-react"; + +interface IFilterHeader { + title: string; + isPreviewEnabled: boolean; + handleIsPreviewEnabled: (isPreviewEnabled: boolean) => void; +} + +export const FilterHeader = ({ + title, + isPreviewEnabled, + handleIsPreviewEnabled, +}: IFilterHeader) => ( +
+
{title}
+
handleIsPreviewEnabled(!isPreviewEnabled)} + > + {isPreviewEnabled ? : } +
+
+); diff --git a/web/components/issue-layouts/header/filters/labels.tsx b/web/components/issue-layouts/header/filters/labels.tsx index 6d8eed30a..fd23664d8 100644 --- a/web/components/issue-layouts/header/filters/labels.tsx +++ b/web/components/issue-layouts/header/filters/labels.tsx @@ -1,90 +1,48 @@ import React from "react"; // lucide icons -import { - AlertCircleIcon, - SignalHighIcon, - SignalMediumIcon, - SignalLowIcon, - BanIcon, - CheckIcon, - ChevronDown, - ChevronUp, -} from "lucide-react"; +import { Check, ChevronDown, ChevronUp } from "lucide-react"; +// components +import { FilterHeader } from "./filter-header"; +import { FilterCard } from "./filter-card"; // 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, issueView: issueStore } = store; - const [allFiltersToggle, setAllFiltersToggle] = React.useState(false); - - const PriorityIcons = ({ priority }: { priority: string }) => { - if (priority === "urgent") - return ( -
- -
- ); - if (priority === "high") - return ( -
- -
- ); - if (priority === "medium") - return ( -
- -
- ); - if (priority === "low") - return ( -
- -
- ); - return ( -
- -
- ); - }; + const [previewEnabled, setPreviewEnabled] = React.useState(false); return (
-
-
Labels
-
setAllFiltersToggle(!allFiltersToggle)} - > - {allFiltersToggle ? : } + + {previewEnabled && ( +
+ {issueFilterStore?.projectLabels && + issueFilterStore?.projectLabels.length > 0 && + issueFilterStore?.projectLabels.map((_label) => ( + } + title={_label.name} + /> + ))}
-
-
- {issueFilterStore?.issueRenderFilters?.priority && - issueFilterStore?.issueRenderFilters?.priority.length > 0 && - issueFilterStore?.issueRenderFilters?.priority.map((priority) => ( -
- -
- {priority.title} -
-
- -
-
- ))} -
+ )}
); }); diff --git a/web/components/issue-layouts/header/filters/priority.tsx b/web/components/issue-layouts/header/filters/priority.tsx index 4615fbfc4..123003809 100644 --- a/web/components/issue-layouts/header/filters/priority.tsx +++ b/web/components/issue-layouts/header/filters/priority.tsx @@ -1,49 +1,51 @@ import React from "react"; // lucide icons -import { - AlertCircle, - SignalHigh, - SignalMedium, - SignalLow, - Ban, - Check, - ChevronDown, - ChevronUp, -} from "lucide-react"; +import { AlertCircle, SignalHigh, SignalMedium, SignalLow, Ban, Check } from "lucide-react"; +// components +import { FilterHeader } from "./filter-header"; +import { FilterCard } from "./filter-card"; // 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 }) => { +const PriorityIcons = ({ + priority, + size = 14, + strokeWidth = 2, +}: { + priority: string; + size?: number; + strokeWidth?: number; +}) => { if (priority === "urgent") return (
- +
); if (priority === "high") return (
- +
); if (priority === "medium") return (
- +
); if (priority === "low") return (
- +
); return (
- +
); }; @@ -52,39 +54,29 @@ export const FilterPriority = observer(() => { const store: RootStore = useMobxStore(); const { issueFilters: issueFilterStore, issueView: issueStore } = store; - const [allFiltersToggle, setAllFiltersToggle] = React.useState(false); + const [previewEnabled, setPreviewEnabled] = React.useState(false); return (
-
-
Priority
-
setAllFiltersToggle(!allFiltersToggle)} - > - {allFiltersToggle ? : } + + {previewEnabled && ( +
+ {issueFilterStore?.issueRenderFilters?.priority && + issueFilterStore?.issueRenderFilters?.priority.length > 0 && + issueFilterStore?.issueRenderFilters?.priority.map((_priority) => ( + } + title={_priority.title} + /> + ))}
-
-
- {issueFilterStore?.issueRenderFilters?.priority && - issueFilterStore?.issueRenderFilters?.priority.length > 0 && - issueFilterStore?.issueRenderFilters?.priority.map((_priority) => ( -
- -
- {_priority.title} -
-
- {false && } -
-
- ))} -
+ )}
); }); diff --git a/web/components/issue-layouts/header/filters/start-date.tsx b/web/components/issue-layouts/header/filters/start-date.tsx index b35d5f30f..efcae3be5 100644 --- a/web/components/issue-layouts/header/filters/start-date.tsx +++ b/web/components/issue-layouts/header/filters/start-date.tsx @@ -1,15 +1,9 @@ import React from "react"; // lucide icons -import { - AlertCircleIcon, - SignalHighIcon, - SignalMediumIcon, - SignalLowIcon, - BanIcon, - CheckIcon, - ChevronDown, - ChevronUp, -} from "lucide-react"; +import { Check, ChevronDown, ChevronUp } from "lucide-react"; +// components +import { FilterHeader } from "./filter-header"; +import { FilterCard } from "./filter-card"; // mobx react lite import { observer } from "mobx-react-lite"; // mobx store @@ -20,71 +14,24 @@ export const FilterStartDate = observer(() => { const store: RootStore = useMobxStore(); const { issueFilters: issueFilterStore, issueView: issueStore } = store; - const [allFiltersToggle, setAllFiltersToggle] = React.useState(false); - - const PriorityIcons = ({ priority }: { priority: string }) => { - if (priority === "urgent") - return ( -
- -
- ); - if (priority === "high") - return ( -
- -
- ); - if (priority === "medium") - return ( -
- -
- ); - if (priority === "low") - return ( -
- -
- ); - return ( -
- -
- ); - }; + const [previewEnabled, setPreviewEnabled] = React.useState(false); return (
-
-
Start Date
-
setAllFiltersToggle(!allFiltersToggle)} - > - {allFiltersToggle ? : } + + {previewEnabled && ( +
+ {issueFilterStore?.issueRenderFilters?.start_date && + issueFilterStore?.issueRenderFilters?.start_date.length > 0 && + issueFilterStore?.issueRenderFilters?.start_date.map((_startDate) => ( + + ))}
-
-
- {issueFilterStore?.issueRenderFilters?.priority && - issueFilterStore?.issueRenderFilters?.priority.length > 0 && - issueFilterStore?.issueRenderFilters?.priority.map((priority) => ( -
- -
- {priority.title} -
-
- -
-
- ))} -
+ )}
); }); diff --git a/web/components/issue-layouts/header/filters/state-group.tsx b/web/components/issue-layouts/header/filters/state-group.tsx index 15049650a..c7211b042 100644 --- a/web/components/issue-layouts/header/filters/state-group.tsx +++ b/web/components/issue-layouts/header/filters/state-group.tsx @@ -1,90 +1,115 @@ import React from "react"; // lucide icons +import { Check, ChevronDown, ChevronUp } from "lucide-react"; import { - AlertCircleIcon, - SignalHighIcon, - SignalMediumIcon, - SignalLowIcon, - BanIcon, - CheckIcon, - ChevronDown, - ChevronUp, -} from "lucide-react"; + StateGroupBacklogIcon, + StateGroupCancelledIcon, + StateGroupCompletedIcon, + StateGroupStartedIcon, + StateGroupUnstartedIcon, +} from "components/icons"; +// components +import { FilterHeader } from "./filter-header"; +import { FilterCard } from "./filter-card"; // 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 }: { stateGroup: string }) => { +export const StateGroupIcons = ({ + stateGroup, + width = "14px", + height = "14px", + color = null, +}: { + stateGroup: string; + width?: string | undefined; + height?: string | undefined; + color?: string | null; +}) => { if (stateGroup === "cancelled") return ( -
- +
+
); if (stateGroup === "completed") return ( -
- +
+
); if (stateGroup === "started") return ( -
- +
+
); if (stateGroup === "unstarted") return ( -
- +
+
); - return ( -
- -
- ); + if (stateGroup === "backlog") + return ( +
+ +
+ ); + return <>; }; export const FilterStateGroup = observer(() => { const store: RootStore = useMobxStore(); const { issueFilters: issueFilterStore, issueView: issueStore } = store; - const [allFiltersToggle, setAllFiltersToggle] = React.useState(false); + const [previewEnabled, setPreviewEnabled] = React.useState(false); return (
-
-
State Group
-
setAllFiltersToggle(!allFiltersToggle)} - > - {allFiltersToggle ? : } + + {previewEnabled && ( +
+ {issueFilterStore?.issueRenderFilters?.state_group && + issueFilterStore?.issueRenderFilters?.state_group.length > 0 && + issueFilterStore?.issueRenderFilters?.state_group.map((_stateGroup) => ( + } + title={_stateGroup.title} + /> + ))}
-
-
- {issueFilterStore?.issueRenderFilters?.state_group && - issueFilterStore?.issueRenderFilters?.state_group.length > 0 && - issueFilterStore?.issueRenderFilters?.state_group.map((_stateGroup) => ( -
- -
- {_stateGroup.title} -
-
- -
-
- ))} -
+ )}
); }); diff --git a/web/components/issue-layouts/header/filters/state.tsx b/web/components/issue-layouts/header/filters/state.tsx index a2b29fbee..3b8bfcf12 100644 --- a/web/components/issue-layouts/header/filters/state.tsx +++ b/web/components/issue-layouts/header/filters/state.tsx @@ -1,51 +1,49 @@ import React from "react"; // lucide icons -import { CheckIcon, ChevronDown, ChevronUp } from "lucide-react"; +import { Check, ChevronDown, ChevronUp } from "lucide-react"; // components import { StateGroupIcons } from "./state-group"; +import { FilterHeader } from "./filter-header"; +import { FilterCard } from "./filter-card"; // 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, issueView: issueStore } = store; - const [allFiltersToggle, setAllFiltersToggle] = React.useState(false); + const [previewEnabled, setPreviewEnabled] = React.useState(false); return (
-
-
State
-
setAllFiltersToggle(!allFiltersToggle)} - > - {allFiltersToggle ? : } + + {previewEnabled && ( +
+ {issueStateGroupKeys.map( + (_stateGroup) => + issueFilterStore?.projectStates && + issueFilterStore?.projectStates[_stateGroup] && + issueFilterStore?.projectStates[_stateGroup].length > 0 && + issueFilterStore?.projectStates[_stateGroup].map((_state: any) => ( + } + title={_state?.name} + /> + )) + )}
-
-
- {issueFilterStore?.projectStates && - issueFilterStore?.projectStates.length > 0 && - issueFilterStore?.projectStates.map((_state) => ( -
- -
- {_state?.name} -
-
- -
-
- ))} -
+ )}
); }); diff --git a/web/components/issue-layouts/header/filters/target-date.tsx b/web/components/issue-layouts/header/filters/target-date.tsx index 8d5af198d..28320b443 100644 --- a/web/components/issue-layouts/header/filters/target-date.tsx +++ b/web/components/issue-layouts/header/filters/target-date.tsx @@ -1,15 +1,9 @@ import React from "react"; // lucide icons -import { - AlertCircleIcon, - SignalHighIcon, - SignalMediumIcon, - SignalLowIcon, - BanIcon, - CheckIcon, - ChevronDown, - ChevronUp, -} from "lucide-react"; +import { Check, ChevronDown, ChevronUp } from "lucide-react"; +// components +import { FilterHeader } from "./filter-header"; +import { FilterCard } from "./filter-card"; // mobx react lite import { observer } from "mobx-react-lite"; // mobx store @@ -20,71 +14,24 @@ export const FilterTargetDate = observer(() => { const store: RootStore = useMobxStore(); const { issueFilters: issueFilterStore, issueView: issueStore } = store; - const [allFiltersToggle, setAllFiltersToggle] = React.useState(false); - - const PriorityIcons = ({ priority }: { priority: string }) => { - if (priority === "urgent") - return ( -
- -
- ); - if (priority === "high") - return ( -
- -
- ); - if (priority === "medium") - return ( -
- -
- ); - if (priority === "low") - return ( -
- -
- ); - return ( -
- -
- ); - }; + const [previewEnabled, setPreviewEnabled] = React.useState(false); return (
-
-
Target Date
-
setAllFiltersToggle(!allFiltersToggle)} - > - {allFiltersToggle ? : } + + {previewEnabled && ( +
+ {issueFilterStore?.issueRenderFilters?.due_date && + issueFilterStore?.issueRenderFilters?.due_date.length > 0 && + issueFilterStore?.issueRenderFilters?.due_date.map((_targetDate) => ( + + ))}
-
-
- {issueFilterStore?.issueRenderFilters?.priority && - issueFilterStore?.issueRenderFilters?.priority.length > 0 && - issueFilterStore?.issueRenderFilters?.priority.map((priority) => ( -
- -
- {priority.title} -
-
- -
-
- ))} -
+ )}
); }); diff --git a/web/public/empty-state/state_graph.svg b/web/public/empty-state/state_graph.svg index 07337991e..651ea3474 100644 --- a/web/public/empty-state/state_graph.svg +++ b/web/public/empty-state/state_graph.svg @@ -2,25 +2,25 @@ - + - + - + - + - + - + diff --git a/web/public/services/json.svg b/web/public/services/json.svg index 4c2df2222..0fe32e276 100644 --- a/web/public/services/json.svg +++ b/web/public/services/json.svg @@ -2,7 +2,7 @@ - + diff --git a/web/store/issue-views/issue_data.ts b/web/store/issue-views/issue_data.ts index d5efa6e7e..bfa17146e 100644 --- a/web/store/issue-views/issue_data.ts +++ b/web/store/issue-views/issue_data.ts @@ -1,3 +1,12 @@ +export type TStateGroup = "backlog" | "unstarted" | "started" | "completed" | "cancelled"; +export const issueStateGroupKeys: TStateGroup[] = [ + "backlog", + "unstarted", + "started", + "completed", + "cancelled", +]; + export const filtersPriority: { key: string; title: string }[] = [ { key: "urgent", title: "Urgent" }, { key: "high", title: "High" }, @@ -6,7 +15,7 @@ export const filtersPriority: { key: string; title: string }[] = [ { key: "null", title: "None" }, ]; -export const filterStateGroup: { key: string; title: string }[] = [ +export const filterStateGroup: { key: TStateGroup; title: string }[] = [ { key: "backlog", title: "Backlog" }, { key: "unstarted", title: "Unstarted" }, { key: "started", title: "Started" }, diff --git a/web/store/issue-views/issue_filters.ts b/web/store/issue-views/issue_filters.ts index 102f15193..5138c413a 100644 --- a/web/store/issue-views/issue_filters.ts +++ b/web/store/issue-views/issue_filters.ts @@ -19,9 +19,7 @@ import { } from "./issue_data"; export type TIssueViews = "my_issues" | "issues" | "modules" | "views" | "cycles"; - export type TIssueLayouts = "list" | "kanban" | "calendar" | "spreadsheet" | "gantt"; - export interface IIssueFilter { priority: string[] | undefined; state: string[] | undefined; @@ -78,7 +76,7 @@ export interface IIssueRenderFilters { labels: any[]; project_properties: { [key: string]: { - states: any[] | null; + states: any | null; labels: any[] | null; members: any[] | null; }; @@ -622,11 +620,6 @@ class IssueFilterStore implements IIssueFilterStore { const issuesStateResponse = await this.stateService.getStates(workspaceId, projectId); if (issuesStateResponse) { - const _states: any[] = []; - Object.keys(issuesStateResponse).map((state) => { - _states.push(...issuesStateResponse[state]); - }); - const _issuesStateResponse = { ...this.issueRenderFilters, workspace_properties: { @@ -638,7 +631,7 @@ class IssueFilterStore implements IIssueFilterStore { [projectId]: { ...this.issueRenderFilters?.workspace_properties?.[workspaceId] ?.project_properties?.[projectId], - states: _states, + states: issuesStateResponse, }, }, },