From 38f014bd77e53bf41eecd8e7f7441d7ec8f2928d Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal Date: Fri, 2 Feb 2024 13:31:57 +0530 Subject: [PATCH 1/5] chore: added tab change animation --- .../dashboard/widgets/assigned-issues.tsx | 2 +- .../dashboard/widgets/created-issues.tsx | 2 +- .../widgets/issue-panels/issues-list.tsx | 9 +-- .../widgets/issue-panels/tabs-list.tsx | 64 +++++++++++++------ 4 files changed, 48 insertions(+), 29 deletions(-) diff --git a/web/components/dashboard/widgets/assigned-issues.tsx b/web/components/dashboard/widgets/assigned-issues.tsx index d4a27afc154..13993ddda6b 100644 --- a/web/components/dashboard/widgets/assigned-issues.tsx +++ b/web/components/dashboard/widgets/assigned-issues.tsx @@ -99,7 +99,7 @@ export const AssignedIssuesWidget: React.FC = observer((props) => { className="h-full flex flex-col" >
- +
{ISSUES_TABS_LIST.map((tab) => ( diff --git a/web/components/dashboard/widgets/created-issues.tsx b/web/components/dashboard/widgets/created-issues.tsx index f5727f277df..3732303d81a 100644 --- a/web/components/dashboard/widgets/created-issues.tsx +++ b/web/components/dashboard/widgets/created-issues.tsx @@ -95,7 +95,7 @@ export const CreatedIssuesWidget: React.FC = observer((props) => { className="h-full flex flex-col" >
- +
{ISSUES_TABS_LIST.map((tab) => ( diff --git a/web/components/dashboard/widgets/issue-panels/issues-list.tsx b/web/components/dashboard/widgets/issue-panels/issues-list.tsx index af2c11660bb..df8ee6d713a 100644 --- a/web/components/dashboard/widgets/issue-panels/issues-list.tsx +++ b/web/components/dashboard/widgets/issue-panels/issues-list.tsx @@ -14,7 +14,7 @@ import { IssueListItemProps, } from "components/dashboard/widgets"; // ui -import { Loader, getButtonStyling } from "@plane/ui"; +import { getButtonStyling } from "@plane/ui"; // helpers import { cn } from "helpers/common.helper"; import { getRedirectionFilters } from "helpers/dashboard.helper"; @@ -61,12 +61,7 @@ export const WidgetIssuesList: React.FC = (props) => { <>
{isLoading ? ( - - - - - - + <> ) : issues.length > 0 ? ( <>
diff --git a/web/components/dashboard/widgets/issue-panels/tabs-list.tsx b/web/components/dashboard/widgets/issue-panels/tabs-list.tsx index 6ef6ec0eea5..03b70a37fa6 100644 --- a/web/components/dashboard/widgets/issue-panels/tabs-list.tsx +++ b/web/components/dashboard/widgets/issue-panels/tabs-list.tsx @@ -1,26 +1,50 @@ import { Tab } from "@headlessui/react"; // helpers import { cn } from "helpers/common.helper"; +// types +import { TIssuesListTypes } from "@plane/types"; // constants import { ISSUES_TABS_LIST } from "constants/dashboard"; -export const TabsList = () => ( - - {ISSUES_TABS_LIST.map((tab) => ( - - cn("font-semibold text-xs rounded py-1.5 focus:outline-none", { - "bg-custom-background-100 text-custom-text-300 shadow-[2px_0_8px_rgba(167,169,174,0.15)]": selected, - "text-custom-text-400": !selected, - }) - } - > - {tab.label} - - ))} - -); +type Props = { + selectedTab: TIssuesListTypes; +}; + +export const TabsList: React.FC = (props) => { + const { selectedTab } = props; + const selectedTabIndex = ISSUES_TABS_LIST.findIndex((tab) => tab.key === selectedTab); + + return ( + +
+ {ISSUES_TABS_LIST.map((tab) => ( + + cn( + "relative z-[1] font-semibold text-xs rounded py-1.5 text-custom-text-400 focus:outline-none transition duration-500", + { + "text-custom-text-100": selected, + "hover:text-custom-text-300": !selected, + } + ) + } + > + {tab.label} + + ))} + + ); +}; From 7b6189bbaa50d7c19c02c1a2c6a450cc61cd233f Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal Date: Fri, 2 Feb 2024 18:51:01 +0530 Subject: [PATCH 2/5] chore: widgets filtering logic updated --- apiserver/plane/app/views/dashboard.py | 34 +++++++++ packages/types/src/dashboard.d.ts | 3 +- .../dashboard/widgets/assigned-issues.tsx | 75 ++++++++++++------- .../dashboard/widgets/created-issues.tsx | 73 +++++++++++------- .../widgets/issue-panels/issues-list.tsx | 6 +- .../widgets/issue-panels/tabs-list.tsx | 44 +++++++---- .../dashboard/widgets/issues-by-priority.tsx | 28 +++---- .../widgets/issues-by-state-group.tsx | 44 +++++------ web/constants/dashboard.ts | 39 ++++++++-- web/helpers/dashboard.helper.ts | 6 +- 10 files changed, 233 insertions(+), 119 deletions(-) diff --git a/apiserver/plane/app/views/dashboard.py b/apiserver/plane/app/views/dashboard.py index 47fae2c9ca1..1366a2886a9 100644 --- a/apiserver/plane/app/views/dashboard.py +++ b/apiserver/plane/app/views/dashboard.py @@ -145,6 +145,23 @@ def dashboard_assigned_issues(self, request, slug): ) ).order_by("priority_order") + if issue_type == "pending": + pending_issues_count = assigned_issues.filter( + state__group__in=["backlog", "started", "unstarted"] + ).count() + pending_issues = assigned_issues.filter( + state__group__in=["backlog", "started", "unstarted"] + )[:5] + return Response( + { + "issues": IssueSerializer( + pending_issues, many=True, expand=self.expand + ).data, + "count": pending_issues_count, + }, + status=status.HTTP_200_OK, + ) + if issue_type == "completed": completed_issues_count = assigned_issues.filter( state__group__in=["completed"] @@ -257,6 +274,23 @@ def dashboard_created_issues(self, request, slug): ) ).order_by("priority_order") + if issue_type == "pending": + pending_issues_count = created_issues.filter( + state__group__in=["backlog", "started", "unstarted"] + ).count() + pending_issues = created_issues.filter( + state__group__in=["backlog", "started", "unstarted"] + )[:5] + return Response( + { + "issues": IssueSerializer( + pending_issues, many=True, expand=self.expand + ).data, + "count": pending_issues_count, + }, + status=status.HTTP_200_OK, + ) + if issue_type == "completed": completed_issues_count = created_issues.filter( state__group__in=["completed"] diff --git a/packages/types/src/dashboard.d.ts b/packages/types/src/dashboard.d.ts index 31751c0d06c..7cfa6aa8563 100644 --- a/packages/types/src/dashboard.d.ts +++ b/packages/types/src/dashboard.d.ts @@ -13,9 +13,10 @@ export type TWidgetKeys = | "recent_projects" | "recent_collaborators"; -export type TIssuesListTypes = "upcoming" | "overdue" | "completed"; +export type TIssuesListTypes = "pending" | "upcoming" | "overdue" | "completed"; export type TDurationFilterOptions = + | "none" | "today" | "this_week" | "this_month" diff --git a/web/components/dashboard/widgets/assigned-issues.tsx b/web/components/dashboard/widgets/assigned-issues.tsx index 13993ddda6b..2c57f6176aa 100644 --- a/web/components/dashboard/widgets/assigned-issues.tsx +++ b/web/components/dashboard/widgets/assigned-issues.tsx @@ -17,7 +17,7 @@ import { getCustomDates, getRedirectionFilters } from "helpers/dashboard.helper" // types import { TAssignedIssuesWidgetFilters, TAssignedIssuesWidgetResponse } from "@plane/types"; // constants -import { ISSUES_TABS_LIST } from "constants/dashboard"; +import { FILTERED_ISSUES_TABS_LIST, UNFILTERED_ISSUES_TABS_LIST } from "constants/dashboard"; const WIDGET_KEY = "assigned_issues"; @@ -41,68 +41,85 @@ export const AssignedIssuesWidget: React.FC = observer((props) => { filters, }); + const filterDates = getCustomDates(filters.target_date ?? widgetDetails.widget_filters.target_date ?? "none"); fetchWidgetStats(workspaceSlug, dashboardId, { widget_key: WIDGET_KEY, - issue_type: filters.tab ?? widgetDetails.widget_filters.tab ?? "upcoming", - target_date: getCustomDates(filters.target_date ?? widgetDetails.widget_filters.target_date ?? "this_week"), + issue_type: filters.tab ?? widgetDetails.widget_filters.tab ?? "pending", + ...(filterDates.trim() !== "" ? { target_date: filterDates } : {}), expand: "issue_relation", }).finally(() => setFetching(false)); }; useEffect(() => { - const filterDates = getCustomDates(widgetDetails?.widget_filters.target_date ?? "this_week"); + const filterDates = getCustomDates(widgetDetails?.widget_filters.target_date ?? "none"); fetchWidgetStats(workspaceSlug, dashboardId, { widget_key: WIDGET_KEY, - issue_type: widgetDetails?.widget_filters.tab ?? "upcoming", - target_date: filterDates, + issue_type: widgetDetails?.widget_filters.tab ?? "pending", + ...(filterDates.trim() !== "" ? { target_date: filterDates } : {}), expand: "issue_relation", }); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - const filterParams = getRedirectionFilters(widgetDetails?.widget_filters.tab ?? "upcoming"); + const filterParams = getRedirectionFilters(widgetDetails?.widget_filters.tab ?? "pending"); + const tabsList = + widgetDetails?.widget_filters.target_date ?? "none" ? UNFILTERED_ISSUES_TABS_LIST : FILTERED_ISSUES_TABS_LIST; if (!widgetDetails || !widgetStats) return ; return (
-
-
- - Assigned to you - -

- Filtered by{" "} - Due date -

-
+
+ + Assigned to you + + value={widgetDetails.widget_filters.target_date ?? "none"} + onChange={(val) => { + if (val === widgetDetails.widget_filters.target_date) return; + let extraOptions: Partial = {}; + + // switch to pending tab if target date is changed to none + if (val === "none" && widgetDetails.widget_filters.tab !== "completed") extraOptions = { tab: "pending" }; + // switch to upcoming tab if target date is changed to other than none + if ( + val !== "none" && + widgetDetails.widget_filters.target_date === "none" && + widgetDetails.widget_filters.tab !== "completed" + ) + extraOptions = { tab: "upcoming" }; + handleUpdateFilters({ target_date: val, - }) - } + ...extraOptions, + }); + }} />
t.key === widgetDetails.widget_filters.tab ?? "upcoming")} + // selectedIndex={selectedIndex} + defaultIndex={tabsList.findIndex((t) => t.key === widgetDetails.widget_filters.tab ?? "pending")} onChange={(i) => { - const selectedTab = ISSUES_TABS_LIST[i]; - handleUpdateFilters({ tab: selectedTab.key ?? "upcoming" }); + const selectedTab = tabsList[i]; + handleUpdateFilters({ tab: selectedTab?.key ?? "pending" }); + // setSelectedIndex(i); }} className="h-full flex flex-col" >
- +
- {ISSUES_TABS_LIST.map((tab) => ( + {tabsList.map((tab) => ( = observer((props) => { filters, }); + const filterDates = getCustomDates(filters.target_date ?? widgetDetails.widget_filters.target_date ?? "none"); fetchWidgetStats(workspaceSlug, dashboardId, { widget_key: WIDGET_KEY, - issue_type: filters.tab ?? widgetDetails.widget_filters.tab ?? "upcoming", - target_date: getCustomDates(filters.target_date ?? widgetDetails.widget_filters.target_date ?? "this_week"), + issue_type: filters.tab ?? widgetDetails.widget_filters.tab ?? "pending", + ...(filterDates.trim() !== "" ? { target_date: filterDates } : {}), }).finally(() => setFetching(false)); }; useEffect(() => { + const filterDates = getCustomDates(widgetDetails?.widget_filters.target_date ?? "none"); + fetchWidgetStats(workspaceSlug, dashboardId, { widget_key: WIDGET_KEY, - issue_type: widgetDetails?.widget_filters.tab ?? "upcoming", - target_date: getCustomDates(widgetDetails?.widget_filters.target_date ?? "this_week"), + issue_type: widgetDetails?.widget_filters.tab ?? "pending", + ...(filterDates.trim() !== "" ? { target_date: filterDates } : {}), }); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - const filterParams = getRedirectionFilters(widgetDetails?.widget_filters.tab ?? "upcoming"); + const filterParams = getRedirectionFilters(widgetDetails?.widget_filters.tab ?? "pending"); + const tabsList = + (widgetDetails?.widget_filters.target_date ?? "none") === "none" + ? UNFILTERED_ISSUES_TABS_LIST + : FILTERED_ISSUES_TABS_LIST; if (!widgetDetails || !widgetStats) return ; return (
-
-
- - Created by you - -

- Filtered by{" "} - Due date -

-
+
+ + Created by you + + value={widgetDetails.widget_filters.target_date ?? "none"} + onChange={(val) => { + if (val === widgetDetails.widget_filters.target_date) return; + let extraOptions: Partial = {}; + + // switch to pending tab if target date is changed to none + if (val === "none" && widgetDetails.widget_filters.tab !== "completed") extraOptions = { tab: "pending" }; + // switch to upcoming tab if target date is changed to other than none + if ( + val !== "none" && + widgetDetails.widget_filters.target_date === "none" && + widgetDetails.widget_filters.tab !== "completed" + ) + extraOptions = { tab: "upcoming" }; + handleUpdateFilters({ target_date: val, - }) - } + ...extraOptions, + }); + }} />
t.key === widgetDetails.widget_filters.tab ?? "upcoming")} onChange={(i) => { - const selectedTab = ISSUES_TABS_LIST[i]; - handleUpdateFilters({ tab: selectedTab.key ?? "upcoming" }); + const selectedTab = tabsList[i]; + handleUpdateFilters({ tab: selectedTab.key ?? "pending" }); }} className="h-full flex flex-col" >
- +
- {ISSUES_TABS_LIST.map((tab) => ( + {tabsList.map((tab) => ( = (props) => { const filterParams = getRedirectionFilters(tab); const ISSUE_LIST_ITEM: { - [key in string]: { + [key: string]: { [key in TIssuesListTypes]: React.FC; }; } = { assigned: { + pending: AssignedUpcomingIssueListItem, upcoming: AssignedUpcomingIssueListItem, overdue: AssignedOverdueIssueListItem, completed: AssignedCompletedIssueListItem, }, created: { + pending: CreatedUpcomingIssueListItem, upcoming: CreatedUpcomingIssueListItem, overdue: CreatedOverdueIssueListItem, completed: CreatedCompletedIssueListItem, @@ -76,7 +78,7 @@ export const WidgetIssuesList: React.FC = (props) => { {totalIssues} - {tab === "upcoming" &&
Due date
} + {["upcoming", "pending"].includes(tab) &&
Due date
} {tab === "overdue" &&
Due by
} {type === "assigned" && tab !== "completed" &&
Blocked by
} {type === "created" &&
Assigned to
} diff --git a/web/components/dashboard/widgets/issue-panels/tabs-list.tsx b/web/components/dashboard/widgets/issue-panels/tabs-list.tsx index 03b70a37fa6..9f8f2bbd61a 100644 --- a/web/components/dashboard/widgets/issue-panels/tabs-list.tsx +++ b/web/components/dashboard/widgets/issue-panels/tabs-list.tsx @@ -2,42 +2,60 @@ import { Tab } from "@headlessui/react"; // helpers import { cn } from "helpers/common.helper"; // types -import { TIssuesListTypes } from "@plane/types"; +import { TDurationFilterOptions, TIssuesListTypes } from "@plane/types"; // constants -import { ISSUES_TABS_LIST } from "constants/dashboard"; +import { FILTERED_ISSUES_TABS_LIST, UNFILTERED_ISSUES_TABS_LIST } from "constants/dashboard"; type Props = { + durationFilter: TDurationFilterOptions; selectedTab: TIssuesListTypes; }; export const TabsList: React.FC = (props) => { - const { selectedTab } = props; - const selectedTabIndex = ISSUES_TABS_LIST.findIndex((tab) => tab.key === selectedTab); + const { durationFilter, selectedTab } = props; + + const tabsList = durationFilter === "none" ? UNFILTERED_ISSUES_TABS_LIST : FILTERED_ISSUES_TABS_LIST; + const selectedTabIndex = tabsList.findIndex((tab) => tab.key === (selectedTab ?? "pending")); + + // console.log("tabsList", tabsList); + // console.log("activeTab", selectedTab); + // console.log("selectedTabIndex", selectedTabIndex); return ( -
- {ISSUES_TABS_LIST.map((tab) => ( + /> */} + {tabsList.map((tab) => ( cn( - "relative z-[1] font-semibold text-xs rounded py-1.5 text-custom-text-400 focus:outline-none transition duration-500", + "relative z-[1] font-semibold text-xs rounded py-1.5 text-custom-text-400 focus:outline-none", + // "transition duration-500", { - "text-custom-text-100": selected, + "text-custom-text-100 bg-custom-background-100": selected, "hover:text-custom-text-300": !selected, + // right shadow + "shadow-[2px_0_8px_rgba(167,169,174,0.15)]": selectedTabIndex !== tabsList.length - 1, + // left shadow + "shadow-[-2px_0_8px_rgba(167,169,174,0.15)]": selectedTabIndex !== 0, } ) } diff --git a/web/components/dashboard/widgets/issues-by-priority.tsx b/web/components/dashboard/widgets/issues-by-priority.tsx index 45b71466d1f..97884bccc1f 100644 --- a/web/components/dashboard/widgets/issues-by-priority.tsx +++ b/web/components/dashboard/widgets/issues-by-priority.tsx @@ -84,16 +84,18 @@ export const IssuesByPriorityWidget: React.FC = observer((props) => filters, }); + const filterDates = getCustomDates(filters.target_date ?? widgetDetails.widget_filters.target_date ?? "none"); fetchWidgetStats(workspaceSlug, dashboardId, { widget_key: WIDGET_KEY, - target_date: getCustomDates(filters.target_date ?? widgetDetails.widget_filters.target_date ?? "this_week"), + ...(filterDates.trim() !== "" ? { target_date: filterDates } : {}), }); }; useEffect(() => { + const filterDates = getCustomDates(widgetDetails?.widget_filters.target_date ?? "none"); fetchWidgetStats(workspaceSlug, dashboardId, { widget_key: WIDGET_KEY, - target_date: getCustomDates(widgetDetails?.widget_filters.target_date ?? "this_week"), + ...(filterDates.trim() !== "" ? { target_date: filterDates } : {}), }); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); @@ -129,21 +131,15 @@ export const IssuesByPriorityWidget: React.FC = observer((props) => return (
-
-
- - Assigned by priority - -

- Filtered by{" "} - Due date -

-
+
+ + Assigned by priority + handleUpdateFilters({ target_date: val, diff --git a/web/components/dashboard/widgets/issues-by-state-group.tsx b/web/components/dashboard/widgets/issues-by-state-group.tsx index bd4171cfa2d..2f7f6ffae87 100644 --- a/web/components/dashboard/widgets/issues-by-state-group.tsx +++ b/web/components/dashboard/widgets/issues-by-state-group.tsx @@ -43,17 +43,19 @@ export const IssuesByStateGroupWidget: React.FC = observer((props) filters, }); + const filterDates = getCustomDates(filters.target_date ?? widgetDetails.widget_filters.target_date ?? "none"); fetchWidgetStats(workspaceSlug, dashboardId, { widget_key: WIDGET_KEY, - target_date: getCustomDates(filters.target_date ?? widgetDetails.widget_filters.target_date ?? "this_week"), + ...(filterDates.trim() !== "" ? { target_date: filterDates } : {}), }); }; // fetch widget stats useEffect(() => { + const filterDates = getCustomDates(widgetDetails?.widget_filters.target_date ?? "none"); fetchWidgetStats(workspaceSlug, dashboardId, { widget_key: WIDGET_KEY, - target_date: getCustomDates(widgetDetails?.widget_filters.target_date ?? "this_week"), + ...(filterDates.trim() !== "" ? { target_date: filterDates } : {}), }); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); @@ -72,14 +74,14 @@ export const IssuesByStateGroupWidget: React.FC = observer((props) startedCount > 0 ? "started" : unStartedCount > 0 - ? "unstarted" - : backlogCount > 0 - ? "backlog" - : completedCount > 0 - ? "completed" - : canceledCount > 0 - ? "cancelled" - : null; + ? "unstarted" + : backlogCount > 0 + ? "backlog" + : completedCount > 0 + ? "completed" + : canceledCount > 0 + ? "cancelled" + : null; setActiveStateGroup(stateGroup); setDefaultStateGroup(stateGroup); @@ -128,21 +130,15 @@ export const IssuesByStateGroupWidget: React.FC = observer((props) return (
-
-
- - Assigned by state - -

- Filtered by{" "} - Due date -

-
+
+ + Assigned by state + handleUpdateFilters({ target_date: val, diff --git a/web/constants/dashboard.ts b/web/constants/dashboard.ts index d23480cfe5c..3f251ca7811 100644 --- a/web/constants/dashboard.ts +++ b/web/constants/dashboard.ts @@ -121,21 +121,25 @@ export const DURATION_FILTER_OPTIONS: { key: TDurationFilterOptions; label: string; }[] = [ + { + key: "none", + label: "None", + }, { key: "today", - label: "Today", + label: "Due today", }, { key: "this_week", - label: "This week", + label: " Due this week", }, { key: "this_month", - label: "This month", + label: "Due this month", }, { key: "this_year", - label: "This year", + label: "Due this year", }, ]; @@ -152,7 +156,7 @@ export const PROJECT_BACKGROUND_COLORS = [ ]; // assigned and created issues widgets tabs list -export const ISSUES_TABS_LIST: { +export const FILTERED_ISSUES_TABS_LIST: { key: TIssuesListTypes; label: string; }[] = [ @@ -170,7 +174,27 @@ export const ISSUES_TABS_LIST: { }, ]; +// assigned and created issues widgets tabs list +export const UNFILTERED_ISSUES_TABS_LIST: { + key: TIssuesListTypes; + label: string; +}[] = [ + { + key: "pending", + label: "Pending", + }, + { + key: "completed", + label: "Marked completed", + }, +]; + export const ASSIGNED_ISSUES_EMPTY_STATES = { + pending: { + title: "Issues assigned to you that are pending\nwill show up here.", + darkImage: UpcomingIssuesDark, + lightImage: UpcomingIssuesLight, + }, upcoming: { title: "Upcoming issues assigned to\nyou will show up here.", darkImage: UpcomingIssuesDark, @@ -189,6 +213,11 @@ export const ASSIGNED_ISSUES_EMPTY_STATES = { }; export const CREATED_ISSUES_EMPTY_STATES = { + pending: { + title: "Issues created by you that are pending\nwill show up here.", + darkImage: UpcomingIssuesDark, + lightImage: UpcomingIssuesLight, + }, upcoming: { title: "Upcoming issues you created\nwill show up here.", darkImage: UpcomingIssuesDark, diff --git a/web/helpers/dashboard.helper.ts b/web/helpers/dashboard.helper.ts index 2a8ade4fa51..8003f15e32d 100644 --- a/web/helpers/dashboard.helper.ts +++ b/web/helpers/dashboard.helper.ts @@ -9,6 +9,8 @@ export const getCustomDates = (duration: TDurationFilterOptions): string => { let firstDay, lastDay; switch (duration) { + case "none": + return ""; case "today": firstDay = renderFormattedPayloadDate(today); lastDay = renderFormattedPayloadDate(today); @@ -32,7 +34,9 @@ export const getRedirectionFilters = (type: TIssuesListTypes): string => { const today = renderFormattedPayloadDate(new Date()); const filterParams = - type === "upcoming" + type === "pending" + ? "?state_group=backlog,unstarted,started" + : type === "upcoming" ? `?target_date=${today};after` : type === "overdue" ? `?target_date=${today};before` From b2a47989f4c0d0f99b7fddc65b376ef7978013ae Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal Date: Mon, 5 Feb 2024 12:30:25 +0530 Subject: [PATCH 3/5] refactor: issues list widget --- .../dashboard/widgets/assigned-issues.tsx | 52 +++++++++---------- .../dashboard/widgets/created-issues.tsx | 51 +++++++++--------- .../widgets/issue-panels/tabs-list.tsx | 11 ++-- 3 files changed, 54 insertions(+), 60 deletions(-) diff --git a/web/components/dashboard/widgets/assigned-issues.tsx b/web/components/dashboard/widgets/assigned-issues.tsx index 2c57f6176aa..e2a54c05f6e 100644 --- a/web/components/dashboard/widgets/assigned-issues.tsx +++ b/web/components/dashboard/widgets/assigned-issues.tsx @@ -30,6 +30,8 @@ export const AssignedIssuesWidget: React.FC = observer((props) => { // derived values const widgetDetails = getWidgetDetails(workspaceSlug, dashboardId, WIDGET_KEY); const widgetStats = getWidgetStats(workspaceSlug, dashboardId, WIDGET_KEY); + const selectedTab = widgetDetails?.widget_filters.tab ?? "pending"; + const selectedDurationFilter = widgetDetails?.widget_filters.target_date ?? "none"; const handleUpdateFilters = async (filters: Partial) => { if (!widgetDetails) return; @@ -41,21 +43,21 @@ export const AssignedIssuesWidget: React.FC = observer((props) => { filters, }); - const filterDates = getCustomDates(filters.target_date ?? widgetDetails.widget_filters.target_date ?? "none"); + const filterDates = getCustomDates(filters.target_date ?? selectedDurationFilter); fetchWidgetStats(workspaceSlug, dashboardId, { widget_key: WIDGET_KEY, - issue_type: filters.tab ?? widgetDetails.widget_filters.tab ?? "pending", + issue_type: filters.tab ?? selectedTab, ...(filterDates.trim() !== "" ? { target_date: filterDates } : {}), expand: "issue_relation", }).finally(() => setFetching(false)); }; useEffect(() => { - const filterDates = getCustomDates(widgetDetails?.widget_filters.target_date ?? "none"); + const filterDates = getCustomDates(selectedDurationFilter); fetchWidgetStats(workspaceSlug, dashboardId, { widget_key: WIDGET_KEY, - issue_type: widgetDetails?.widget_filters.tab ?? "pending", + issue_type: selectedTab, ...(filterDates.trim() !== "" ? { target_date: filterDates } : {}), expand: "issue_relation", }); @@ -63,9 +65,8 @@ export const AssignedIssuesWidget: React.FC = observer((props) => { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - const filterParams = getRedirectionFilters(widgetDetails?.widget_filters.tab ?? "pending"); - const tabsList = - widgetDetails?.widget_filters.target_date ?? "none" ? UNFILTERED_ISSUES_TABS_LIST : FILTERED_ISSUES_TABS_LIST; + const filterParams = getRedirectionFilters(selectedTab); + const tabsList = selectedDurationFilter === "none" ? UNFILTERED_ISSUES_TABS_LIST : FILTERED_ISSUES_TABS_LIST; if (!widgetDetails || !widgetStats) return ; @@ -79,44 +80,39 @@ export const AssignedIssuesWidget: React.FC = observer((props) => { Assigned to you { - if (val === widgetDetails.widget_filters.target_date) return; - let extraOptions: Partial = {}; + if (val === selectedDurationFilter) return; // switch to pending tab if target date is changed to none - if (val === "none" && widgetDetails.widget_filters.tab !== "completed") extraOptions = { tab: "pending" }; + if (val === "none" && selectedTab !== "completed") { + handleUpdateFilters({ target_date: val, tab: "pending" }); + return; + } // switch to upcoming tab if target date is changed to other than none - if ( - val !== "none" && - widgetDetails.widget_filters.target_date === "none" && - widgetDetails.widget_filters.tab !== "completed" - ) - extraOptions = { tab: "upcoming" }; + if (val !== "none" && selectedDurationFilter === "none" && selectedTab !== "completed") { + handleUpdateFilters({ + target_date: val, + tab: "upcoming", + }); + return; + } - handleUpdateFilters({ - target_date: val, - ...extraOptions, - }); + handleUpdateFilters({ target_date: val }); }} />
t.key === widgetDetails.widget_filters.tab ?? "pending")} + selectedIndex={tabsList.findIndex((tab) => tab.key === selectedTab)} onChange={(i) => { const selectedTab = tabsList[i]; handleUpdateFilters({ tab: selectedTab?.key ?? "pending" }); - // setSelectedIndex(i); }} className="h-full flex flex-col" >
- +
{tabsList.map((tab) => ( diff --git a/web/components/dashboard/widgets/created-issues.tsx b/web/components/dashboard/widgets/created-issues.tsx index 0ad02bd6900..dcdff6685a9 100644 --- a/web/components/dashboard/widgets/created-issues.tsx +++ b/web/components/dashboard/widgets/created-issues.tsx @@ -30,6 +30,8 @@ export const CreatedIssuesWidget: React.FC = observer((props) => { // derived values const widgetDetails = getWidgetDetails(workspaceSlug, dashboardId, WIDGET_KEY); const widgetStats = getWidgetStats(workspaceSlug, dashboardId, WIDGET_KEY); + const selectedTab = widgetDetails?.widget_filters.tab ?? "pending"; + const selectedDurationFilter = widgetDetails?.widget_filters.target_date ?? "none"; const handleUpdateFilters = async (filters: Partial) => { if (!widgetDetails) return; @@ -41,30 +43,27 @@ export const CreatedIssuesWidget: React.FC = observer((props) => { filters, }); - const filterDates = getCustomDates(filters.target_date ?? widgetDetails.widget_filters.target_date ?? "none"); + const filterDates = getCustomDates(filters.target_date ?? selectedDurationFilter); fetchWidgetStats(workspaceSlug, dashboardId, { widget_key: WIDGET_KEY, - issue_type: filters.tab ?? widgetDetails.widget_filters.tab ?? "pending", + issue_type: filters.tab ?? selectedTab, ...(filterDates.trim() !== "" ? { target_date: filterDates } : {}), }).finally(() => setFetching(false)); }; useEffect(() => { - const filterDates = getCustomDates(widgetDetails?.widget_filters.target_date ?? "none"); + const filterDates = getCustomDates(selectedDurationFilter); fetchWidgetStats(workspaceSlug, dashboardId, { widget_key: WIDGET_KEY, - issue_type: widgetDetails?.widget_filters.tab ?? "pending", + issue_type: selectedTab, ...(filterDates.trim() !== "" ? { target_date: filterDates } : {}), }); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - const filterParams = getRedirectionFilters(widgetDetails?.widget_filters.tab ?? "pending"); - const tabsList = - (widgetDetails?.widget_filters.target_date ?? "none") === "none" - ? UNFILTERED_ISSUES_TABS_LIST - : FILTERED_ISSUES_TABS_LIST; + const filterParams = getRedirectionFilters(selectedTab); + const tabsList = selectedDurationFilter === "none" ? UNFILTERED_ISSUES_TABS_LIST : FILTERED_ISSUES_TABS_LIST; if (!widgetDetails || !widgetStats) return ; @@ -78,30 +77,31 @@ export const CreatedIssuesWidget: React.FC = observer((props) => { Created by you { - if (val === widgetDetails.widget_filters.target_date) return; - let extraOptions: Partial = {}; + if (val === selectedDurationFilter) return; // switch to pending tab if target date is changed to none - if (val === "none" && widgetDetails.widget_filters.tab !== "completed") extraOptions = { tab: "pending" }; + if (val === "none" && selectedTab !== "completed") { + handleUpdateFilters({ target_date: val, tab: "pending" }); + return; + } // switch to upcoming tab if target date is changed to other than none - if ( - val !== "none" && - widgetDetails.widget_filters.target_date === "none" && - widgetDetails.widget_filters.tab !== "completed" - ) - extraOptions = { tab: "upcoming" }; + if (val !== "none" && selectedDurationFilter === "none" && selectedTab !== "completed") { + handleUpdateFilters({ + target_date: val, + tab: "upcoming", + }); + return; + } - handleUpdateFilters({ - target_date: val, - ...extraOptions, - }); + handleUpdateFilters({ target_date: val }); }} />
tab.key === selectedTab)} onChange={(i) => { const selectedTab = tabsList[i]; handleUpdateFilters({ tab: selectedTab.key ?? "pending" }); @@ -109,10 +109,7 @@ export const CreatedIssuesWidget: React.FC = observer((props) => { className="h-full flex flex-col" >
- +
{tabsList.map((tab) => ( diff --git a/web/components/dashboard/widgets/issue-panels/tabs-list.tsx b/web/components/dashboard/widgets/issue-panels/tabs-list.tsx index 9f8f2bbd61a..980b7e23abc 100644 --- a/web/components/dashboard/widgets/issue-panels/tabs-list.tsx +++ b/web/components/dashboard/widgets/issue-panels/tabs-list.tsx @@ -1,3 +1,4 @@ +import { observer } from "mobx-react"; import { Tab } from "@headlessui/react"; // helpers import { cn } from "helpers/common.helper"; @@ -11,15 +12,15 @@ type Props = { selectedTab: TIssuesListTypes; }; -export const TabsList: React.FC = (props) => { +export const TabsList: React.FC = observer((props) => { const { durationFilter, selectedTab } = props; const tabsList = durationFilter === "none" ? UNFILTERED_ISSUES_TABS_LIST : FILTERED_ISSUES_TABS_LIST; const selectedTabIndex = tabsList.findIndex((tab) => tab.key === (selectedTab ?? "pending")); - // console.log("tabsList", tabsList); - // console.log("activeTab", selectedTab); - // console.log("selectedTabIndex", selectedTabIndex); + console.log("tabsList", tabsList); + console.log("activeTab", selectedTab); + console.log("selectedTabIndex", selectedTabIndex); return ( = (props) => { ))} ); -}; +}); From 66981b6094d46fdcb5283b250505c97b9abc1438 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal Date: Mon, 5 Feb 2024 12:46:31 +0530 Subject: [PATCH 4/5] fix: tab navigation transition --- .../widgets/issue-panels/tabs-list.tsx | 34 ++++++++----------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/web/components/dashboard/widgets/issue-panels/tabs-list.tsx b/web/components/dashboard/widgets/issue-panels/tabs-list.tsx index 980b7e23abc..9ce00a03c59 100644 --- a/web/components/dashboard/widgets/issue-panels/tabs-list.tsx +++ b/web/components/dashboard/widgets/issue-panels/tabs-list.tsx @@ -18,10 +18,6 @@ export const TabsList: React.FC = observer((props) => { const tabsList = durationFilter === "none" ? UNFILTERED_ISSUES_TABS_LIST : FILTERED_ISSUES_TABS_LIST; const selectedTabIndex = tabsList.findIndex((tab) => tab.key === (selectedTab ?? "pending")); - console.log("tabsList", tabsList); - console.log("activeTab", selectedTab); - console.log("selectedTabIndex", selectedTabIndex); - return ( = observer((props) => { gridTemplateColumns: `repeat(${tabsList.length}, 1fr)`, }} > - {/*
= observer((props) => { width: `${100 / tabsList.length}%`, transform: `translateX(${selectedTabIndex * 100}%)`, }} - /> */} + /> {tabsList.map((tab) => ( - cn( - "relative z-[1] font-semibold text-xs rounded py-1.5 text-custom-text-400 focus:outline-none", - // "transition duration-500", - { - "text-custom-text-100 bg-custom-background-100": selected, - "hover:text-custom-text-300": !selected, - // right shadow - "shadow-[2px_0_8px_rgba(167,169,174,0.15)]": selectedTabIndex !== tabsList.length - 1, - // left shadow - "shadow-[-2px_0_8px_rgba(167,169,174,0.15)]": selectedTabIndex !== 0, - } - ) - } + className={cn( + "relative z-[1] font-semibold text-xs rounded py-1.5 text-custom-text-400 focus:outline-none", + "transition duration-500", + { + "text-custom-text-100 bg-custom-background-100": selectedTab === tab.key, + "hover:text-custom-text-300": selectedTab !== tab.key, + // // right shadow + // "shadow-[2px_0_8px_rgba(167,169,174,0.15)]": selectedTabIndex !== tabsList.length - 1, + // // left shadow + // "shadow-[-2px_0_8px_rgba(167,169,174,0.15)]": selectedTabIndex !== 0, + } + )} > {tab.label} From 0c58c40d245de079ac611d894192ff4654e66463 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal Date: Mon, 5 Feb 2024 18:23:31 +0530 Subject: [PATCH 5/5] fix: extra top spacing on opening the peek overview --- .../page-views/workspace-dashboard.tsx | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/web/components/page-views/workspace-dashboard.tsx b/web/components/page-views/workspace-dashboard.tsx index 3ae0b9e62a0..a66e843aea5 100644 --- a/web/components/page-views/workspace-dashboard.tsx +++ b/web/components/page-views/workspace-dashboard.tsx @@ -62,16 +62,18 @@ export const WorkspaceDashboardView = observer(() => { {homeDashboardId && joinedProjectIds ? ( <> {joinedProjectIds.length > 0 ? ( -
+ <> - {currentUser && } - {currentUser && !currentUser.is_tour_completed && ( -
- -
- )} - -
+
+ {currentUser && } + {currentUser && !currentUser.is_tour_completed && ( +
+ +
+ )} + +
+ ) : (