-
+
+
Blocked by
@@ -299,8 +301,8 @@ export const PeekOverviewProperties: FC
= observer((pro
{/* duplicate of */}
-
-
+
+
Duplicate of
From c7616fda1106022870fb6b9e4d633fcb16fbbd55 Mon Sep 17 00:00:00 2001
From: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com>
Date: Mon, 29 Jan 2024 20:38:32 +0530
Subject: [PATCH 3/7] chore: empty state theme improvement (#3501)
---
web/components/cycles/active-cycle-details.tsx | 6 +++++-
web/components/cycles/cycles-board.tsx | 7 ++++++-
web/components/cycles/cycles-list.tsx | 7 ++++++-
.../issue-layouts/empty-states/archived-issues.tsx | 13 +++++++------
.../issue-layouts/empty-states/draft-issues.tsx | 13 +++++++------
.../issue-layouts/empty-states/project-issues.tsx | 12 ++++++------
.../issue-layouts/roots/all-issue-layout-root.tsx | 6 +++++-
web/components/modules/modules-list-view.tsx | 6 +++++-
web/components/page-views/workspace-dashboard.tsx | 6 +++++-
web/components/pages/pages-list/list-view.tsx | 12 ++++++------
.../pages/pages-list/recent-pages-list.tsx | 6 +++++-
web/components/profile/profile-issues.tsx | 7 ++++++-
web/components/project/card-list.tsx | 8 +++++---
web/components/views/views-list.tsx | 6 +++++-
web/pages/[workspaceSlug]/analytics.tsx | 6 +++++-
.../projects/[projectId]/cycles/index.tsx | 7 ++++++-
.../projects/[projectId]/pages/index.tsx | 8 ++++++--
17 files changed, 96 insertions(+), 40 deletions(-)
diff --git a/web/components/cycles/active-cycle-details.tsx b/web/components/cycles/active-cycle-details.tsx
index d42f9f543..b1d144d15 100644
--- a/web/components/cycles/active-cycle-details.tsx
+++ b/web/components/cycles/active-cycle-details.tsx
@@ -2,6 +2,7 @@ import { MouseEvent } from "react";
import Link from "next/link";
import { observer } from "mobx-react-lite";
import useSWR from "swr";
+import { useTheme } from "next-themes";
// hooks
import { useCycle, useIssues, useProject, useUser } from "hooks/store";
import useToast from "hooks/use-toast";
@@ -43,6 +44,7 @@ interface IActiveCycleDetails {
export const ActiveCycleDetails: React.FC
= observer((props) => {
// props
const { workspaceSlug, projectId } = props;
+ const { resolvedTheme } = useTheme();
// store hooks
const { currentUser } = useUser();
const {
@@ -76,7 +78,9 @@ export const ActiveCycleDetails: React.FC = observer((props
);
const emptyStateDetail = CYCLE_EMPTY_STATE_DETAILS["active"];
- const emptyStateImage = getEmptyStateImagePath("cycle", "active", currentUser?.theme.theme === "light");
+
+ const isLightMode = resolvedTheme ? resolvedTheme === "light" : currentUser?.theme.theme === "light";
+ const emptyStateImage = getEmptyStateImagePath("cycle", "active", isLightMode);
if (!activeCycle && isLoading)
return (
diff --git a/web/components/cycles/cycles-board.tsx b/web/components/cycles/cycles-board.tsx
index 1365e4aa4..19e7f2225 100644
--- a/web/components/cycles/cycles-board.tsx
+++ b/web/components/cycles/cycles-board.tsx
@@ -1,5 +1,6 @@
import { FC } from "react";
import { observer } from "mobx-react-lite";
+import { useTheme } from "next-themes";
// hooks
import { useUser } from "hooks/store";
// components
@@ -18,11 +19,15 @@ export interface ICyclesBoard {
export const CyclesBoard: FC = observer((props) => {
const { cycleIds, filter, workspaceSlug, projectId, peekCycle } = props;
+ // theme
+ const { resolvedTheme } = useTheme();
// store hooks
const { currentUser } = useUser();
const emptyStateDetail = CYCLE_EMPTY_STATE_DETAILS[filter as keyof typeof CYCLE_EMPTY_STATE_DETAILS];
- const emptyStateImage = getEmptyStateImagePath("cycle", filter, currentUser?.theme.theme === "light");
+
+ const isLightMode = resolvedTheme ? resolvedTheme === "light" : currentUser?.theme.theme === "light";
+ const emptyStateImage = getEmptyStateImagePath("cycle", filter, isLightMode);
return (
<>
diff --git a/web/components/cycles/cycles-list.tsx b/web/components/cycles/cycles-list.tsx
index 3dfa2130b..90fcdd8f9 100644
--- a/web/components/cycles/cycles-list.tsx
+++ b/web/components/cycles/cycles-list.tsx
@@ -1,5 +1,6 @@
import { FC } from "react";
import { observer } from "mobx-react-lite";
+import { useTheme } from "next-themes";
// hooks
import { useUser } from "hooks/store";
// components
@@ -19,11 +20,15 @@ export interface ICyclesList {
export const CyclesList: FC = observer((props) => {
const { cycleIds, filter, workspaceSlug, projectId } = props;
+ // theme
+ const { resolvedTheme } = useTheme();
// store hooks
const { currentUser } = useUser();
const emptyStateDetail = CYCLE_EMPTY_STATE_DETAILS[filter as keyof typeof CYCLE_EMPTY_STATE_DETAILS];
- const emptyStateImage = getEmptyStateImagePath("cycle", filter, currentUser?.theme.theme === "light");
+
+ const isLightMode = resolvedTheme ? resolvedTheme === "light" : currentUser?.theme.theme === "light";
+ const emptyStateImage = getEmptyStateImagePath("cycle", filter, isLightMode);
return (
<>
diff --git a/web/components/issues/issue-layouts/empty-states/archived-issues.tsx b/web/components/issues/issue-layouts/empty-states/archived-issues.tsx
index 33f46ba24..f04144d04 100644
--- a/web/components/issues/issue-layouts/empty-states/archived-issues.tsx
+++ b/web/components/issues/issue-layouts/empty-states/archived-issues.tsx
@@ -1,6 +1,7 @@
import { observer } from "mobx-react-lite";
import { useRouter } from "next/router";
import size from "lodash/size";
+import { useTheme } from "next-themes";
// hooks
import { useIssues, useUser } from "hooks/store";
// components
@@ -26,6 +27,9 @@ export const ProjectArchivedEmptyState: React.FC = observer(() => {
// router
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
+ // theme
+ const { resolvedTheme } = useTheme();
+ // store hooks
const {
membership: { currentProjectRole },
currentUser,
@@ -35,12 +39,9 @@ export const ProjectArchivedEmptyState: React.FC = observer(() => {
const userFilters = issuesFilter?.issueFilters?.filters;
const activeLayout = issuesFilter?.issueFilters?.displayFilters?.layout;
- const currentLayoutEmptyStateImagePath = getEmptyStateImagePath(
- "empty-filters",
- activeLayout ?? "list",
- currentUser?.theme.theme === "light"
- );
- const EmptyStateImagePath = getEmptyStateImagePath("archived", "empty-issues", currentUser?.theme.theme === "light");
+ const isLightMode = resolvedTheme ? resolvedTheme === "light" : currentUser?.theme.theme === "light";
+ const currentLayoutEmptyStateImagePath = getEmptyStateImagePath("empty-filters", activeLayout ?? "list", isLightMode);
+ const EmptyStateImagePath = getEmptyStateImagePath("archived", "empty-issues", isLightMode);
const issueFilterCount = size(
Object.fromEntries(
diff --git a/web/components/issues/issue-layouts/empty-states/draft-issues.tsx b/web/components/issues/issue-layouts/empty-states/draft-issues.tsx
index 258d0d5d3..ba6a9ed2a 100644
--- a/web/components/issues/issue-layouts/empty-states/draft-issues.tsx
+++ b/web/components/issues/issue-layouts/empty-states/draft-issues.tsx
@@ -1,6 +1,7 @@
import { observer } from "mobx-react-lite";
import { useRouter } from "next/router";
import size from "lodash/size";
+import { useTheme } from "next-themes";
// hooks
import { useIssues, useUser } from "hooks/store";
// components
@@ -26,6 +27,9 @@ export const ProjectDraftEmptyState: React.FC = observer(() => {
// router
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
+ // theme
+ const { resolvedTheme } = useTheme();
+ // store hooks
const {
membership: { currentProjectRole },
currentUser,
@@ -35,12 +39,9 @@ export const ProjectDraftEmptyState: React.FC = observer(() => {
const userFilters = issuesFilter?.issueFilters?.filters;
const activeLayout = issuesFilter?.issueFilters?.displayFilters?.layout;
- const currentLayoutEmptyStateImagePath = getEmptyStateImagePath(
- "empty-filters",
- activeLayout ?? "list",
- currentUser?.theme.theme === "light"
- );
- const EmptyStateImagePath = getEmptyStateImagePath("draft", "empty-issues", currentUser?.theme.theme === "light");
+ const isLightMode = resolvedTheme ? resolvedTheme === "light" : currentUser?.theme.theme === "light";
+ const currentLayoutEmptyStateImagePath = getEmptyStateImagePath("empty-filters", activeLayout ?? "list", isLightMode);
+ const EmptyStateImagePath = getEmptyStateImagePath("draft", "empty-issues", isLightMode);
const issueFilterCount = size(
Object.fromEntries(
diff --git a/web/components/issues/issue-layouts/empty-states/project-issues.tsx b/web/components/issues/issue-layouts/empty-states/project-issues.tsx
index 49de72aca..ee6216634 100644
--- a/web/components/issues/issue-layouts/empty-states/project-issues.tsx
+++ b/web/components/issues/issue-layouts/empty-states/project-issues.tsx
@@ -1,6 +1,7 @@
import { observer } from "mobx-react-lite";
import { useRouter } from "next/router";
import size from "lodash/size";
+import { useTheme } from "next-themes";
// hooks
import { useApplication, useIssues, useUser } from "hooks/store";
// components
@@ -26,6 +27,8 @@ export const ProjectEmptyState: React.FC = observer(() => {
// router
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
+ // theme
+ const { resolvedTheme } = useTheme();
// store hooks
const {
commandPalette: commandPaletteStore,
@@ -40,12 +43,9 @@ export const ProjectEmptyState: React.FC = observer(() => {
const userFilters = issuesFilter?.issueFilters?.filters;
const activeLayout = issuesFilter?.issueFilters?.displayFilters?.layout;
- const currentLayoutEmptyStateImagePath = getEmptyStateImagePath(
- "empty-filters",
- activeLayout ?? "list",
- currentUser?.theme.theme === "light"
- );
- const EmptyStateImagePath = getEmptyStateImagePath("onboarding", "issues", currentUser?.theme.theme === "light");
+ const isLightMode = resolvedTheme ? resolvedTheme === "light" : currentUser?.theme.theme === "light";
+ const currentLayoutEmptyStateImagePath = getEmptyStateImagePath("empty-filters", activeLayout ?? "list", isLightMode);
+ const EmptyStateImagePath = getEmptyStateImagePath("onboarding", "issues", isLightMode);
const issueFilterCount = size(
Object.fromEntries(
diff --git a/web/components/issues/issue-layouts/roots/all-issue-layout-root.tsx b/web/components/issues/issue-layouts/roots/all-issue-layout-root.tsx
index d808bded2..be853b64a 100644
--- a/web/components/issues/issue-layouts/roots/all-issue-layout-root.tsx
+++ b/web/components/issues/issue-layouts/roots/all-issue-layout-root.tsx
@@ -3,6 +3,7 @@ import { useRouter } from "next/router";
import { observer } from "mobx-react-lite";
import useSWR from "swr";
import isEmpty from "lodash/isEmpty";
+import { useTheme } from "next-themes";
// hooks
import { useApplication, useGlobalView, useIssues, useProject, useUser } from "hooks/store";
import { useWorkspaceIssueProperties } from "hooks/use-workspace-issue-properties";
@@ -25,6 +26,8 @@ export const AllIssueLayoutRoot: React.FC = observer(() => {
// router
const router = useRouter();
const { workspaceSlug, globalViewId } = router.query;
+ // theme
+ const { resolvedTheme } = useTheme();
//swr hook for fetching issue properties
useWorkspaceIssueProperties(workspaceSlug);
// store
@@ -46,7 +49,8 @@ export const AllIssueLayoutRoot: React.FC = observer(() => {
const currentView = isDefaultView ? groupedIssueIds.dataViewId : "custom-view";
const currentViewDetails = ALL_ISSUES_EMPTY_STATE_DETAILS[currentView as keyof typeof ALL_ISSUES_EMPTY_STATE_DETAILS];
- const emptyStateImage = getEmptyStateImagePath("all-issues", currentView, currentUser?.theme.theme === "light");
+ const isLightMode = resolvedTheme ? resolvedTheme === "light" : currentUser?.theme.theme === "light";
+ const emptyStateImage = getEmptyStateImagePath("all-issues", currentView, isLightMode);
// filter init from the query params
diff --git a/web/components/modules/modules-list-view.tsx b/web/components/modules/modules-list-view.tsx
index 0708187c1..93b12d94c 100644
--- a/web/components/modules/modules-list-view.tsx
+++ b/web/components/modules/modules-list-view.tsx
@@ -1,5 +1,6 @@
import { useRouter } from "next/router";
import { observer } from "mobx-react-lite";
+import { useTheme } from "next-themes";
// hooks
import { useApplication, useModule, useUser } from "hooks/store";
import useLocalStorage from "hooks/use-local-storage";
@@ -15,6 +16,8 @@ export const ModulesListView: React.FC = observer(() => {
// router
const router = useRouter();
const { workspaceSlug, projectId, peekModule } = router.query;
+ // theme
+ const { resolvedTheme } = useTheme();
// store hooks
const { commandPalette: commandPaletteStore } = useApplication();
const {
@@ -25,7 +28,8 @@ export const ModulesListView: React.FC = observer(() => {
const { storedValue: modulesView } = useLocalStorage("modules_view", "grid");
- const EmptyStateImagePath = getEmptyStateImagePath("onboarding", "modules", currentUser?.theme.theme === "light");
+ const isLightMode = resolvedTheme ? resolvedTheme === "light" : currentUser?.theme.theme === "light";
+ const EmptyStateImagePath = getEmptyStateImagePath("onboarding", "modules", isLightMode);
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
diff --git a/web/components/page-views/workspace-dashboard.tsx b/web/components/page-views/workspace-dashboard.tsx
index fa5f7c2c1..3ae0b9e62 100644
--- a/web/components/page-views/workspace-dashboard.tsx
+++ b/web/components/page-views/workspace-dashboard.tsx
@@ -1,4 +1,5 @@
import { useEffect } from "react";
+import { useTheme } from "next-themes";
import { observer } from "mobx-react-lite";
// hooks
import { useApplication, useDashboard, useProject, useUser } from "hooks/store";
@@ -14,6 +15,8 @@ import { Spinner } from "@plane/ui";
import { EUserWorkspaceRoles } from "constants/workspace";
export const WorkspaceDashboardView = observer(() => {
+ // theme
+ const { resolvedTheme } = useTheme();
// store hooks
const {
commandPalette: { toggleCreateProjectModal },
@@ -28,7 +31,8 @@ export const WorkspaceDashboardView = observer(() => {
const { homeDashboardId, fetchHomeDashboardWidgets } = useDashboard();
const { joinedProjectIds } = useProject();
- const emptyStateImage = getEmptyStateImagePath("onboarding", "dashboard", currentUser?.theme.theme === "light");
+ const isLightMode = resolvedTheme ? resolvedTheme === "light" : currentUser?.theme.theme === "light";
+ const emptyStateImage = getEmptyStateImagePath("onboarding", "dashboard", isLightMode);
const handleTourCompleted = () => {
updateTourCompleted()
diff --git a/web/components/pages/pages-list/list-view.tsx b/web/components/pages/pages-list/list-view.tsx
index d1bde308d..4b5634736 100644
--- a/web/components/pages/pages-list/list-view.tsx
+++ b/web/components/pages/pages-list/list-view.tsx
@@ -1,5 +1,6 @@
import { FC } from "react";
import { useRouter } from "next/router";
+import { useTheme } from "next-themes";
// hooks
import { useApplication, useUser } from "hooks/store";
import useLocalStorage from "hooks/use-local-storage";
@@ -18,7 +19,9 @@ type IPagesListView = {
export const PagesListView: FC = (props) => {
const { pageIds: projectPageIds } = props;
-
+ // theme
+ const { resolvedTheme } = useTheme();
+ // store hooks
const {
commandPalette: { toggleCreatePageModal },
} = useApplication();
@@ -36,11 +39,8 @@ export const PagesListView: FC = (props) => {
? PAGE_EMPTY_STATE_DETAILS[pageTab as keyof typeof PAGE_EMPTY_STATE_DETAILS]
: PAGE_EMPTY_STATE_DETAILS["All"];
- const emptyStateImage = getEmptyStateImagePath(
- "pages",
- currentPageTabDetails.key,
- currentUser?.theme.theme === "light"
- );
+ const isLightMode = resolvedTheme ? resolvedTheme === "light" : currentUser?.theme.theme === "light";
+ const emptyStateImage = getEmptyStateImagePath("pages", currentPageTabDetails.key, isLightMode);
const isButtonVisible = currentPageTabDetails.key !== "archived" && currentPageTabDetails.key !== "favorites";
diff --git a/web/components/pages/pages-list/recent-pages-list.tsx b/web/components/pages/pages-list/recent-pages-list.tsx
index 24916debc..960d5253b 100644
--- a/web/components/pages/pages-list/recent-pages-list.tsx
+++ b/web/components/pages/pages-list/recent-pages-list.tsx
@@ -1,5 +1,6 @@
import React, { FC } from "react";
import { observer } from "mobx-react-lite";
+import { useTheme } from "next-themes";
// hooks
import { useApplication, useUser } from "hooks/store";
import { useProjectPages } from "hooks/store/use-project-specific-pages";
@@ -14,6 +15,8 @@ import { replaceUnderscoreIfSnakeCase } from "helpers/string.helper";
import { EUserProjectRoles } from "constants/project";
export const RecentPagesList: FC = observer(() => {
+ // theme
+ const { resolvedTheme } = useTheme();
// store hooks
const { commandPalette: commandPaletteStore } = useApplication();
const {
@@ -22,7 +25,8 @@ export const RecentPagesList: FC = observer(() => {
} = useUser();
const { recentProjectPages } = useProjectPages();
- const EmptyStateImagePath = getEmptyStateImagePath("pages", "recent", currentUser?.theme.theme === "light");
+ const isLightMode = resolvedTheme ? resolvedTheme === "light" : currentUser?.theme.theme === "light";
+ const EmptyStateImagePath = getEmptyStateImagePath("pages", "recent", isLightMode);
// FIXME: replace any with proper type
const isEmpty = recentProjectPages && Object.values(recentProjectPages).every((value: any) => value.length === 0);
diff --git a/web/components/profile/profile-issues.tsx b/web/components/profile/profile-issues.tsx
index 4b3721103..81c9b141c 100644
--- a/web/components/profile/profile-issues.tsx
+++ b/web/components/profile/profile-issues.tsx
@@ -2,6 +2,7 @@ import React from "react";
import { useRouter } from "next/router";
import useSWR from "swr";
import { observer } from "mobx-react-lite";
+import { useTheme } from "next-themes";
// components
import { ProfileIssuesListLayout } from "components/issues/issue-layouts/list/roots/profile-issues-root";
import { ProfileIssuesKanBanLayout } from "components/issues/issue-layouts/kanban/roots/profile-issues-root";
@@ -27,6 +28,9 @@ export const ProfileIssuesPage = observer((props: IProfileIssuesPage) => {
workspaceSlug: string;
userId: string;
};
+ // theme
+ const { resolvedTheme } = useTheme();
+ // store hooks
const {
membership: { currentWorkspaceRole },
currentUser,
@@ -46,7 +50,8 @@ export const ProfileIssuesPage = observer((props: IProfileIssuesPage) => {
}
);
- const emptyStateImage = getEmptyStateImagePath("profile", type, currentUser?.theme.theme === "light");
+ const isLightMode = resolvedTheme ? resolvedTheme === "light" : currentUser?.theme.theme === "light";
+ const emptyStateImage = getEmptyStateImagePath("profile", type, isLightMode);
const activeLayout = issueFilters?.displayFilters?.layout || undefined;
diff --git a/web/components/project/card-list.tsx b/web/components/project/card-list.tsx
index ebb166f49..76e67e1b7 100644
--- a/web/components/project/card-list.tsx
+++ b/web/components/project/card-list.tsx
@@ -1,16 +1,17 @@
import { observer } from "mobx-react-lite";
+import { useTheme } from "next-themes";
// hooks
import { useApplication, useProject, useUser } from "hooks/store";
// components
import { ProjectCard } from "components/project";
import { Loader } from "@plane/ui";
import { EmptyState, getEmptyStateImagePath } from "components/empty-state";
-// icons
-import { Plus } from "lucide-react";
// constants
import { EUserWorkspaceRoles } from "constants/workspace";
export const ProjectCardList = observer(() => {
+ // theme
+ const { resolvedTheme } = useTheme();
// store hooks
const {
commandPalette: commandPaletteStore,
@@ -22,7 +23,8 @@ export const ProjectCardList = observer(() => {
} = useUser();
const { workspaceProjectIds, searchedProjects, getProjectById } = useProject();
- const emptyStateImage = getEmptyStateImagePath("onboarding", "projects", currentUser?.theme.theme === "light");
+ const isLightMode = resolvedTheme ? resolvedTheme === "light" : currentUser?.theme.theme === "light";
+ const emptyStateImage = getEmptyStateImagePath("onboarding", "projects", isLightMode);
const isEditingAllowed = !!currentWorkspaceRole && currentWorkspaceRole >= EUserWorkspaceRoles.MEMBER;
diff --git a/web/components/views/views-list.tsx b/web/components/views/views-list.tsx
index 6b3b3e45a..13ad10441 100644
--- a/web/components/views/views-list.tsx
+++ b/web/components/views/views-list.tsx
@@ -1,6 +1,7 @@
import { useState } from "react";
import { observer } from "mobx-react-lite";
import { Search } from "lucide-react";
+import { useTheme } from "next-themes";
// hooks
import { useApplication, useProjectView, useUser } from "hooks/store";
// components
@@ -14,6 +15,8 @@ import { EUserProjectRoles } from "constants/project";
export const ProjectViewsList = observer(() => {
// states
const [query, setQuery] = useState("");
+ // theme
+ const { resolvedTheme } = useTheme();
// store hooks
const {
commandPalette: { toggleCreateViewModal },
@@ -43,7 +46,8 @@ export const ProjectViewsList = observer(() => {
const viewsList = projectViewIds.map((viewId) => getViewById(viewId));
- const EmptyStateImagePath = getEmptyStateImagePath("onboarding", "views", currentUser?.theme.theme === "light");
+ const isLightMode = resolvedTheme ? resolvedTheme === "light" : currentUser?.theme.theme === "light";
+ const EmptyStateImagePath = getEmptyStateImagePath("onboarding", "views", isLightMode);
const filteredViewsList = viewsList.filter((v) => v?.name.toLowerCase().includes(query.toLowerCase()));
diff --git a/web/pages/[workspaceSlug]/analytics.tsx b/web/pages/[workspaceSlug]/analytics.tsx
index fcaef9f70..3d6d501f2 100644
--- a/web/pages/[workspaceSlug]/analytics.tsx
+++ b/web/pages/[workspaceSlug]/analytics.tsx
@@ -1,6 +1,7 @@
import React, { Fragment, ReactElement } from "react";
import { observer } from "mobx-react-lite";
import { Tab } from "@headlessui/react";
+import { useTheme } from "next-themes";
// hooks
import { useApplication, useProject, useUser } from "hooks/store";
// layouts
@@ -16,6 +17,8 @@ import { EUserWorkspaceRoles } from "constants/workspace";
import { NextPageWithLayout } from "lib/types";
const AnalyticsPage: NextPageWithLayout = observer(() => {
+ // theme
+ const { resolvedTheme } = useTheme();
// store hooks
const {
commandPalette: { toggleCreateProjectModal },
@@ -27,7 +30,8 @@ const AnalyticsPage: NextPageWithLayout = observer(() => {
} = useUser();
const { workspaceProjectIds } = useProject();
- const EmptyStateImagePath = getEmptyStateImagePath("onboarding", "analytics", currentUser?.theme.theme === "light");
+ const isLightMode = resolvedTheme ? resolvedTheme === "light" : currentUser?.theme.theme === "light";
+ const EmptyStateImagePath = getEmptyStateImagePath("onboarding", "analytics", isLightMode);
const isEditingAllowed = !!currentWorkspaceRole && currentWorkspaceRole >= EUserWorkspaceRoles.MEMBER;
return (
diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx
index c00777319..d0dbb3514 100644
--- a/web/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx
+++ b/web/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx
@@ -2,6 +2,7 @@ import { Fragment, useCallback, useState, ReactElement } from "react";
import { useRouter } from "next/router";
import { observer } from "mobx-react-lite";
import { Tab } from "@headlessui/react";
+import { useTheme } from "next-themes";
// hooks
import { useCycle, useUser } from "hooks/store";
import useLocalStorage from "hooks/use-local-storage";
@@ -22,6 +23,8 @@ import { EUserWorkspaceRoles } from "constants/workspace";
const ProjectCyclesPage: NextPageWithLayout = observer(() => {
const [createModal, setCreateModal] = useState(false);
+ // theme
+ const { resolvedTheme } = useTheme();
// store hooks
const {
membership: { currentProjectRole },
@@ -49,7 +52,9 @@ const ProjectCyclesPage: NextPageWithLayout = observer(() => {
},
[handleCurrentLayout, setCycleTab]
);
- const EmptyStateImagePath = getEmptyStateImagePath("onboarding", "cycles", currentUser?.theme.theme === "light");
+
+ const isLightMode = resolvedTheme ? resolvedTheme === "light" : currentUser?.theme.theme === "light";
+ const EmptyStateImagePath = getEmptyStateImagePath("onboarding", "cycles", isLightMode);
const totalCycles = currentProjectCycleIds?.length ?? 0;
diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/pages/index.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/pages/index.tsx
index 32299747f..10cda05e1 100644
--- a/web/pages/[workspaceSlug]/projects/[projectId]/pages/index.tsx
+++ b/web/pages/[workspaceSlug]/projects/[projectId]/pages/index.tsx
@@ -4,6 +4,7 @@ import dynamic from "next/dynamic";
import { Tab } from "@headlessui/react";
import useSWR from "swr";
import { observer } from "mobx-react-lite";
+import { useTheme } from "next-themes";
// hooks
import { useApplication, useUser } from "hooks/store";
import useLocalStorage from "hooks/use-local-storage";
@@ -48,7 +49,9 @@ const ProjectPagesPage: NextPageWithLayout = observer(() => {
const { workspaceSlug, projectId } = router.query;
// states
const [createUpdatePageModal, setCreateUpdatePageModal] = useState(false);
- // store
+ // theme
+ const { resolvedTheme } = useTheme();
+ // store hooks
const {
currentUser,
currentUserLoader,
@@ -94,7 +97,8 @@ const ProjectPagesPage: NextPageWithLayout = observer(() => {
}
};
- const EmptyStateImagePath = getEmptyStateImagePath("onboarding", "pages", currentUser?.theme.theme === "light");
+ const isLightMode = resolvedTheme ? resolvedTheme === "light" : currentUser?.theme.theme === "light";
+ const EmptyStateImagePath = getEmptyStateImagePath("onboarding", "pages", isLightMode);
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
From 4aa34f3eda1ddb2bade8eea33ca6e5bea3d4b25f Mon Sep 17 00:00:00 2001
From: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com>
Date: Tue, 30 Jan 2024 13:58:18 +0530
Subject: [PATCH 4/7] fix: create update cycle modal project id pre-load data
updated (#3502)
---
web/components/cycles/form.tsx | 19 ++++++++++++++++++-
web/components/cycles/modal.tsx | 31 +++++++++++++++++++++++++++----
2 files changed, 45 insertions(+), 5 deletions(-)
diff --git a/web/components/cycles/form.tsx b/web/components/cycles/form.tsx
index e648a158e..865cc68a1 100644
--- a/web/components/cycles/form.tsx
+++ b/web/components/cycles/form.tsx
@@ -1,3 +1,4 @@
+import { useEffect } from "react";
import { Controller, useForm } from "react-hook-form";
// components
import { DateDropdown, ProjectDropdown } from "components/dropdowns";
@@ -11,19 +12,28 @@ import { ICycle } from "@plane/types";
type Props = {
handleFormSubmit: (values: Partial) => Promise;
handleClose: () => void;
+ status: boolean;
projectId: string;
setActiveProject: (projectId: string) => void;
data?: ICycle | null;
};
+const defaultValues: Partial = {
+ name: "",
+ description: "",
+ start_date: null,
+ end_date: null,
+};
+
export const CycleForm: React.FC = (props) => {
- const { handleFormSubmit, handleClose, projectId, setActiveProject, data } = props;
+ const { handleFormSubmit, handleClose, status, projectId, setActiveProject, data } = props;
// form data
const {
formState: { errors, isSubmitting },
handleSubmit,
control,
watch,
+ reset,
} = useForm({
defaultValues: {
project: projectId,
@@ -34,6 +44,13 @@ export const CycleForm: React.FC = (props) => {
},
});
+ useEffect(() => {
+ reset({
+ ...defaultValues,
+ ...data,
+ });
+ }, [data, reset]);
+
const startDate = watch("start_date");
const endDate = watch("end_date");
diff --git a/web/components/cycles/modal.tsx b/web/components/cycles/modal.tsx
index fed6eefc2..8144feef7 100644
--- a/web/components/cycles/modal.tsx
+++ b/web/components/cycles/modal.tsx
@@ -1,9 +1,9 @@
-import React, { useState } from "react";
+import React, { useEffect, useState } from "react";
import { Dialog, Transition } from "@headlessui/react";
// services
import { CycleService } from "services/cycle.service";
// hooks
-import { useApplication, useCycle } from "hooks/store";
+import { useApplication, useCycle, useProject } from "hooks/store";
import useToast from "hooks/use-toast";
import useLocalStorage from "hooks/use-local-storage";
// components
@@ -25,11 +25,12 @@ const cycleService = new CycleService();
export const CycleCreateUpdateModal: React.FC = (props) => {
const { isOpen, handleClose, data, workspaceSlug, projectId } = props;
// states
- const [activeProject, setActiveProject] = useState(projectId);
+ const [activeProject, setActiveProject] = useState(null);
// store hooks
const {
eventTracker: { postHogEventTracker },
} = useApplication();
+ const { workspaceProjectIds } = useProject();
const { createCycle, updateCycleDetails } = useCycle();
// toast alert
const { setToastAlert } = useToast();
@@ -134,6 +135,27 @@ export const CycleCreateUpdateModal: React.FC = (props) => {
});
};
+ useEffect(() => {
+ // if modal is closed, reset active project to null
+ // and return to avoid activeProject being set to some other project
+ if (!isOpen) {
+ setActiveProject(null);
+ return;
+ }
+
+ // if data is present, set active project to the project of the
+ // issue. This has more priority than the project in the url.
+ if (data && data.project) {
+ setActiveProject(data.project);
+ return;
+ }
+
+ // if data is not present, set active project to the project
+ // in the url. This has the least priority.
+ if (workspaceProjectIds && workspaceProjectIds.length > 0 && !activeProject)
+ setActiveProject(projectId ?? workspaceProjectIds?.[0] ?? null);
+ }, [activeProject, data, projectId, workspaceProjectIds, isOpen]);
+
return (
@@ -173,7 +185,7 @@ export const IssueGanttSidebar: React.FC
= (props) => {
)}
)}
-
+
);
};
diff --git a/web/components/gantt-chart/types/index.ts b/web/components/gantt-chart/types/index.ts
index 9cab40f5c..1360f9f45 100644
--- a/web/components/gantt-chart/types/index.ts
+++ b/web/components/gantt-chart/types/index.ts
@@ -13,8 +13,8 @@ export interface IGanttBlock {
width: number;
};
sort_order: number;
- start_date: Date;
- target_date: Date;
+ start_date: Date | null;
+ target_date: Date | null;
}
export interface IBlockUpdateData {
diff --git a/web/components/gantt-chart/views/month-view.ts b/web/components/gantt-chart/views/month-view.ts
index fc145d69c..13d054da1 100644
--- a/web/components/gantt-chart/views/month-view.ts
+++ b/web/components/gantt-chart/views/month-view.ts
@@ -167,6 +167,8 @@ export const getMonthChartItemPositionWidthInMonth = (chartData: ChartDataType,
const { startDate } = chartData.data;
const { start_date: itemStartDate, target_date: itemTargetDate } = itemData;
+ if (!itemStartDate || !itemTargetDate) return null;
+
startDate.setHours(0, 0, 0, 0);
itemStartDate.setHours(0, 0, 0, 0);
itemTargetDate.setHours(0, 0, 0, 0);
diff --git a/web/components/issues/issue-layouts/gantt/base-gantt-root.tsx b/web/components/issues/issue-layouts/gantt/base-gantt-root.tsx
index 73802886e..601205b5c 100644
--- a/web/components/issues/issue-layouts/gantt/base-gantt-root.tsx
+++ b/web/components/issues/issue-layouts/gantt/base-gantt-root.tsx
@@ -13,11 +13,12 @@ import {
} from "components/gantt-chart";
// types
import { TIssue, TUnGroupedIssues } from "@plane/types";
-import { EUserProjectRoles } from "constants/project";
import { ICycleIssues, ICycleIssuesFilter } from "store/issue/cycle";
import { IModuleIssues, IModuleIssuesFilter } from "store/issue/module";
import { IProjectIssues, IProjectIssuesFilter } from "store/issue/project";
import { IProjectViewIssues, IProjectViewIssuesFilter } from "store/issue/project-views";
+// constants
+import { EUserProjectRoles } from "constants/project";
import { EIssueActions } from "../types";
interface IBaseGanttRoot {
@@ -76,12 +77,14 @@ export const BaseGanttRoot: React.FC
= observer((props: IBaseGan
viewId={viewId}
enableQuickIssueCreate
disableIssueCreation={!enableIssueCreation || !isAllowed}
+ showAllBlocks
/>
)}
enableBlockLeftResize={isAllowed}
enableBlockRightResize={isAllowed}
enableBlockMove={isAllowed}
enableReorder={appliedDisplayFilters?.order_by === "sort_order" && isAllowed}
+ showAllBlocks
/>
>
diff --git a/web/constants/fetch-keys.ts b/web/constants/fetch-keys.ts
index ec88c8c87..86386e968 100644
--- a/web/constants/fetch-keys.ts
+++ b/web/constants/fetch-keys.ts
@@ -13,7 +13,6 @@ const paramsToKey = (params: any) => {
start_date,
target_date,
sub_issue,
- start_target_date,
project,
layout,
subscriber,
@@ -28,7 +27,6 @@ const paramsToKey = (params: any) => {
let createdByKey = created_by ? created_by.split(",") : [];
let labelsKey = labels ? labels.split(",") : [];
let subscriberKey = subscriber ? subscriber.split(",") : [];
- const startTargetDate = start_target_date ? `${start_target_date}`.toUpperCase() : "FALSE";
const startDateKey = start_date ?? "";
const targetDateKey = target_date ?? "";
const type = params.type ? params.type.toUpperCase() : "NULL";
@@ -47,7 +45,7 @@ const paramsToKey = (params: any) => {
labelsKey = labelsKey.sort().join("_");
subscriberKey = subscriberKey.sort().join("_");
- return `${layoutKey}_${projectKey}_${stateGroupKey}_${stateKey}_${priorityKey}_${assigneesKey}_${mentionsKey}_${createdByKey}_${type}_${groupBy}_${orderBy}_${labelsKey}_${startDateKey}_${targetDateKey}_${sub_issue}_${startTargetDate}_${subscriberKey}`;
+ return `${layoutKey}_${projectKey}_${stateGroupKey}_${stateKey}_${priorityKey}_${assigneesKey}_${mentionsKey}_${createdByKey}_${type}_${groupBy}_${orderBy}_${labelsKey}_${startDateKey}_${targetDateKey}_${sub_issue}_${subscriberKey}`;
};
const myIssuesParamsToKey = (params: any) => {
diff --git a/web/helpers/issue.helper.ts b/web/helpers/issue.helper.ts
index cdaa85883..b0121320e 100644
--- a/web/helpers/issue.helper.ts
+++ b/web/helpers/issue.helper.ts
@@ -105,9 +105,6 @@ export const handleIssueQueryParamsByLayout = (
});
}
- // add start_target_date query param for the gantt_chart layout
- if (layout === "gantt_chart") queryParams.push("start_target_date");
-
return queryParams;
};
diff --git a/web/store/issue/archived/filter.store.ts b/web/store/issue/archived/filter.store.ts
index 9a9c91a37..d92453a30 100644
--- a/web/store/issue/archived/filter.store.ts
+++ b/web/store/issue/archived/filter.store.ts
@@ -89,7 +89,6 @@ export class ArchivedIssuesFilter extends IssueFilterHelperStore implements IArc
filteredParams
);
- if (userFilters?.displayFilters?.layout === "gantt_chart") filteredRouteParams.start_target_date = true;
if (userFilters?.displayFilters?.layout === "spreadsheet") filteredRouteParams.sub_issue = false;
return filteredRouteParams;
diff --git a/web/store/issue/cycle/filter.store.ts b/web/store/issue/cycle/filter.store.ts
index 27347536b..dd81cfc0e 100644
--- a/web/store/issue/cycle/filter.store.ts
+++ b/web/store/issue/cycle/filter.store.ts
@@ -90,7 +90,6 @@ export class CycleIssuesFilter extends IssueFilterHelperStore implements ICycleI
filteredParams
);
- if (userFilters?.displayFilters?.layout === "gantt_chart") filteredRouteParams.start_target_date = true;
if (userFilters?.displayFilters?.layout === "spreadsheet") filteredRouteParams.sub_issue = false;
return filteredRouteParams;
diff --git a/web/store/issue/draft/filter.store.ts b/web/store/issue/draft/filter.store.ts
index 7096040d5..8295c263d 100644
--- a/web/store/issue/draft/filter.store.ts
+++ b/web/store/issue/draft/filter.store.ts
@@ -89,7 +89,6 @@ export class DraftIssuesFilter extends IssueFilterHelperStore implements IDraftI
filteredParams
);
- if (userFilters?.displayFilters?.layout === "gantt_chart") filteredRouteParams.start_target_date = true;
if (userFilters?.displayFilters?.layout === "spreadsheet") filteredRouteParams.sub_issue = false;
return filteredRouteParams;
diff --git a/web/store/issue/helpers/issue-filter-helper.store.ts b/web/store/issue/helpers/issue-filter-helper.store.ts
index ac89c5018..6516b28fd 100644
--- a/web/store/issue/helpers/issue-filter-helper.store.ts
+++ b/web/store/issue/helpers/issue-filter-helper.store.ts
@@ -81,7 +81,6 @@ export class IssueFilterHelperStore implements IIssueFilterHelperStore {
// display filters
type: displayFilters?.type || undefined,
sub_issue: displayFilters?.sub_issue ?? true,
- start_target_date: displayFilters?.start_target_date ?? true,
};
const issueFiltersParams: Partial
> = {};
@@ -170,7 +169,6 @@ export class IssueFilterHelperStore implements IIssueFilterHelperStore {
type: filters?.type || null,
sub_issue: filters?.sub_issue || false,
show_empty_groups: filters?.show_empty_groups || false,
- start_target_date: filters?.start_target_date || false,
};
};
diff --git a/web/store/issue/module/filter.store.ts b/web/store/issue/module/filter.store.ts
index 3c309cecd..e92027235 100644
--- a/web/store/issue/module/filter.store.ts
+++ b/web/store/issue/module/filter.store.ts
@@ -90,7 +90,6 @@ export class ModuleIssuesFilter extends IssueFilterHelperStore implements IModul
filteredParams
);
- if (userFilters?.displayFilters?.layout === "gantt_chart") filteredRouteParams.start_target_date = true;
if (userFilters?.displayFilters?.layout === "spreadsheet") filteredRouteParams.sub_issue = false;
return filteredRouteParams;
diff --git a/web/store/issue/profile/filter.store.ts b/web/store/issue/profile/filter.store.ts
index a0f8028f8..563af5b01 100644
--- a/web/store/issue/profile/filter.store.ts
+++ b/web/store/issue/profile/filter.store.ts
@@ -93,7 +93,6 @@ export class ProfileIssuesFilter extends IssueFilterHelperStore implements IProf
filteredParams
);
- if (userFilters?.displayFilters?.layout === "gantt_chart") filteredRouteParams.start_target_date = true;
if (userFilters?.displayFilters?.layout === "spreadsheet") filteredRouteParams.sub_issue = false;
return filteredRouteParams;
diff --git a/web/store/issue/project-views/filter.store.ts b/web/store/issue/project-views/filter.store.ts
index e0dae761c..b3df3903b 100644
--- a/web/store/issue/project-views/filter.store.ts
+++ b/web/store/issue/project-views/filter.store.ts
@@ -90,7 +90,6 @@ export class ProjectViewIssuesFilter extends IssueFilterHelperStore implements I
filteredParams
);
- if (userFilters?.displayFilters?.layout === "gantt_chart") filteredRouteParams.start_target_date = true;
if (userFilters?.displayFilters?.layout === "spreadsheet") filteredRouteParams.sub_issue = false;
return filteredRouteParams;
diff --git a/web/store/issue/project/filter.store.ts b/web/store/issue/project/filter.store.ts
index 392b7203f..69393a320 100644
--- a/web/store/issue/project/filter.store.ts
+++ b/web/store/issue/project/filter.store.ts
@@ -89,7 +89,6 @@ export class ProjectIssuesFilter extends IssueFilterHelperStore implements IProj
filteredParams
);
- if (userFilters?.displayFilters?.layout === "gantt_chart") filteredRouteParams.start_target_date = true;
if (userFilters?.displayFilters?.layout === "spreadsheet") filteredRouteParams.sub_issue = false;
return filteredRouteParams;
diff --git a/web/store/issue/workspace/filter.store.ts b/web/store/issue/workspace/filter.store.ts
index 82fb75ce2..92cc33a64 100644
--- a/web/store/issue/workspace/filter.store.ts
+++ b/web/store/issue/workspace/filter.store.ts
@@ -99,7 +99,6 @@ export class WorkspaceIssuesFilter extends IssueFilterHelperStore implements IWo
filteredParams
);
- if (userFilters?.displayFilters?.layout === "gantt_chart") filteredRouteParams.start_target_date = true;
if (userFilters?.displayFilters?.layout === "spreadsheet") filteredRouteParams.sub_issue = false;
return filteredRouteParams;