diff --git a/web/core/components/dashboard/index.ts b/web/core/components/dashboard/index.ts
deleted file mode 100644
index e88b1c701d9..00000000000
--- a/web/core/components/dashboard/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from "./widgets";
-export * from "./project-empty-state";
diff --git a/web/core/components/dashboard/project-empty-state.tsx b/web/core/components/dashboard/project-empty-state.tsx
deleted file mode 100644
index eb06d21be00..00000000000
--- a/web/core/components/dashboard/project-empty-state.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-"use client";
-
-import { observer } from "mobx-react";
-import Image from "next/image";
-// ui
-import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
-import { Button } from "@plane/ui";
-// hooks
-import { useCommandPalette, useEventTracker, useUserPermissions } from "@/hooks/store";
-// assets
-import ProjectEmptyStateImage from "@/public/empty-state/onboarding/dashboard-light.webp";
-
-export const DashboardProjectEmptyState = observer(() => {
- // store hooks
- const { toggleCreateProjectModal } = useCommandPalette();
- const { setTrackElement } = useEventTracker();
- const { allowPermissions } = useUserPermissions();
-
- // derived values
- const canCreateProject = allowPermissions([EUserPermissions.ADMIN], EUserPermissionsLevel.WORKSPACE);
-
- return (
-
-
Overview of your projects, activity, and metrics
-
- Welcome to Plane, we are excited to have you here. Create your first project and track your work items, and this
- page will transform into a space that helps you progress. Admins will also see items which help their team
- progress.
-
-
- {canCreateProject && (
-
- {
- setTrackElement("Project empty state");
- toggleCreateProjectModal(true);
- }}
- >
- Build your first project
-
-
- )}
-
- );
-});
diff --git a/web/core/components/dashboard/widgets/assigned-issues.tsx b/web/core/components/dashboard/widgets/assigned-issues.tsx
deleted file mode 100644
index cc2b74314e1..00000000000
--- a/web/core/components/dashboard/widgets/assigned-issues.tsx
+++ /dev/null
@@ -1,165 +0,0 @@
-import { useEffect, useState } from "react";
-import { observer } from "mobx-react";
-import Link from "next/link";
-import { Tab } from "@headlessui/react";
-import { EDurationFilters, FILTERED_ISSUES_TABS_LIST, UNFILTERED_ISSUES_TABS_LIST } from "@plane/constants";
-import { TAssignedIssuesWidgetFilters, TAssignedIssuesWidgetResponse } from "@plane/types";
-// hooks
-import { Card } from "@plane/ui";
-import {
- DurationFilterDropdown,
- IssuesErrorState,
- TabsList,
- WidgetIssuesList,
- WidgetLoader,
- WidgetProps,
-} from "@/components/dashboard/widgets";
-import { getCustomDates, getRedirectionFilters, getTabKey } from "@/helpers/dashboard.helper";
-import { useDashboard } from "@/hooks/store";
-// components
-// helpers
-// types
-// constants
-
-const WIDGET_KEY = "assigned_issues";
-
-export const AssignedIssuesWidget: React.FC = observer((props) => {
- const { dashboardId, workspaceSlug } = props;
- // states
- const [fetching, setFetching] = useState(false);
- // store hooks
- const { fetchWidgetStats, getWidgetDetails, getWidgetStats, getWidgetStatsError, updateDashboardWidgetFilters } =
- useDashboard();
- // derived values
- const widgetDetails = getWidgetDetails(workspaceSlug, dashboardId, WIDGET_KEY);
- const widgetStats = getWidgetStats(workspaceSlug, dashboardId, WIDGET_KEY);
- const widgetStatsError = getWidgetStatsError(workspaceSlug, dashboardId, WIDGET_KEY);
- const selectedDurationFilter = widgetDetails?.widget_filters.duration ?? EDurationFilters.NONE;
- const selectedTab = getTabKey(selectedDurationFilter, widgetDetails?.widget_filters.tab);
- const selectedCustomDates = widgetDetails?.widget_filters.custom_dates ?? [];
-
- const handleUpdateFilters = async (filters: Partial) => {
- if (!widgetDetails) return;
-
- setFetching(true);
-
- await updateDashboardWidgetFilters(workspaceSlug, dashboardId, widgetDetails.id, {
- widgetKey: WIDGET_KEY,
- filters,
- });
-
- const filterDates = getCustomDates(
- filters.duration ?? selectedDurationFilter,
- filters.custom_dates ?? selectedCustomDates
- );
- fetchWidgetStats(workspaceSlug, dashboardId, {
- widget_key: WIDGET_KEY,
- issue_type: filters.tab ?? selectedTab,
- ...(filterDates.trim() !== "" ? { target_date: filterDates } : {}),
- expand: "issue_relation",
- }).finally(() => setFetching(false));
- };
-
- useEffect(() => {
- const filterDates = getCustomDates(selectedDurationFilter, selectedCustomDates);
-
- fetchWidgetStats(workspaceSlug, dashboardId, {
- widget_key: WIDGET_KEY,
- issue_type: selectedTab,
- ...(filterDates.trim() !== "" ? { target_date: filterDates } : {}),
- expand: "issue_relation",
- });
-
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, []);
-
- const filterParams = getRedirectionFilters(selectedTab);
- const tabsList = selectedDurationFilter === "none" ? UNFILTERED_ISSUES_TABS_LIST : FILTERED_ISSUES_TABS_LIST;
- const selectedTabIndex = tabsList.findIndex((tab) => tab.key === selectedTab);
-
- if ((!widgetDetails || !widgetStats) && !widgetStatsError) return ;
-
- return (
-
- {widgetStatsError ? (
-
- handleUpdateFilters({
- duration: EDurationFilters.NONE,
- tab: "pending",
- })
- }
- />
- ) : (
- widgetStats && (
- <>
-
-
- Assigned to you
-
- {
- if (val === "custom" && customDates) {
- handleUpdateFilters({
- duration: val,
- custom_dates: customDates,
- });
- return;
- }
-
- if (val === selectedDurationFilter) return;
-
- let newTab = selectedTab;
- // switch to pending tab if target date is changed to none
- if (val === "none" && selectedTab !== "completed") newTab = "pending";
- // switch to upcoming tab if target date is changed to other than none
- if (val !== "none" && selectedDurationFilter === "none" && selectedTab !== "completed")
- newTab = "upcoming";
-
- handleUpdateFilters({
- duration: val,
- tab: newTab,
- });
- }}
- />
-
- {
- const newSelectedTab = tabsList[i];
- handleUpdateFilters({ tab: newSelectedTab?.key ?? "completed" });
- }}
- className="h-full flex flex-col"
- >
-
-
- {tabsList.map((tab) => {
- if (tab.key !== selectedTab) return null;
-
- return (
-
-
-
- );
- })}
-
-
- >
- )
- )}
-
- );
-});
diff --git a/web/core/components/dashboard/widgets/created-issues.tsx b/web/core/components/dashboard/widgets/created-issues.tsx
deleted file mode 100644
index 47dc6c268eb..00000000000
--- a/web/core/components/dashboard/widgets/created-issues.tsx
+++ /dev/null
@@ -1,162 +0,0 @@
-import { useEffect, useState } from "react";
-import { observer } from "mobx-react";
-import Link from "next/link";
-import { Tab } from "@headlessui/react";
-import { EDurationFilters, FILTERED_ISSUES_TABS_LIST, UNFILTERED_ISSUES_TABS_LIST } from "@plane/constants";
-import { TCreatedIssuesWidgetFilters, TCreatedIssuesWidgetResponse } from "@plane/types";
-// hooks
-import { Card } from "@plane/ui";
-import {
- DurationFilterDropdown,
- IssuesErrorState,
- TabsList,
- WidgetIssuesList,
- WidgetLoader,
- WidgetProps,
-} from "@/components/dashboard/widgets";
-import { getCustomDates, getRedirectionFilters, getTabKey } from "@/helpers/dashboard.helper";
-import { useDashboard } from "@/hooks/store";
-// components
-// helpers
-// types
-// constants
-
-const WIDGET_KEY = "created_issues";
-
-export const CreatedIssuesWidget: React.FC = observer((props) => {
- const { dashboardId, workspaceSlug } = props;
- // states
- const [fetching, setFetching] = useState(false);
- // store hooks
- const { fetchWidgetStats, getWidgetDetails, getWidgetStats, getWidgetStatsError, updateDashboardWidgetFilters } =
- useDashboard();
- // derived values
- const widgetDetails = getWidgetDetails(workspaceSlug, dashboardId, WIDGET_KEY);
- const widgetStats = getWidgetStats(workspaceSlug, dashboardId, WIDGET_KEY);
- const widgetStatsError = getWidgetStatsError(workspaceSlug, dashboardId, WIDGET_KEY);
- const selectedDurationFilter = widgetDetails?.widget_filters.duration ?? EDurationFilters.NONE;
- const selectedTab = getTabKey(selectedDurationFilter, widgetDetails?.widget_filters.tab);
- const selectedCustomDates = widgetDetails?.widget_filters.custom_dates ?? [];
-
- const handleUpdateFilters = async (filters: Partial) => {
- if (!widgetDetails) return;
-
- setFetching(true);
-
- await updateDashboardWidgetFilters(workspaceSlug, dashboardId, widgetDetails.id, {
- widgetKey: WIDGET_KEY,
- filters,
- });
-
- const filterDates = getCustomDates(
- filters.duration ?? selectedDurationFilter,
- filters.custom_dates ?? selectedCustomDates
- );
- fetchWidgetStats(workspaceSlug, dashboardId, {
- widget_key: WIDGET_KEY,
- issue_type: filters.tab ?? selectedTab,
- ...(filterDates.trim() !== "" ? { target_date: filterDates } : {}),
- }).finally(() => setFetching(false));
- };
-
- useEffect(() => {
- const filterDates = getCustomDates(selectedDurationFilter, selectedCustomDates);
-
- fetchWidgetStats(workspaceSlug, dashboardId, {
- widget_key: WIDGET_KEY,
- issue_type: selectedTab,
- ...(filterDates.trim() !== "" ? { target_date: filterDates } : {}),
- });
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, []);
-
- const filterParams = getRedirectionFilters(selectedTab);
- const tabsList = selectedDurationFilter === "none" ? UNFILTERED_ISSUES_TABS_LIST : FILTERED_ISSUES_TABS_LIST;
- const selectedTabIndex = tabsList.findIndex((tab) => tab.key === selectedTab);
-
- if ((!widgetDetails || !widgetStats) && !widgetStatsError) return ;
-
- return (
-
- {widgetStatsError ? (
-
- handleUpdateFilters({
- duration: EDurationFilters.NONE,
- tab: "pending",
- })
- }
- />
- ) : (
- widgetStats && (
- <>
-
-
- Created by you
-
- {
- if (val === "custom" && customDates) {
- handleUpdateFilters({
- duration: val,
- custom_dates: customDates,
- });
- return;
- }
-
- if (val === selectedDurationFilter) return;
-
- let newTab = selectedTab;
- // switch to pending tab if target date is changed to none
- if (val === "none" && selectedTab !== "completed") newTab = "pending";
- // switch to upcoming tab if target date is changed to other than none
- if (val !== "none" && selectedDurationFilter === "none" && selectedTab !== "completed")
- newTab = "upcoming";
-
- handleUpdateFilters({
- duration: val,
- tab: newTab,
- });
- }}
- />
-
- {
- const newSelectedTab = tabsList[i];
- handleUpdateFilters({ tab: newSelectedTab.key ?? "completed" });
- }}
- className="h-full flex flex-col"
- >
-
-
- {tabsList.map((tab) => {
- if (tab.key !== selectedTab) return null;
-
- return (
-
-
-
- );
- })}
-
-
- >
- )
- )}
-
- );
-});
diff --git a/web/core/components/dashboard/widgets/dropdowns/duration-filter.tsx b/web/core/components/dashboard/widgets/dropdowns/duration-filter.tsx
deleted file mode 100644
index 2a897de82a9..00000000000
--- a/web/core/components/dashboard/widgets/dropdowns/duration-filter.tsx
+++ /dev/null
@@ -1,58 +0,0 @@
-"use client";
-
-import { useState } from "react";
-import { ChevronDown } from "lucide-react";
-// components
-import { DURATION_FILTER_OPTIONS, EDurationFilters } from "@plane/constants";
-import { CustomMenu } from "@plane/ui";
-import { DateFilterModal } from "@/components/core";
-// ui
-// helpers
-import { getDurationFilterDropdownLabel } from "@/helpers/dashboard.helper";
-// constants
-
-type Props = {
- customDates?: string[];
- onChange: (value: EDurationFilters, customDates?: string[]) => void;
- value: EDurationFilters;
-};
-
-export const DurationFilterDropdown: React.FC = (props) => {
- const { customDates, onChange, value } = props;
- // states
- const [isDateFilterModalOpen, setIsDateFilterModalOpen] = useState(false);
-
- return (
- <>
- setIsDateFilterModalOpen(false)}
- onSelect={(val) => onChange(EDurationFilters.CUSTOM, val)}
- title="Due date"
- />
-
- {getDurationFilterDropdownLabel(value, customDates ?? [])}
-
-
- }
- placement="bottom-end"
- closeOnSelect
- >
- {DURATION_FILTER_OPTIONS.map((option) => (
- {
- if (option.key === "custom") setIsDateFilterModalOpen(true);
- else onChange(option.key);
- }}
- >
- {option.label}
-
- ))}
-
- >
- );
-};
diff --git a/web/core/components/dashboard/widgets/dropdowns/index.ts b/web/core/components/dashboard/widgets/dropdowns/index.ts
deleted file mode 100644
index cff4cdb449c..00000000000
--- a/web/core/components/dashboard/widgets/dropdowns/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from "./duration-filter";
diff --git a/web/core/components/dashboard/widgets/empty-states/assigned-issues.tsx b/web/core/components/dashboard/widgets/empty-states/assigned-issues.tsx
deleted file mode 100644
index 169547846e4..00000000000
--- a/web/core/components/dashboard/widgets/empty-states/assigned-issues.tsx
+++ /dev/null
@@ -1,55 +0,0 @@
-import Image from "next/image";
-import { useTheme } from "next-themes";
-import { TIssuesListTypes } from "@plane/types";
-import CompletedIssuesDark from "@/public/empty-state/dashboard/dark/completed-issues.svg";
-import OverdueIssuesDark from "@/public/empty-state/dashboard/dark/overdue-issues.svg";
-import UpcomingIssuesDark from "@/public/empty-state/dashboard/dark/upcoming-issues.svg";
-import CompletedIssuesLight from "@/public/empty-state/dashboard/light/completed-issues.svg";
-import OverdueIssuesLight from "@/public/empty-state/dashboard/light/overdue-issues.svg";
-import UpcomingIssuesLight from "@/public/empty-state/dashboard/light/upcoming-issues.svg";
-
-export const ASSIGNED_ISSUES_EMPTY_STATES = {
- pending: {
- title: "Work items assigned to you that are pending\nwill show up here.",
- darkImage: UpcomingIssuesDark,
- lightImage: UpcomingIssuesLight,
- },
- upcoming: {
- title: "Upcoming work items assigned to\nyou will show up here.",
- darkImage: UpcomingIssuesDark,
- lightImage: UpcomingIssuesLight,
- },
- overdue: {
- title: "Work items assigned to you that are past\ntheir due date will show up here.",
- darkImage: OverdueIssuesDark,
- lightImage: OverdueIssuesLight,
- },
- completed: {
- title: "Work items assigned to you that you have\nmarked Completed will show up here.",
- darkImage: CompletedIssuesDark,
- lightImage: CompletedIssuesLight,
- },
-};
-type Props = {
- type: TIssuesListTypes;
-};
-
-export const AssignedIssuesEmptyState: React.FC = (props) => {
- const { type } = props;
- // next-themes
- const { resolvedTheme } = useTheme();
-
- const typeDetails = ASSIGNED_ISSUES_EMPTY_STATES[type];
-
- const image = resolvedTheme === "dark" ? typeDetails.darkImage : typeDetails.lightImage;
-
- // TODO: update empty state logic to use a general component
- return (
-
-
-
-
-
{typeDetails.title}
-
- );
-};
diff --git a/web/core/components/dashboard/widgets/empty-states/created-issues.tsx b/web/core/components/dashboard/widgets/empty-states/created-issues.tsx
deleted file mode 100644
index 49a96f1fb3b..00000000000
--- a/web/core/components/dashboard/widgets/empty-states/created-issues.tsx
+++ /dev/null
@@ -1,55 +0,0 @@
-import Image from "next/image";
-import { useTheme } from "next-themes";
-import { TIssuesListTypes } from "@plane/types";
-import CompletedIssuesDark from "@/public/empty-state/dashboard/dark/completed-issues.svg";
-import OverdueIssuesDark from "@/public/empty-state/dashboard/dark/overdue-issues.svg";
-import UpcomingIssuesDark from "@/public/empty-state/dashboard/dark/upcoming-issues.svg";
-import CompletedIssuesLight from "@/public/empty-state/dashboard/light/completed-issues.svg";
-import OverdueIssuesLight from "@/public/empty-state/dashboard/light/overdue-issues.svg";
-import UpcomingIssuesLight from "@/public/empty-state/dashboard/light/upcoming-issues.svg";
-
-export const CREATED_ISSUES_EMPTY_STATES = {
- pending: {
- title: "Work items created by you that are pending\nwill show up here.",
- darkImage: UpcomingIssuesDark,
- lightImage: UpcomingIssuesLight,
- },
- upcoming: {
- title: "Upcoming work items you created\nwill show up here.",
- darkImage: UpcomingIssuesDark,
- lightImage: UpcomingIssuesLight,
- },
- overdue: {
- title: "Work items created by you that are past their\ndue date will show up here.",
- darkImage: OverdueIssuesDark,
- lightImage: OverdueIssuesLight,
- },
- completed: {
- title: "Work items created by you that you have\nmarked completed will show up here.",
- darkImage: CompletedIssuesDark,
- lightImage: CompletedIssuesLight,
- },
-};
-
-type Props = {
- type: TIssuesListTypes;
-};
-
-export const CreatedIssuesEmptyState: React.FC = (props) => {
- const { type } = props;
- // next-themes
- const { resolvedTheme } = useTheme();
-
- const typeDetails = CREATED_ISSUES_EMPTY_STATES[type];
-
- const image = resolvedTheme === "dark" ? typeDetails.darkImage : typeDetails.lightImage;
-
- return (
-
-
-
-
-
{typeDetails.title}
-
- );
-};
diff --git a/web/core/components/dashboard/widgets/empty-states/index.ts b/web/core/components/dashboard/widgets/empty-states/index.ts
deleted file mode 100644
index 72ca1dbb2dc..00000000000
--- a/web/core/components/dashboard/widgets/empty-states/index.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export * from "./assigned-issues";
-export * from "./created-issues";
-export * from "./issues-by-priority";
-export * from "./issues-by-state-group";
-export * from "./recent-activity";
-export * from "./recent-collaborators";
diff --git a/web/core/components/dashboard/widgets/empty-states/issues-by-priority.tsx b/web/core/components/dashboard/widgets/empty-states/issues-by-priority.tsx
deleted file mode 100644
index 7f70d3bf303..00000000000
--- a/web/core/components/dashboard/widgets/empty-states/issues-by-priority.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import Image from "next/image";
-import { useTheme } from "next-themes";
-// assets
-import DarkImage from "@/public/empty-state/dashboard/dark/issues-by-priority.svg";
-import LightImage from "@/public/empty-state/dashboard/light/issues-by-priority.svg";
-
-export const IssuesByPriorityEmptyState = () => {
- // next-themes
- const { resolvedTheme } = useTheme();
-
- const image = resolvedTheme === "dark" ? DarkImage : LightImage;
-
- return (
-
-
-
-
-
- Work items assigned to you, broken down by
-
- priority will show up here.
-
-
- );
-};
diff --git a/web/core/components/dashboard/widgets/empty-states/issues-by-state-group.tsx b/web/core/components/dashboard/widgets/empty-states/issues-by-state-group.tsx
deleted file mode 100644
index 69d4761e5ec..00000000000
--- a/web/core/components/dashboard/widgets/empty-states/issues-by-state-group.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import Image from "next/image";
-import { useTheme } from "next-themes";
-// assets
-import DarkImage from "@/public/empty-state/dashboard/dark/issues-by-state-group.svg";
-import LightImage from "@/public/empty-state/dashboard/light/issues-by-state-group.svg";
-
-export const IssuesByStateGroupEmptyState = () => {
- // next-themes
- const { resolvedTheme } = useTheme();
-
- const image = resolvedTheme === "dark" ? DarkImage : LightImage;
-
- return (
-
-
-
-
-
- Work items assigned to you, broken down by state,
-
- will show up here.
-
-
- );
-};
diff --git a/web/core/components/dashboard/widgets/empty-states/recent-activity.tsx b/web/core/components/dashboard/widgets/empty-states/recent-activity.tsx
deleted file mode 100644
index f25f3992088..00000000000
--- a/web/core/components/dashboard/widgets/empty-states/recent-activity.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import Image from "next/image";
-import { useTheme } from "next-themes";
-// assets
-import DarkImage from "@/public/empty-state/dashboard/dark/recent-activity.svg";
-import LightImage from "@/public/empty-state/dashboard/light/recent-activity.svg";
-
-export const RecentActivityEmptyState = () => {
- // next-themes
- const { resolvedTheme } = useTheme();
-
- const image = resolvedTheme === "dark" ? DarkImage : LightImage;
-
- return (
-
-
-
-
-
- All your work items activities across
-
- projects will show up here.
-
-
- );
-};
diff --git a/web/core/components/dashboard/widgets/empty-states/recent-collaborators.tsx b/web/core/components/dashboard/widgets/empty-states/recent-collaborators.tsx
deleted file mode 100644
index d1a1200aa59..00000000000
--- a/web/core/components/dashboard/widgets/empty-states/recent-collaborators.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-import Image from "next/image";
-import { useTheme } from "next-themes";
-// assets
-import DarkImage1 from "@/public/empty-state/dashboard/dark/recent-collaborators-1.svg";
-import DarkImage2 from "@/public/empty-state/dashboard/dark/recent-collaborators-2.svg";
-import DarkImage3 from "@/public/empty-state/dashboard/dark/recent-collaborators-3.svg";
-import LightImage1 from "@/public/empty-state/dashboard/light/recent-collaborators-1.svg";
-import LightImage2 from "@/public/empty-state/dashboard/light/recent-collaborators-2.svg";
-import LightImage3 from "@/public/empty-state/dashboard/light/recent-collaborators-3.svg";
-
-export const RecentCollaboratorsEmptyState = () => {
- // next-themes
- const { resolvedTheme } = useTheme();
-
- const image1 = resolvedTheme === "dark" ? DarkImage1 : LightImage1;
- const image2 = resolvedTheme === "dark" ? DarkImage2 : LightImage2;
- const image3 = resolvedTheme === "dark" ? DarkImage3 : LightImage3;
-
- return (
-
-
- Compare your activities with the top
-
- seven in your project.
-
-
-
- );
-};
diff --git a/web/core/components/dashboard/widgets/error-states/index.ts b/web/core/components/dashboard/widgets/error-states/index.ts
deleted file mode 100644
index bd8854f3744..00000000000
--- a/web/core/components/dashboard/widgets/error-states/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from "./issues";
diff --git a/web/core/components/dashboard/widgets/error-states/issues.tsx b/web/core/components/dashboard/widgets/error-states/issues.tsx
deleted file mode 100644
index fb3e3550b44..00000000000
--- a/web/core/components/dashboard/widgets/error-states/issues.tsx
+++ /dev/null
@@ -1,34 +0,0 @@
-"use client";
-
-import { AlertTriangle, RefreshCcw } from "lucide-react";
-// ui
-import { Button } from "@plane/ui";
-
-type Props = {
- isRefreshing: boolean;
- onClick: () => void;
-};
-
-export const IssuesErrorState: React.FC = (props) => {
- const { isRefreshing, onClick } = props;
-
- return (
-
-
-
-
There was an error in fetching widget details
-
}
- className="mt-2 mx-auto"
- onClick={onClick}
- loading={isRefreshing}
- >
- {isRefreshing ? "Retrying" : "Retry"}
-
-
-
- );
-};
diff --git a/web/core/components/dashboard/widgets/index.ts b/web/core/components/dashboard/widgets/index.ts
deleted file mode 100644
index e622d708f71..00000000000
--- a/web/core/components/dashboard/widgets/index.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-export * from "./dropdowns";
-export * from "./empty-states";
-export * from "./error-states";
-export * from "./issue-panels";
-export * from "./loaders";
-export * from "./assigned-issues";
-export * from "./created-issues";
-export * from "./overview-stats";
-export * from "./recent-activity";
-export * from "./recent-collaborators";
-export * from "./recent-projects";
diff --git a/web/core/components/dashboard/widgets/issue-panels/index.ts b/web/core/components/dashboard/widgets/issue-panels/index.ts
deleted file mode 100644
index f5b7d53d49e..00000000000
--- a/web/core/components/dashboard/widgets/issue-panels/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export * from "./issue-list-item";
-export * from "./issues-list";
-export * from "./tabs-list";
diff --git a/web/core/components/dashboard/widgets/issue-panels/issue-list-item.tsx b/web/core/components/dashboard/widgets/issue-panels/issue-list-item.tsx
deleted file mode 100644
index 75471c6fd60..00000000000
--- a/web/core/components/dashboard/widgets/issue-panels/issue-list-item.tsx
+++ /dev/null
@@ -1,401 +0,0 @@
-"use client";
-
-import { isToday } from "date-fns/isToday";
-import { observer } from "mobx-react";
-// types
-import { TIssue, TWidgetIssue } from "@plane/types";
-// ui
-import { Avatar, AvatarGroup, ControlLink, PriorityIcon } from "@plane/ui";
-// helpers
-import { findTotalDaysInRange, getDate, renderFormattedDate } from "@/helpers/date-time.helper";
-import { getFileURL } from "@/helpers/file.helper";
-import { generateWorkItemLink } from "@/helpers/issue.helper";
-// hooks
-import { useIssueDetail, useMember, useProject } from "@/hooks/store";
-// plane web components
-import { IssueIdentifier } from "@/plane-web/components/issues";
-
-export type IssueListItemProps = {
- issueId: string;
- onClick: (issue: TIssue) => void;
- workspaceSlug: string;
-};
-
-export const AssignedUpcomingIssueListItem: React.FC = observer((props) => {
- const { issueId, onClick, workspaceSlug } = props;
- // store hooks
- const { getProjectById } = useProject();
- const {
- issue: { getIssueById },
- } = useIssueDetail();
- // derived values
- const issueDetails = getIssueById(issueId) as TWidgetIssue | undefined;
-
- if (!issueDetails || !issueDetails.project_id) return null;
-
- const projectDetails = getProjectById(issueDetails.project_id);
-
- const blockedByIssues = issueDetails.issue_relation?.filter((issue) => issue.relation_type === "blocked_by") ?? [];
-
- const blockedByIssueProjectDetails =
- blockedByIssues.length === 1 ? getProjectById(blockedByIssues[0]?.project_id ?? "") : null;
-
- const targetDate = getDate(issueDetails.target_date);
-
- const workItemLink = generateWorkItemLink({
- workspaceSlug,
- projectId: issueDetails?.project_id,
- issueId: issueDetails?.id,
- projectIdentifier: projectDetails?.identifier,
- sequenceId: issueDetails?.sequence_id,
- });
-
- return (
- onClick(issueDetails)}
- className="grid grid-cols-12 gap-1 rounded px-3 py-2 hover:bg-custom-background-80"
- >
-
- {projectDetails && (
-
- )}
-
{issueDetails.name}
-
-
-
- {targetDate ? (isToday(targetDate) ? "Today" : renderFormattedDate(targetDate)) : "-"}
-
-
- {blockedByIssues.length > 0
- ? blockedByIssues.length > 1
- ? `${blockedByIssues.length} blockers`
- : blockedByIssueProjectDetails && (
-
- )
- : "-"}
-
-
- );
-});
-
-export const AssignedOverdueIssueListItem: React.FC = observer((props) => {
- const { issueId, onClick, workspaceSlug } = props;
- // store hooks
- const { getProjectById } = useProject();
- const {
- issue: { getIssueById },
- } = useIssueDetail();
- // derived values
- const issueDetails = getIssueById(issueId) as TWidgetIssue | undefined;
-
- if (!issueDetails || !issueDetails.project_id) return null;
-
- const projectDetails = getProjectById(issueDetails.project_id);
- const blockedByIssues = issueDetails.issue_relation?.filter((issue) => issue.relation_type === "blocked_by") ?? [];
-
- const blockedByIssueProjectDetails =
- blockedByIssues.length === 1 ? getProjectById(blockedByIssues[0]?.project_id ?? "") : null;
-
- const dueBy = findTotalDaysInRange(getDate(issueDetails.target_date), new Date(), false) ?? 0;
-
- const workItemLink = generateWorkItemLink({
- workspaceSlug,
- projectId: issueDetails?.project_id,
- issueId: issueDetails?.id,
- projectIdentifier: projectDetails?.identifier,
- sequenceId: issueDetails?.sequence_id,
- });
-
- return (
- onClick(issueDetails)}
- className="grid grid-cols-12 gap-1 rounded px-3 py-2 hover:bg-custom-background-80"
- >
-
- {projectDetails && (
-
- )}
-
{issueDetails.name}
-
-
-
- {dueBy} {`day${dueBy > 1 ? "s" : ""}`}
-
-
- {blockedByIssues.length > 0
- ? blockedByIssues.length > 1
- ? `${blockedByIssues.length} blockers`
- : blockedByIssueProjectDetails && (
-
- )
- : "-"}
-
-
- );
-});
-
-export const AssignedCompletedIssueListItem: React.FC = observer((props) => {
- const { issueId, onClick, workspaceSlug } = props;
- // store hooks
- const {
- issue: { getIssueById },
- } = useIssueDetail();
- const { getProjectById } = useProject();
- // derived values
- const issueDetails = getIssueById(issueId);
-
- if (!issueDetails || !issueDetails.project_id) return null;
-
- const projectDetails = getProjectById(issueDetails.project_id);
-
- const workItemLink = generateWorkItemLink({
- workspaceSlug,
- projectId: issueDetails?.project_id,
- issueId: issueDetails?.id,
- projectIdentifier: projectDetails?.identifier,
- sequenceId: issueDetails?.sequence_id,
- });
-
- return (
- onClick(issueDetails)}
- className="grid grid-cols-12 gap-1 rounded px-3 py-2 hover:bg-custom-background-80"
- >
-
- {projectDetails && (
-
- )}
-
{issueDetails.name}
-
-
-
- );
-});
-
-export const CreatedUpcomingIssueListItem: React.FC = observer((props) => {
- const { issueId, onClick, workspaceSlug } = props;
- // store hooks
- const { getUserDetails } = useMember();
- const {
- issue: { getIssueById },
- } = useIssueDetail();
- const { getProjectById } = useProject();
- // derived values
- const issue = getIssueById(issueId);
-
- if (!issue || !issue.project_id) return null;
-
- const projectDetails = getProjectById(issue.project_id);
- const targetDate = getDate(issue.target_date);
-
- const workItemLink = generateWorkItemLink({
- workspaceSlug,
- projectId: issue?.project_id,
- issueId: issue?.id,
- projectIdentifier: projectDetails?.identifier,
- sequenceId: issue?.sequence_id,
- });
-
- return (
- onClick(issue)}
- className="grid grid-cols-12 gap-1 rounded px-3 py-2 hover:bg-custom-background-80"
- >
-
- {projectDetails && (
-
- )}
-
{issue.name}
-
-
-
- {targetDate ? (isToday(targetDate) ? "Today" : renderFormattedDate(targetDate)) : "-"}
-
-
- {issue.assignee_ids && issue.assignee_ids?.length > 0 ? (
-
- {issue.assignee_ids?.map((assigneeId) => {
- const userDetails = getUserDetails(assigneeId);
-
- if (!userDetails) return null;
-
- return (
-
- );
- })}
-
- ) : (
- "-"
- )}
-
-
- );
-});
-
-export const CreatedOverdueIssueListItem: React.FC = observer((props) => {
- const { issueId, onClick, workspaceSlug } = props;
- // store hooks
- const { getUserDetails } = useMember();
- const {
- issue: { getIssueById },
- } = useIssueDetail();
- const { getProjectById } = useProject();
- // derived values
- const issue = getIssueById(issueId);
-
- if (!issue || !issue.project_id) return null;
-
- const projectDetails = getProjectById(issue.project_id);
-
- const dueBy: number = findTotalDaysInRange(getDate(issue.target_date), new Date(), false) ?? 0;
-
- const workItemLink = generateWorkItemLink({
- workspaceSlug,
- projectId: issue?.project_id,
- issueId: issue?.id,
- projectIdentifier: projectDetails?.identifier,
- sequenceId: issue?.sequence_id,
- });
-
- return (
- onClick(issue)}
- className="grid grid-cols-12 gap-1 rounded px-3 py-2 hover:bg-custom-background-80"
- >
-
- {projectDetails && (
-
- )}
-
{issue.name}
-
-
-
- {dueBy} {`day${dueBy > 1 ? "s" : ""}`}
-
-
- {issue.assignee_ids.length > 0 ? (
-
- {issue.assignee_ids?.map((assigneeId) => {
- const userDetails = getUserDetails(assigneeId);
-
- if (!userDetails) return null;
-
- return (
-
- );
- })}
-
- ) : (
- "-"
- )}
-
-
- );
-});
-
-export const CreatedCompletedIssueListItem: React.FC = observer((props) => {
- const { issueId, onClick, workspaceSlug } = props;
- // store hooks
- const { getUserDetails } = useMember();
- const {
- issue: { getIssueById },
- } = useIssueDetail();
- const { getProjectById } = useProject();
- // derived values
- const issue = getIssueById(issueId);
-
- if (!issue || !issue.project_id) return null;
-
- const projectDetails = getProjectById(issue.project_id);
-
- const workItemLink = generateWorkItemLink({
- workspaceSlug,
- projectId: issue?.project_id,
- issueId: issue?.id,
- projectIdentifier: projectDetails?.identifier,
- sequenceId: issue?.sequence_id,
- });
-
- return (
- onClick(issue)}
- className="grid grid-cols-12 gap-1 rounded px-3 py-2 hover:bg-custom-background-80"
- >
-
- {projectDetails && (
-
- )}
-
{issue.name}
-
-
-
- {issue.assignee_ids.length > 0 ? (
-
- {issue.assignee_ids?.map((assigneeId) => {
- const userDetails = getUserDetails(assigneeId);
-
- if (!userDetails) return null;
-
- return (
-
- );
- })}
-
- ) : (
- "-"
- )}
-
-
- );
-});
diff --git a/web/core/components/dashboard/widgets/issue-panels/issues-list.tsx b/web/core/components/dashboard/widgets/issue-panels/issues-list.tsx
deleted file mode 100644
index 925e2ee9af8..00000000000
--- a/web/core/components/dashboard/widgets/issue-panels/issues-list.tsx
+++ /dev/null
@@ -1,134 +0,0 @@
-"use client";
-
-import Link from "next/link";
-import { TAssignedIssuesWidgetResponse, TCreatedIssuesWidgetResponse, TIssue, TIssuesListTypes } from "@plane/types";
-// hooks
-// components
-import { Loader, getButtonStyling } from "@plane/ui";
-import {
- AssignedCompletedIssueListItem,
- AssignedIssuesEmptyState,
- AssignedOverdueIssueListItem,
- AssignedUpcomingIssueListItem,
- CreatedCompletedIssueListItem,
- CreatedIssuesEmptyState,
- CreatedOverdueIssueListItem,
- CreatedUpcomingIssueListItem,
- IssueListItemProps,
-} from "@/components/dashboard/widgets";
-// ui
-// helpers
-import { cn } from "@/helpers/common.helper";
-import { getRedirectionFilters } from "@/helpers/dashboard.helper";
-// hooks
-import useIssuePeekOverviewRedirection from "@/hooks/use-issue-peek-overview-redirection";
-import { usePlatformOS } from "@/hooks/use-platform-os";
-
-export type WidgetIssuesListProps = {
- isLoading: boolean;
- tab: TIssuesListTypes;
- type: "assigned" | "created";
- widgetStats: TAssignedIssuesWidgetResponse | TCreatedIssuesWidgetResponse;
- workspaceSlug: string;
-};
-
-export const WidgetIssuesList: React.FC = (props) => {
- const { isLoading, tab, type, widgetStats, workspaceSlug } = props;
- // hooks
- const { isMobile } = usePlatformOS();
- const { handleRedirection } = useIssuePeekOverviewRedirection();
-
- // handlers
- const handleIssuePeekOverview = (issue: TIssue) => handleRedirection(workspaceSlug, issue, isMobile);
-
- const filterParams = getRedirectionFilters(tab);
-
- const ISSUE_LIST_ITEM: {
- [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,
- },
- };
-
- const issuesList = widgetStats.issues;
-
- return (
- <>
-
- {isLoading ? (
-
-
-
-
-
-
- ) : issuesList.length > 0 ? (
- <>
-
-
- Work items
-
- {widgetStats.count}
-
-
- Priority
- {["upcoming", "pending"].includes(tab) && Due date }
- {tab === "overdue" && Due by }
- {type === "assigned" && tab !== "completed" && Blocked by }
- {type === "created" && Assigned to }
-
-
- {issuesList.map((issue) => {
- const IssueListItem = ISSUE_LIST_ITEM[type][tab];
-
- if (!IssueListItem) return null;
-
- return (
-
- );
- })}
-
- >
- ) : (
-
- {type === "assigned" &&
}
- {type === "created" &&
}
-
- )}
-
- {!isLoading && issuesList.length > 0 && (
-
- View all work items
-
- )}
- >
- );
-};
diff --git a/web/core/components/dashboard/widgets/issue-panels/tabs-list.tsx b/web/core/components/dashboard/widgets/issue-panels/tabs-list.tsx
deleted file mode 100644
index 9df044c37b7..00000000000
--- a/web/core/components/dashboard/widgets/issue-panels/tabs-list.tsx
+++ /dev/null
@@ -1,61 +0,0 @@
-import { observer } from "mobx-react";
-import { Tab } from "@headlessui/react";
-// helpers
-import { EDurationFilters, FILTERED_ISSUES_TABS_LIST, UNFILTERED_ISSUES_TABS_LIST } from "@plane/constants";
-import { TIssuesListTypes } from "@plane/types";
-import { cn } from "@/helpers/common.helper";
-// types
-// constants
-
-type Props = {
- durationFilter: EDurationFilters;
- selectedTab: TIssuesListTypes;
-};
-
-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);
-
- return (
-
-
- {tabsList.map((tab) => (
-
- {tab.label}
-
- ))}
-
- );
-});
diff --git a/web/core/components/dashboard/widgets/loaders/assigned-issues.tsx b/web/core/components/dashboard/widgets/loaders/assigned-issues.tsx
deleted file mode 100644
index 8a78fedf1a4..00000000000
--- a/web/core/components/dashboard/widgets/loaders/assigned-issues.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-"use client";
-
-// ui
-import { Loader } from "@plane/ui";
-
-export const AssignedIssuesWidgetLoader = () => (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-);
diff --git a/web/core/components/dashboard/widgets/loaders/index.ts b/web/core/components/dashboard/widgets/loaders/index.ts
deleted file mode 100644
index ee5286f0fbf..00000000000
--- a/web/core/components/dashboard/widgets/loaders/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from "./loader";
diff --git a/web/core/components/dashboard/widgets/loaders/issues-by-priority.tsx b/web/core/components/dashboard/widgets/loaders/issues-by-priority.tsx
deleted file mode 100644
index c6f075b5806..00000000000
--- a/web/core/components/dashboard/widgets/loaders/issues-by-priority.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-"use client";
-
-// ui
-import { Loader } from "@plane/ui";
-
-export const IssuesByPriorityWidgetLoader = () => (
-
-
-
-
-
-
-
-
-
-
-);
diff --git a/web/core/components/dashboard/widgets/loaders/issues-by-state-group.tsx b/web/core/components/dashboard/widgets/loaders/issues-by-state-group.tsx
deleted file mode 100644
index 099323cce75..00000000000
--- a/web/core/components/dashboard/widgets/loaders/issues-by-state-group.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-"use client";
-
-import range from "lodash/range";
-// ui
-import { Loader } from "@plane/ui";
-
-export const IssuesByStateGroupWidgetLoader = () => (
-
-
-
-
-
- {range(5).map((index) => (
-
- ))}
-
-
-
-);
diff --git a/web/core/components/dashboard/widgets/loaders/loader.tsx b/web/core/components/dashboard/widgets/loaders/loader.tsx
deleted file mode 100644
index ae4038b38da..00000000000
--- a/web/core/components/dashboard/widgets/loaders/loader.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-// components
-import { TWidgetKeys } from "@plane/types";
-import { AssignedIssuesWidgetLoader } from "./assigned-issues";
-import { IssuesByPriorityWidgetLoader } from "./issues-by-priority";
-import { IssuesByStateGroupWidgetLoader } from "./issues-by-state-group";
-import { OverviewStatsWidgetLoader } from "./overview-stats";
-import { RecentActivityWidgetLoader } from "./recent-activity";
-import { RecentCollaboratorsWidgetLoader } from "./recent-collaborators";
-import { RecentProjectsWidgetLoader } from "./recent-projects";
-// types
-
-type Props = {
- widgetKey: TWidgetKeys;
-};
-
-export const WidgetLoader: React.FC = (props) => {
- const { widgetKey } = props;
-
- const loaders = {
- overview_stats: ,
- assigned_issues: ,
- created_issues: ,
- issues_by_state_groups: ,
- issues_by_priority: ,
- recent_activity: ,
- recent_projects: ,
- recent_collaborators: ,
- };
-
- return loaders[widgetKey];
-};
diff --git a/web/core/components/dashboard/widgets/loaders/overview-stats.tsx b/web/core/components/dashboard/widgets/loaders/overview-stats.tsx
deleted file mode 100644
index e780bb39966..00000000000
--- a/web/core/components/dashboard/widgets/loaders/overview-stats.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-"use client";
-
-import range from "lodash/range";
-// ui
-import { Loader } from "@plane/ui";
-
-export const OverviewStatsWidgetLoader = () => (
-
- {range(4).map((index) => (
-
-
-
-
- ))}
-
-);
diff --git a/web/core/components/dashboard/widgets/loaders/recent-activity.tsx b/web/core/components/dashboard/widgets/loaders/recent-activity.tsx
deleted file mode 100644
index 2df78a15af1..00000000000
--- a/web/core/components/dashboard/widgets/loaders/recent-activity.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-"use client";
-
-import range from "lodash/range";
-// ui
-import { Loader } from "@plane/ui";
-
-export const RecentActivityWidgetLoader = () => (
-
-
- {range(7).map((index) => (
-
- ))}
-
-);
diff --git a/web/core/components/dashboard/widgets/loaders/recent-collaborators.tsx b/web/core/components/dashboard/widgets/loaders/recent-collaborators.tsx
deleted file mode 100644
index 2dceaf1320a..00000000000
--- a/web/core/components/dashboard/widgets/loaders/recent-collaborators.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-"use client";
-
-import range from "lodash/range";
-// ui
-import { Loader } from "@plane/ui";
-
-export const RecentCollaboratorsWidgetLoader = () => (
- <>
- {range(8).map((index) => (
-
-
-
- ))}
- >
-);
diff --git a/web/core/components/dashboard/widgets/loaders/recent-projects.tsx b/web/core/components/dashboard/widgets/loaders/recent-projects.tsx
deleted file mode 100644
index 38bc7e29a01..00000000000
--- a/web/core/components/dashboard/widgets/loaders/recent-projects.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-"use client";
-
-import range from "lodash/range";
-// ui
-import { Loader } from "@plane/ui";
-
-export const RecentProjectsWidgetLoader = () => (
-
-
- {range(5).map((index) => (
-
- ))}
-
-);
diff --git a/web/core/components/dashboard/widgets/overview-stats.tsx b/web/core/components/dashboard/widgets/overview-stats.tsx
deleted file mode 100644
index 20421f33b49..00000000000
--- a/web/core/components/dashboard/widgets/overview-stats.tsx
+++ /dev/null
@@ -1,100 +0,0 @@
-import { useEffect } from "react";
-import { observer } from "mobx-react";
-import Link from "next/link";
-import { TOverviewStatsWidgetResponse } from "@plane/types";
-// hooks
-import { Card, ECardSpacing } from "@plane/ui";
-import { WidgetLoader } from "@/components/dashboard/widgets";
-import { cn } from "@/helpers/common.helper";
-import { renderFormattedPayloadDate } from "@/helpers/date-time.helper";
-import { useDashboard } from "@/hooks/store";
-// components
-// helpers
-// types
-
-export type WidgetProps = {
- dashboardId: string;
- workspaceSlug: string;
-};
-
-const WIDGET_KEY = "overview_stats";
-
-export const OverviewStatsWidget: React.FC = observer((props) => {
- const { dashboardId, workspaceSlug } = props;
- // store hooks
- const { fetchWidgetStats, getWidgetStats } = useDashboard();
- // derived values
- const widgetStats = getWidgetStats(workspaceSlug, dashboardId, WIDGET_KEY);
-
- const today = renderFormattedPayloadDate(new Date());
- const STATS_LIST = [
- {
- key: "assigned",
- title: "Work items assigned",
- count: widgetStats?.assigned_issues_count,
- link: `/${workspaceSlug}/workspace-views/assigned`,
- },
- {
- key: "overdue",
- title: "Work items overdue",
- count: widgetStats?.pending_issues_count,
- link: `/${workspaceSlug}/workspace-views/assigned/?state_group=backlog,unstarted,started&target_date=${today};before`,
- },
- {
- key: "created",
- title: "Work items created",
- count: widgetStats?.created_issues_count,
- link: `/${workspaceSlug}/workspace-views/created`,
- },
- {
- key: "completed",
- title: "Work items completed",
- count: widgetStats?.completed_issues_count,
- link: `/${workspaceSlug}/workspace-views/assigned?state_group=completed`,
- },
- ];
-
- useEffect(() => {
- fetchWidgetStats(workspaceSlug, dashboardId, {
- widget_key: WIDGET_KEY,
- });
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, []);
-
- if (!widgetStats) return ;
-
- return (
-
- {STATS_LIST.map((stat, index) => (
-
-
-
-
-
{stat.count}
-
{stat.title}
-
-
-
-
- ))}
-
- );
-});
diff --git a/web/core/components/dashboard/widgets/recent-activity.tsx b/web/core/components/dashboard/widgets/recent-activity.tsx
deleted file mode 100644
index 84ac985e10c..00000000000
--- a/web/core/components/dashboard/widgets/recent-activity.tsx
+++ /dev/null
@@ -1,109 +0,0 @@
-"use client";
-
-import { useEffect } from "react";
-import { observer } from "mobx-react";
-import Link from "next/link";
-import { History } from "lucide-react";
-// types
-import { TRecentActivityWidgetResponse } from "@plane/types";
-// components
-import { Card, Avatar, getButtonStyling } from "@plane/ui";
-import { ActivityIcon, ActivityMessage, IssueLink } from "@/components/core";
-import { RecentActivityEmptyState, WidgetLoader, WidgetProps } from "@/components/dashboard/widgets";
-// helpers
-import { cn } from "@/helpers/common.helper";
-import { calculateTimeAgo } from "@/helpers/date-time.helper";
-import { getFileURL } from "@/helpers/file.helper";
-// hooks
-import { useDashboard, useUser } from "@/hooks/store";
-
-const WIDGET_KEY = "recent_activity";
-
-export const RecentActivityWidget: React.FC = observer((props) => {
- const { dashboardId, workspaceSlug } = props;
- // store hooks
- const { data: currentUser } = useUser();
- // derived values
- const { fetchWidgetStats, getWidgetStats } = useDashboard();
- const widgetStats = getWidgetStats(workspaceSlug, dashboardId, WIDGET_KEY);
- const redirectionLink = `/${workspaceSlug}/profile/${currentUser?.id}/activity`;
-
- useEffect(() => {
- fetchWidgetStats(workspaceSlug, dashboardId, {
- widget_key: WIDGET_KEY,
- });
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, []);
-
- if (!widgetStats) return ;
-
- return (
-
-
- Your work item activities
-
- {widgetStats.length > 0 ? (
-
- {widgetStats.map((activity) => (
-
-
- {activity.field ? (
- activity.new_value === "restore" ? (
-
- ) : (
-
- )
- ) : activity.actor_detail.avatar_url && activity.actor_detail.avatar_url !== "" ? (
-
- ) : (
-
- {activity.actor_detail.is_bot
- ? activity.actor_detail.first_name.charAt(0)
- : activity.actor_detail.display_name.charAt(0)}
-
- )}
-
-
-
-
- {currentUser?.id === activity.actor_detail.id ? "You" : activity.actor_detail?.display_name}{" "}
-
- {activity.field ? (
-
- ) : (
-
- created
-
- )}
-
-
- {calculateTimeAgo(activity.created_at)}
-
-
-
- ))}
-
- View all
-
-
- ) : (
-
-
-
- )}
-
- );
-});
diff --git a/web/core/components/dashboard/widgets/recent-collaborators/collaborators-list.tsx b/web/core/components/dashboard/widgets/recent-collaborators/collaborators-list.tsx
deleted file mode 100644
index 415809e0433..00000000000
--- a/web/core/components/dashboard/widgets/recent-collaborators/collaborators-list.tsx
+++ /dev/null
@@ -1,154 +0,0 @@
-"use client";
-import { useState } from "react";
-import sortBy from "lodash/sortBy";
-import { observer } from "mobx-react";
-import Link from "next/link";
-import useSWR from "swr";
-// types
-import { TRecentCollaboratorsWidgetResponse } from "@plane/types";
-// ui
-import { Avatar } from "@plane/ui";
-// helpers
-import { getFileURL } from "@/helpers/file.helper";
-// hooks
-import { useDashboard, useMember, useUser } from "@/hooks/store";
-// components
-import { WidgetLoader } from "../loaders";
-
-type CollaboratorListItemProps = {
- issueCount: number;
- userId: string;
- workspaceSlug: string;
-};
-
-const CollaboratorListItem: React.FC = observer((props) => {
- const { issueCount, userId, workspaceSlug } = props;
- // store hooks
- const { data: currentUser } = useUser();
- const { getUserDetails } = useMember();
- // derived values
- const userDetails = getUserDetails(userId);
- const isCurrentUser = userId === currentUser?.id;
-
- if (!userDetails || userDetails.is_bot) return null;
-
- return (
-
-
-
- {isCurrentUser ? "You" : userDetails?.display_name}
-
-
- {issueCount} active work items{issueCount > 1 ? "s" : ""}
-
-
- );
-});
-
-type CollaboratorsListProps = {
- dashboardId: string;
- searchQuery?: string;
- workspaceSlug: string;
-};
-
-const WIDGET_KEY = "recent_collaborators";
-
-export const CollaboratorsList: React.FC = (props) => {
- const { dashboardId, searchQuery = "", workspaceSlug } = props;
-
- // state
- const [visibleItems, setVisibleItems] = useState(16);
- const [isExpanded, setIsExpanded] = useState(false);
- // store hooks
- const { fetchWidgetStats } = useDashboard();
- const { getUserDetails } = useMember();
- const { data: currentUser } = useUser();
-
- const { data: widgetStats } = useSWR(
- workspaceSlug && dashboardId ? `WIDGET_STATS_${workspaceSlug}_${dashboardId}` : null,
- workspaceSlug && dashboardId
- ? () =>
- fetchWidgetStats(workspaceSlug, dashboardId, {
- widget_key: WIDGET_KEY,
- })
- : null
- ) as {
- data: TRecentCollaboratorsWidgetResponse[] | undefined;
- };
-
- if (!widgetStats)
- return (
-
-
-
- );
-
- const sortedStats = sortBy(widgetStats, [(user) => user?.user_id !== currentUser?.id]);
-
- const filteredStats = sortedStats.filter((user) => {
- if (!user) return false;
- const userDetails = getUserDetails(user?.user_id);
- if (!userDetails || userDetails.is_bot) return false;
- const { display_name, first_name, last_name } = userDetails;
- const searchLower = searchQuery.toLowerCase();
- return (
- display_name?.toLowerCase().includes(searchLower) ||
- first_name?.toLowerCase().includes(searchLower) ||
- last_name?.toLowerCase().includes(searchLower)
- );
- });
-
- // Update the displayedStats to always use the visibleItems limit
- const handleLoadMore = () => {
- setVisibleItems((prev) => {
- const newValue = prev + 16;
- if (newValue >= filteredStats.length) {
- setIsExpanded(true);
- return filteredStats.length;
- }
- return newValue;
- });
- };
-
- const handleHide = () => {
- setVisibleItems(16);
- setIsExpanded(false);
- };
-
- const displayedStats = filteredStats.slice(0, visibleItems);
-
- return (
- <>
-
- {displayedStats?.map((user) => (
-
- ))}
-
- {filteredStats.length > visibleItems && !isExpanded && (
-
- )}
- {isExpanded && (
-
- )}
- >
- );
-};
diff --git a/web/core/components/dashboard/widgets/recent-collaborators/index.ts b/web/core/components/dashboard/widgets/recent-collaborators/index.ts
deleted file mode 100644
index 1efe34c51ec..00000000000
--- a/web/core/components/dashboard/widgets/recent-collaborators/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from "./root";
diff --git a/web/core/components/dashboard/widgets/recent-collaborators/root.tsx b/web/core/components/dashboard/widgets/recent-collaborators/root.tsx
deleted file mode 100644
index 4d30642071b..00000000000
--- a/web/core/components/dashboard/widgets/recent-collaborators/root.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-import { useState } from "react";
-import { Search } from "lucide-react";
-// types
-import { Card } from "@plane/ui";
-import { WidgetProps } from "@/components/dashboard/widgets";
-// components
-import { CollaboratorsList } from "./collaborators-list";
-
-export const RecentCollaboratorsWidget: React.FC = (props) => {
- const { dashboardId, workspaceSlug } = props;
- // states
- const [searchQuery, setSearchQuery] = useState("");
-
- return (
-
-
-
-
Collaborators
-
- View and find all members you collaborate with across projects
-
-
-
-
- setSearchQuery(e.target.value)}
- />
-
-
-
-
- );
-};
diff --git a/web/core/components/dashboard/widgets/recent-projects.tsx b/web/core/components/dashboard/widgets/recent-projects.tsx
deleted file mode 100644
index 3e9c4e257b9..00000000000
--- a/web/core/components/dashboard/widgets/recent-projects.tsx
+++ /dev/null
@@ -1,134 +0,0 @@
-"use client";
-
-import { useEffect } from "react";
-import { observer } from "mobx-react";
-import Link from "next/link";
-import { Plus } from "lucide-react";
-// plane types
-import { PROJECT_BACKGROUND_COLORS, EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
-import { TRecentProjectsWidgetResponse } from "@plane/types";
-// plane ui
-import { Avatar, AvatarGroup, Card } from "@plane/ui";
-// components
-import { Logo } from "@/components/common";
-import { WidgetLoader, WidgetProps } from "@/components/dashboard/widgets";
-// constants
-// helpers
-import { getFileURL } from "@/helpers/file.helper";
-// hooks
-import {
- useEventTracker,
- useDashboard,
- useProject,
- useCommandPalette,
- useUserPermissions,
- useMember,
-} from "@/hooks/store";
-// plane web constants
-
-const WIDGET_KEY = "recent_projects";
-
-type ProjectListItemProps = {
- projectId: string;
- workspaceSlug: string;
-};
-
-const ProjectListItem: React.FC = observer((props) => {
- const { projectId, workspaceSlug } = props;
- // store hooks
- const { getProjectById } = useProject();
- const { getUserDetails } = useMember();
- // derived values
- const projectDetails = getProjectById(projectId);
-
- const randomBgColor = PROJECT_BACKGROUND_COLORS[Math.floor(Math.random() * PROJECT_BACKGROUND_COLORS.length)];
-
- if (!projectDetails) return null;
-
- return (
-
-
-
-
- {projectDetails.name}
-
-
-
- {projectDetails.members?.map((memberId) => {
- const userDetails = getUserDetails(memberId);
- if (!userDetails) return null;
- return (
-
- );
- })}
-
-
-
-
- );
-});
-
-export const RecentProjectsWidget: React.FC = observer((props) => {
- const { dashboardId, workspaceSlug } = props;
- // store hooks
- const { toggleCreateProjectModal } = useCommandPalette();
- const { setTrackElement } = useEventTracker();
- const { allowPermissions } = useUserPermissions();
- const { fetchWidgetStats, getWidgetStats } = useDashboard();
- // derived values
- const widgetStats = getWidgetStats(workspaceSlug, dashboardId, WIDGET_KEY);
- const canCreateProject = allowPermissions(
- [EUserPermissions.ADMIN, EUserPermissions.MEMBER],
- EUserPermissionsLevel.WORKSPACE
- );
-
- useEffect(() => {
- fetchWidgetStats(workspaceSlug, dashboardId, {
- widget_key: WIDGET_KEY,
- });
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, []);
-
- if (!widgetStats) return ;
-
- return (
-
-
- Recent projects
-
-
- {canCreateProject && (
-
{
- e.preventDefault();
- e.stopPropagation();
- setTrackElement("Sidebar");
- toggleCreateProjectModal(true);
- }}
- >
-
-
- Create new project
-
-
- )}
- {widgetStats.map((projectId) => (
-
- ))}
-
-
- );
-});
diff --git a/web/core/constants/fetch-keys.ts b/web/core/constants/fetch-keys.ts
index d5bbf3ed65c..f0c9551a440 100644
--- a/web/core/constants/fetch-keys.ts
+++ b/web/core/constants/fetch-keys.ts
@@ -47,105 +47,19 @@ const paramsToKey = (params: any) => {
return `${layoutKey}_${projectKey}_${stateGroupKey}_${stateKey}_${priorityKey}_${assigneesKey}_${mentionsKey}_${createdByKey}_${type}_${groupBy}_${orderBy}_${labelsKey}_${startDateKey}_${targetDateKey}_${sub_issue}_${subscriberKey}`;
};
-const myIssuesParamsToKey = (params: any) => {
- const { assignees, created_by, labels, priority, state_group, subscriber, start_date, target_date } = params;
-
- let assigneesKey = assignees ? assignees.split(",") : [];
- let createdByKey = created_by ? created_by.split(",") : [];
- let stateGroupKey = state_group ? state_group.split(",") : [];
- let subscriberKey = subscriber ? subscriber.split(",") : [];
- let priorityKey = priority ? priority.split(",") : [];
- let labelsKey = labels ? labels.split(",") : [];
- const startDateKey = start_date ?? "";
- const targetDateKey = target_date ?? "";
- const type = params?.type ? params.type.toUpperCase() : "NULL";
- const groupBy = params?.group_by ? params.group_by.toUpperCase() : "NULL";
- const orderBy = params?.order_by ? params.order_by.toUpperCase() : "NULL";
-
- // sorting each keys in ascending order
- assigneesKey = assigneesKey.sort().join("_");
- createdByKey = createdByKey.sort().join("_");
- stateGroupKey = stateGroupKey.sort().join("_");
- subscriberKey = subscriberKey.sort().join("_");
- priorityKey = priorityKey.sort().join("_");
- labelsKey = labelsKey.sort().join("_");
-
- return `${assigneesKey}_${createdByKey}_${stateGroupKey}_${subscriberKey}_${priorityKey}_${type}_${groupBy}_${orderBy}_${labelsKey}_${startDateKey}_${targetDateKey}`;
-};
-
-export const CURRENT_USER = "CURRENT_USER";
-export const USER_WORKSPACE_INVITATIONS = "USER_WORKSPACE_INVITATIONS";
export const USER_WORKSPACES_LIST = "USER_WORKSPACES_LIST";
-export const WORKSPACE_DETAILS = (workspaceSlug: string) => `WORKSPACE_DETAILS_${workspaceSlug.toUpperCase()}`;
-
export const WORKSPACE_MEMBERS = (workspaceSlug: string) => `WORKSPACE_MEMBERS_${workspaceSlug.toUpperCase()}`;
-export const WORKSPACE_MEMBERS_ME = (workspaceSlug: string) => `WORKSPACE_MEMBERS_ME${workspaceSlug.toUpperCase()}`;
-export const WORKSPACE_INVITATIONS = (workspaceSlug: string) => `WORKSPACE_INVITATIONS_${workspaceSlug.toString()}`;
-export const WORKSPACE_INVITATION = (invitationId: string) => `WORKSPACE_INVITATION_${invitationId}`;
-export const LAST_ACTIVE_WORKSPACE_AND_PROJECTS = "LAST_ACTIVE_WORKSPACE_AND_PROJECTS";
-export const PROJECTS_LIST = (
- workspaceSlug: string,
- params: {
- is_favorite: "all" | boolean;
- }
-) => {
- if (!params) return `PROJECTS_LIST_${workspaceSlug.toUpperCase()}`;
+export const WORKSPACE_INVITATION = (invitationId: string) => `WORKSPACE_INVITATION_${invitationId}`;
- return `PROJECTS_LIST_${workspaceSlug.toUpperCase()}_${params.is_favorite.toString().toUpperCase()}`;
-};
export const PROJECT_DETAILS = (projectId: string) => `PROJECT_DETAILS_${projectId.toUpperCase()}`;
export const PROJECT_MEMBERS = (projectId: string) => `PROJECT_MEMBERS_${projectId.toUpperCase()}`;
-export const PROJECT_INVITATIONS = (projectId: string) => `PROJECT_INVITATIONS_${projectId.toString()}`;
-
-export const PROJECT_ISSUES_LIST = (workspaceSlug: string, projectId: string) =>
- `PROJECT_ISSUES_LIST_${workspaceSlug.toUpperCase()}_${projectId.toUpperCase()}`;
-export const PROJECT_ISSUES_LIST_WITH_PARAMS = (projectId: string, params?: any) => {
- if (!params) return `PROJECT_ISSUES_LIST_WITH_PARAMS_${projectId.toUpperCase()}`;
-
- const paramsKey = paramsToKey(params);
- return `PROJECT_ISSUES_LIST_WITH_PARAMS_${projectId.toUpperCase()}_${paramsKey}`;
-};
-export const PROJECT_ARCHIVED_ISSUES_LIST_WITH_PARAMS = (projectId: string, params?: any) => {
- if (!params) return `PROJECT_ARCHIVED_ISSUES_LIST_WITH_PARAMS_${projectId.toUpperCase()}`;
-
- const paramsKey = paramsToKey(params);
-
- return `PROJECT_ARCHIVED_ISSUES_LIST_WITH_PARAMS_${projectId.toUpperCase()}_${paramsKey}`;
-};
-
-export const PROJECT_DRAFT_ISSUES_LIST_WITH_PARAMS = (projectId: string, params?: any) => {
- if (!params) return `PROJECT_DRAFT_ISSUES_LIST_WITH_PARAMS${projectId.toUpperCase()}`;
-
- const paramsKey = paramsToKey(params);
-
- return `PROJECT_DRAFT_ISSUES_LIST_WITH_PARAMS${projectId.toUpperCase()}_${paramsKey}`;
-};
-
-export const GLOBAL_VIEWS_LIST = (workspaceSlug: string) => `GLOBAL_VIEWS_LIST_${workspaceSlug.toUpperCase()}`;
-export const GLOBAL_VIEW_DETAILS = (globalViewId: string) => `GLOBAL_VIEW_DETAILS_${globalViewId.toUpperCase()}`;
-export const GLOBAL_VIEW_ISSUES = (globalViewId: string) => `GLOBAL_VIEW_ISSUES_${globalViewId.toUpperCase()}`;
-
-export const PROJECT_ISSUES_DETAILS = (issueId: string) => `PROJECT_ISSUES_DETAILS_${issueId.toUpperCase()}`;
-export const PROJECT_ISSUES_PROPERTIES = (projectId: string) => `PROJECT_ISSUES_PROPERTIES_${projectId.toUpperCase()}`;
-export const PROJECT_ISSUES_COMMENTS = (issueId: string) => `PROJECT_ISSUES_COMMENTS_${issueId.toUpperCase()}`;
-export const PROJECT_ISSUES_ACTIVITY = (issueId: string) => `PROJECT_ISSUES_ACTIVITY_${issueId.toUpperCase()}`;
-export const PROJECT_ISSUE_BY_STATE = (projectId: string) => `PROJECT_ISSUE_BY_STATE_${projectId.toUpperCase()}`;
-export const PROJECT_ISSUE_LABELS = (projectId: string) => `PROJECT_ISSUE_LABELS_${projectId.toUpperCase()}`;
-export const WORKSPACE_LABELS = (workspaceSlug: string) => `WORKSPACE_LABELS_${workspaceSlug.toUpperCase()}`;
export const PROJECT_GITHUB_REPOSITORY = (projectId: string) => `PROJECT_GITHUB_REPOSITORY_${projectId.toUpperCase()}`;
// cycles
-export const CYCLES_LIST = (projectId: string) => `CYCLE_LIST_${projectId.toUpperCase()}`;
-export const INCOMPLETE_CYCLES_LIST = (projectId: string) => `INCOMPLETE_CYCLES_LIST_${projectId.toUpperCase()}`;
-export const CURRENT_CYCLE_LIST = (projectId: string) => `CURRENT_CYCLE_LIST_${projectId.toUpperCase()}`;
-export const UPCOMING_CYCLES_LIST = (projectId: string) => `UPCOMING_CYCLES_LIST_${projectId.toUpperCase()}`;
-export const DRAFT_CYCLES_LIST = (projectId: string) => `DRAFT_CYCLES_LIST_${projectId.toUpperCase()}`;
-export const COMPLETED_CYCLES_LIST = (projectId: string) => `COMPLETED_CYCLES_LIST_${projectId.toUpperCase()}`;
-export const CYCLE_ISSUES = (cycleId: string) => `CYCLE_ISSUES_${cycleId.toUpperCase()}`;
export const CYCLE_ISSUES_WITH_PARAMS = (cycleId: string, params?: any) => {
if (!params) return `CYCLE_ISSUES_WITH_PARAMS_${cycleId.toUpperCase()}`;
@@ -153,47 +67,11 @@ export const CYCLE_ISSUES_WITH_PARAMS = (cycleId: string, params?: any) => {
return `CYCLE_ISSUES_WITH_PARAMS_${cycleId.toUpperCase()}_${paramsKey.toUpperCase()}`;
};
-export const CYCLE_DETAILS = (cycleId: string) => `CYCLE_DETAILS_${cycleId.toUpperCase()}`;
-export const STATES_LIST = (projectId: string) => `STATES_LIST_${projectId.toUpperCase()}`;
-
-export const USER_ISSUE = (workspaceSlug: string) => `USER_ISSUE_${workspaceSlug.toUpperCase()}`;
-export const USER_ISSUES = (workspaceSlug: string, params: any) => {
- const paramsKey = myIssuesParamsToKey(params);
-
- return `USER_ISSUES_${workspaceSlug.toUpperCase()}_${paramsKey}`;
-};
export const USER_ACTIVITY = (params: { cursor?: string }) => `USER_ACTIVITY_${params?.cursor}`;
-export const USER_WORKSPACE_DASHBOARD = (workspaceSlug: string) =>
- `USER_WORKSPACE_DASHBOARD_${workspaceSlug.toUpperCase()}`;
-export const USER_PROJECT_VIEW = (projectId: string) => `USER_PROJECT_VIEW_${projectId.toUpperCase()}`;
-
-export const MODULE_LIST = (projectId: string) => `MODULE_LIST_${projectId.toUpperCase()}`;
-export const MODULE_ISSUES = (moduleId: string) => `MODULE_ISSUES_${moduleId.toUpperCase()}`;
-export const MODULE_ISSUES_WITH_PARAMS = (moduleId: string, params?: any) => {
- if (!params) return `MODULE_ISSUES_WITH_PARAMS_${moduleId.toUpperCase()}`;
-
- const paramsKey = paramsToKey(params);
-
- return `MODULE_ISSUES_WITH_PARAMS_${moduleId.toUpperCase()}_${paramsKey.toUpperCase()}`;
-};
-export const MODULE_DETAILS = (moduleId: string) => `MODULE_DETAILS_${moduleId.toUpperCase()}`;
-
-export const VIEWS_LIST = (projectId: string) => `VIEWS_LIST_${projectId.toUpperCase()}`;
-export const VIEW_DETAILS = (viewId: string) => `VIEW_DETAILS_${viewId.toUpperCase()}`;
-export const VIEW_ISSUES = (viewId: string, params: any) => {
- if (!params) return `VIEW_ISSUES_${viewId.toUpperCase()}`;
-
- const paramsKey = paramsToKey(params);
-
- return `VIEW_ISSUES_${viewId.toUpperCase()}_${paramsKey.toUpperCase()}`;
-};
// Issues
export const ISSUE_DETAILS = (issueId: string) => `ISSUE_DETAILS_${issueId.toUpperCase()}`;
-export const SUB_ISSUES = (issueId: string) => `SUB_ISSUES_${issueId.toUpperCase()}`;
-export const ISSUE_ATTACHMENTS = (issueId: string) => `ISSUE_ATTACHMENTS_${issueId.toUpperCase()}`;
-export const ARCHIVED_ISSUE_DETAILS = (issueId: string) => `ARCHIVED_ISSUE_DETAILS_${issueId.toUpperCase()}`;
// integrations
export const APP_INTEGRATIONS = "APP_INTEGRATIONS";
@@ -222,21 +100,6 @@ export const GITHUB_REPOSITORY_INFO = (workspaceSlug: string, repoName: string)
export const SLACK_CHANNEL_INFO = (workspaceSlug: string, projectId: string) =>
`SLACK_CHANNEL_INFO_${workspaceSlug.toString().toUpperCase()}_${projectId.toUpperCase()}`;
-// Pages
-export const RECENT_PAGES_LIST = (projectId: string) => `RECENT_PAGES_LIST_${projectId.toUpperCase()}`;
-export const ALL_PAGES_LIST = (projectId: string) => `ALL_PAGES_LIST_${projectId.toUpperCase()}`;
-export const ARCHIVED_PAGES_LIST = (projectId: string) => `ARCHIVED_PAGES_LIST_${projectId.toUpperCase}`;
-export const FAVORITE_PAGES_LIST = (projectId: string) => `FAVORITE_PAGES_LIST_${projectId.toUpperCase()}`;
-export const PRIVATE_PAGES_LIST = (projectId: string) => `PRIVATE_PAGES_LIST_${projectId.toUpperCase()}`;
-export const SHARED_PAGES_LIST = (projectId: string) => `SHARED_PAGES_LIST_${projectId.toUpperCase()}`;
-export const PAGE_DETAILS = (pageId: string) => `PAGE_DETAILS_${pageId.toUpperCase()}`;
-export const PAGE_BLOCKS_LIST = (pageId: string) => `PAGE_BLOCK_LIST_${pageId.toUpperCase()}`;
-export const PAGE_BLOCK_DETAILS = (pageId: string) => `PAGE_BLOCK_DETAILS_${pageId.toUpperCase()}`;
-export const MY_PAGES_LIST = (pageId: string) => `MY_PAGE_LIST_${pageId}`;
-// estimates
-export const ESTIMATES_LIST = (projectId: string) => `ESTIMATES_LIST_${projectId.toUpperCase()}`;
-export const ESTIMATE_DETAILS = (estimateId: string) => `ESTIMATE_DETAILS_${estimateId.toUpperCase()}`;
-
// profile
export const USER_PROFILE_DATA = (workspaceSlug: string, userId: string) =>
`USER_PROFILE_ACTIVITY_${workspaceSlug.toUpperCase()}_${userId.toUpperCase()}`;
@@ -249,19 +112,6 @@ export const USER_PROFILE_ACTIVITY = (
) => `USER_WORKSPACE_PROFILE_ACTIVITY_${workspaceSlug.toUpperCase()}_${userId.toUpperCase()}_${params?.cursor}`;
export const USER_PROFILE_PROJECT_SEGREGATION = (workspaceSlug: string, userId: string) =>
`USER_PROFILE_PROJECT_SEGREGATION_${workspaceSlug.toUpperCase()}_${userId.toUpperCase()}`;
-export const USER_PROFILE_ISSUES = (workspaceSlug: string, userId: string, params: any) => {
- const paramsKey = myIssuesParamsToKey(params);
-
- return `USER_PROFILE_ISSUES_${workspaceSlug.toUpperCase()}_${userId.toUpperCase()}_${paramsKey}`;
-};
-
-// reactions
-export const ISSUE_REACTION_LIST = (workspaceSlug: string, projectId: string, issueId: string) =>
- `ISSUE_REACTION_LIST_${workspaceSlug.toUpperCase()}_${projectId.toUpperCase()}_${issueId.toUpperCase()}`;
-export const COMMENT_REACTION_LIST = (workspaceSlug: string, projectId: string, commendId: string) =>
- `COMMENT_REACTION_LIST_${workspaceSlug.toUpperCase()}_${projectId.toUpperCase()}_${commendId.toUpperCase()}`;
// api-tokens
export const API_TOKENS_LIST = (workspaceSlug: string) => `API_TOKENS_LIST_${workspaceSlug.toUpperCase()}`;
-export const API_TOKEN_DETAILS = (workspaceSlug: string, tokenId: string) =>
- `API_TOKEN_DETAILS_${workspaceSlug.toUpperCase()}_${tokenId.toUpperCase()}`;
diff --git a/web/core/hooks/use-comment-reaction.tsx b/web/core/hooks/use-comment-reaction.tsx
deleted file mode 100644
index 848c9b42654..00000000000
--- a/web/core/hooks/use-comment-reaction.tsx
+++ /dev/null
@@ -1,93 +0,0 @@
-import useSWR from "swr";
-// fetch keys
-import { COMMENT_REACTION_LIST } from "@/constants/fetch-keys";
-// services
-import { groupReactions } from "@/helpers/emoji.helper";
-import { useUser } from "@/hooks/store";
-import { IssueReactionService } from "@/services/issue";
-// helpers
-// hooks
-// services
-const issueReactionService = new IssueReactionService();
-
-const useCommentReaction: any = (
- workspaceSlug?: string | string[] | null,
- projectId?: string | string[] | null,
- commendId?: string | string[] | null
-) => {
- const {
- data: commentReactions,
- mutate: mutateCommentReactions,
- error,
- } = useSWR(
- workspaceSlug && projectId && commendId
- ? COMMENT_REACTION_LIST(workspaceSlug.toString(), projectId.toString(), commendId.toString())
- : null,
- workspaceSlug && projectId && commendId
- ? () =>
- issueReactionService.listIssueCommentReactions(
- workspaceSlug.toString(),
- projectId.toString(),
- commendId.toString()
- )
- : null
- );
-
- const { data: currentUser } = useUser();
-
- const groupedReactions = groupReactions(commentReactions || [], "reaction");
-
- /**
- * @description Use this function to create user's reaction to an issue. This function will mutate the reactions state.
- * @param {string} reaction
- * @example handleReactionDelete("123") // 123 -> is emoji hexa-code
- */
-
- const handleReactionCreate = async (reaction: string) => {
- if (!workspaceSlug || !projectId || !commendId) return;
-
- const data = await issueReactionService.createIssueCommentReaction(
- workspaceSlug.toString(),
- projectId.toString(),
- commendId.toString(),
- { reaction }
- );
-
- mutateCommentReactions((prev: any) => [...(prev || []), data]);
- };
-
- /**
- * @description Use this function to delete user's reaction from an issue. This function will mutate the reactions state.
- * @param {string} reaction
- * @example handleReactionDelete("123") // 123 -> is emoji hexa-code
- */
-
- const handleReactionDelete = async (reaction: string) => {
- if (!workspaceSlug || !projectId || !commendId) return;
-
- mutateCommentReactions(
- (prevData: any) => prevData?.filter((r: any) => r.actor !== currentUser?.id || r.reaction !== reaction) || [],
- false
- );
-
- await issueReactionService.deleteIssueCommentReaction(
- workspaceSlug.toString(),
- projectId.toString(),
- commendId.toString(),
- reaction
- );
-
- mutateCommentReactions();
- };
-
- return {
- isLoading: !commentReactions && !error,
- commentReactions,
- groupedReactions,
- handleReactionCreate,
- handleReactionDelete,
- mutateCommentReactions,
- } as const;
-};
-
-export default useCommentReaction;
diff --git a/web/core/hooks/use-dynamic-dropdown.tsx b/web/core/hooks/use-dynamic-dropdown.tsx
deleted file mode 100644
index 771763e3585..00000000000
--- a/web/core/hooks/use-dynamic-dropdown.tsx
+++ /dev/null
@@ -1,63 +0,0 @@
-import React, { useCallback, useEffect } from "react";
-// plane helpers
-import { useOutsideClickDetector } from "@plane/hooks";
-
-/**
- * Custom hook for dynamic dropdown position calculation.
- * @param isOpen - Indicates whether the dropdown is open.
- * @param handleClose - Callback to handle closing the dropdown.
- * @param buttonRef - Ref object for the button triggering the dropdown.
- * @param dropdownRef - Ref object for the dropdown element.
- */
-
-const useDynamicDropdownPosition = (
- isOpen: boolean,
- handleClose: () => void,
- buttonRef: React.RefObject,
- dropdownRef: React.RefObject
-) => {
- const handlePosition = useCallback(() => {
- const button = buttonRef.current;
- const dropdown = dropdownRef.current;
-
- if (!dropdown || !button) return;
-
- const buttonRect = button.getBoundingClientRect();
- const dropdownRect = dropdown.getBoundingClientRect();
-
- const { innerHeight, innerWidth, scrollX, scrollY } = window;
-
- let top: number = buttonRect.bottom + scrollY;
- if (top + dropdownRect.height > innerHeight) top = innerHeight - dropdownRect.height;
-
- let left: number = buttonRect.left + scrollX + (buttonRect.width - dropdownRect.width) / 2;
- if (left + dropdownRect.width > innerWidth) left = innerWidth - dropdownRect.width;
-
- dropdown.style.top = `${Math.max(top, 5)}px`;
- dropdown.style.left = `${Math.max(left, 5)}px`;
- }, [buttonRef, dropdownRef]);
-
- useEffect(() => {
- if (isOpen) handlePosition();
- }, [handlePosition, isOpen]);
-
- useOutsideClickDetector(dropdownRef, () => {
- if (isOpen) handleClose();
- });
-
- const handleResize = useCallback(() => {
- if (isOpen) {
- handlePosition();
- }
- }, [handlePosition, isOpen]);
-
- useEffect(() => {
- window.addEventListener("resize", handleResize);
-
- return () => {
- window.removeEventListener("resize", handleResize);
- };
- }, [isOpen, handleResize]);
-};
-
-export default useDynamicDropdownPosition;
diff --git a/web/core/hooks/use-url-hash.tsx b/web/core/hooks/use-url-hash.tsx
deleted file mode 100644
index 9dc6d1770fa..00000000000
--- a/web/core/hooks/use-url-hash.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import { useEffect, useState } from "react";
-
-const useURLHash = () => {
- const [hashValue, setHashValue] = useState();
-
- useEffect(() => {
- const hash = window.location.hash?.split("#")[1];
- setHashValue(hash);
- }, []);
-
- return hashValue;
-};
-
-export default useURLHash;
diff --git a/web/core/lib/wrappers/crisp-wrapper.tsx b/web/core/lib/wrappers/crisp-wrapper.tsx
deleted file mode 100644
index 1debf8ea5bd..00000000000
--- a/web/core/lib/wrappers/crisp-wrapper.tsx
+++ /dev/null
@@ -1,41 +0,0 @@
-import { useEffect, ReactNode, FC } from "react";
-import { observer } from "mobx-react";
-// hooks
-import { useUser } from "@/hooks/store";
-
-declare global {
- interface Window {
- $crisp: unknown[];
- CRISP_WEBSITE_ID: unknown;
- }
-}
-
-export interface ICrispWrapper {
- children: ReactNode;
-}
-
-const CrispWrapper: FC = observer((props) => {
- const { children } = props;
- const { data: user } = useUser();
-
- useEffect(() => {
- if (typeof window && user?.email && process.env.NEXT_PUBLIC_CRISP_ID) {
- window.$crisp = [];
- window.CRISP_WEBSITE_ID = process.env.NEXT_PUBLIC_CRISP_ID;
- (function () {
- const d = document;
- const s = d.createElement("script");
- s.src = "https://client.crisp.chat/l.js";
- s.async = true;
- d.getElementsByTagName("head")[0].appendChild(s);
- window.$crisp.push(["set", "user:email", [user.email]]);
- window.$crisp.push(["do", "chat:hide"]);
- window.$crisp.push(["do", "chat:close"]);
- })();
- }
- }, [user?.email]);
-
- return <>{children}>;
-});
-
-export default CrispWrapper;
diff --git a/web/helpers/string.helper.ts b/web/helpers/string.helper.ts
index d0973109171..4c85e3ca84a 100644
--- a/web/helpers/string.helper.ts
+++ b/web/helpers/string.helper.ts
@@ -1,10 +1,4 @@
import DOMPurify from "isomorphic-dompurify";
-import {
- CYCLE_ISSUES_WITH_PARAMS,
- MODULE_ISSUES_WITH_PARAMS,
- PROJECT_ISSUES_LIST_WITH_PARAMS,
- VIEW_ISSUES,
-} from "@/constants/fetch-keys";
export const addSpaceIfCamelCase = (str: string) => {
if (str === undefined || str === null) return "";
@@ -150,29 +144,6 @@ export const objToQueryParams = (obj: any) => {
return params.toString();
};
-export const getFetchKeysForIssueMutation = (options: {
- cycleId?: string | string[];
- moduleId?: string | string[];
- viewId?: string | string[];
- projectId: string;
- viewGanttParams: any;
- ganttParams: any;
-}) => {
- const { cycleId, moduleId, viewId, projectId, viewGanttParams, ganttParams } = options;
-
- const ganttFetchKey = cycleId
- ? { ganttFetchKey: CYCLE_ISSUES_WITH_PARAMS(cycleId.toString(), ganttParams) }
- : moduleId
- ? { ganttFetchKey: MODULE_ISSUES_WITH_PARAMS(moduleId.toString(), ganttParams) }
- : viewId
- ? { ganttFetchKey: VIEW_ISSUES(viewId.toString(), viewGanttParams) }
- : { ganttFetchKey: PROJECT_ISSUES_LIST_WITH_PARAMS(projectId?.toString() ?? "", ganttParams) };
-
- return {
- ...ganttFetchKey,
- };
-};
-
/**
* @returns {boolean} true if searchQuery is substring of text in the same order, false otherwise
* @description Returns true if searchQuery is substring of text in the same order, false otherwise
diff --git a/web/package.json b/web/package.json
index 6312f9f903b..2122586e505 100644
--- a/web/package.json
+++ b/web/package.json
@@ -19,7 +19,6 @@
"@atlaskit/pragmatic-drag-and-drop": "^1.1.3",
"@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^1.3.0",
"@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.0.3",
- "@blueprintjs/popover2": "^1.13.3",
"@headlessui/react": "^1.7.3",
"@intercom/messenger-js-sdk": "^0.0.12",
"@plane/constants": "*",
@@ -65,7 +64,6 @@
"smooth-scroll-into-view-if-needed": "^2.0.2",
"swr": "^2.1.3",
"tailwind-merge": "^2.0.0",
- "use-debounce": "^9.0.4",
"use-font-face-observer": "^1.2.2",
"uuid": "^9.0.0",
"zxcvbn": "^4.4.2"