diff --git a/apiserver/plane/app/serializers/cycle.py b/apiserver/plane/app/serializers/cycle.py index a041dd227..77c3f16cc 100644 --- a/apiserver/plane/app/serializers/cycle.py +++ b/apiserver/plane/app/serializers/cycle.py @@ -33,7 +33,6 @@ class CycleWriteSerializer(BaseSerializer): class CycleSerializer(BaseSerializer): - owned_by = UserLiteSerializer(read_only=True) is_favorite = serializers.BooleanField(read_only=True) total_issues = serializers.IntegerField(read_only=True) cancelled_issues = serializers.IntegerField(read_only=True) diff --git a/packages/types/src/cycles.d.ts b/packages/types/src/cycles.d.ts index 91c6ef1d5..12cbab4c6 100644 --- a/packages/types/src/cycles.d.ts +++ b/packages/types/src/cycles.d.ts @@ -30,7 +30,7 @@ export interface ICycle { is_favorite: boolean; issue: string; name: string; - owned_by: IUser; + owned_by: string; project: string; project_detail: IProjectLite; status: TCycleGroups; diff --git a/packages/ui/src/breadcrumbs/breadcrumbs.tsx b/packages/ui/src/breadcrumbs/breadcrumbs.tsx index e82944c03..0f09764ac 100644 --- a/packages/ui/src/breadcrumbs/breadcrumbs.tsx +++ b/packages/ui/src/breadcrumbs/breadcrumbs.tsx @@ -2,8 +2,6 @@ import * as React from "react"; // icons import { ChevronRight } from "lucide-react"; -// components -import { Tooltip } from "../tooltip"; type BreadcrumbsProps = { children: any; @@ -25,42 +23,11 @@ const Breadcrumbs = ({ children }: BreadcrumbsProps) => ( type Props = { type?: "text" | "component"; component?: React.ReactNode; - label?: string; - icon?: React.ReactNode; - link?: string; + link?: JSX.Element; }; const BreadcrumbItem: React.FC = (props) => { - const { type = "text", component, label, icon, link } = props; - return ( - <> - {type != "text" ? ( -
{component}
- ) : ( - -
  • -
    - {link ? ( - - {icon && ( -
    {icon}
    - )} -
    {label}
    -
    - ) : ( -
    - {icon &&
    {icon}
    } -
    {label}
    -
    - )} -
    -
  • -
    - )} - - ); + const { type = "text", component, link } = props; + return <>{type != "text" ?
    {component}
    : link}; }; Breadcrumbs.BreadcrumbItem = BreadcrumbItem; diff --git a/web/components/analytics/custom-analytics/sidebar/sidebar-header.tsx b/web/components/analytics/custom-analytics/sidebar/sidebar-header.tsx index d46cad191..4a18011d1 100644 --- a/web/components/analytics/custom-analytics/sidebar/sidebar-header.tsx +++ b/web/components/analytics/custom-analytics/sidebar/sidebar-header.tsx @@ -1,7 +1,7 @@ import { useRouter } from "next/router"; import { observer } from "mobx-react-lite"; // hooks -import { useCycle, useModule, useProject } from "hooks/store"; +import { useCycle, useMember, useModule, useProject } from "hooks/store"; // helpers import { renderEmoji } from "helpers/emoji.helper"; import { renderFormattedDate } from "helpers/date-time.helper"; @@ -15,10 +15,12 @@ export const CustomAnalyticsSidebarHeader = observer(() => { const { getProjectById } = useProject(); const { getCycleById } = useCycle(); const { getModuleById } = useModule(); + const { getUserDetails } = useMember(); const cycleDetails = cycleId ? getCycleById(cycleId.toString()) : undefined; const moduleDetails = moduleId ? getModuleById(moduleId.toString()) : undefined; const projectDetails = projectId ? getProjectById(projectId.toString()) : undefined; + const cycleOwnerDetails = cycleDetails ? getUserDetails(cycleDetails.owned_by) : undefined; return ( <> @@ -29,7 +31,7 @@ export const CustomAnalyticsSidebarHeader = observer(() => {
    Lead
    - {cycleDetails.owned_by?.display_name} + {cycleOwnerDetails?.display_name}
    Start Date
    diff --git a/web/components/common/breadcrumb-link.tsx b/web/components/common/breadcrumb-link.tsx new file mode 100644 index 000000000..aebd7fc02 --- /dev/null +++ b/web/components/common/breadcrumb-link.tsx @@ -0,0 +1,36 @@ +import { Tooltip } from "@plane/ui"; +import Link from "next/link"; + +type Props = { + label?: string; + href?: string; + icon?: React.ReactNode | undefined; +}; + +export const BreadcrumbLink: React.FC = (props) => { + const { href, label, icon } = props; + return ( + +
  • +
    + {href ? ( + + {icon && ( +
    {icon}
    + )} +
    {label}
    + + ) : ( +
    + {icon &&
    {icon}
    } +
    {label}
    +
    + )} +
    +
  • +
    + ); +}; diff --git a/web/components/common/index.ts b/web/components/common/index.ts index 04aaa8512..0eff24d93 100644 --- a/web/components/common/index.ts +++ b/web/components/common/index.ts @@ -1,3 +1,4 @@ export * from "./product-updates-modal"; export * from "./empty-state"; export * from "./latest-feature-block"; +export * from "./breadcrumb-link"; diff --git a/web/components/core/modals/gpt-assistant-popover.tsx b/web/components/core/modals/gpt-assistant-popover.tsx index 3afd6d1b9..590015e12 100644 --- a/web/components/core/modals/gpt-assistant-popover.tsx +++ b/web/components/core/modals/gpt-assistant-popover.tsx @@ -157,6 +157,7 @@ export const GptAssistantPopover: React.FC = (props) => { window.removeEventListener("keydown", handleEnterKeyPress); window.removeEventListener("keydown", handleEscapeKeyPress); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [isOpen, handleSubmit, onClose]); const responseActionButton = response !== "" && ( diff --git a/web/components/cycles/active-cycle-details.tsx b/web/components/cycles/active-cycle-details.tsx index 12d836695..a0101b1c1 100644 --- a/web/components/cycles/active-cycle-details.tsx +++ b/web/components/cycles/active-cycle-details.tsx @@ -4,7 +4,7 @@ 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 { useCycle, useIssues, useMember, useProject, useUser } from "hooks/store"; import useToast from "hooks/use-toast"; // ui import { SingleProgressStats } from "components/core"; @@ -58,6 +58,7 @@ export const ActiveCycleDetails: React.FC = observer((props removeCycleFromFavorites, } = useCycle(); const { currentProjectDetails } = useProject(); + const { getUserDetails } = useMember(); // toast alert const { setToastAlert } = useToast(); @@ -67,6 +68,7 @@ export const ActiveCycleDetails: React.FC = observer((props ); const activeCycle = currentProjectActiveCycleId ? getActiveCycleById(currentProjectActiveCycleId) : null; + const cycleOwnerDetails = activeCycle ? getUserDetails(activeCycle.owned_by) : undefined; const { data: activeCycleIssues } = useSWR( workspaceSlug && projectId && currentProjectActiveCycleId @@ -203,20 +205,20 @@ export const ActiveCycleDetails: React.FC = observer((props
    - {activeCycle.owned_by.avatar && activeCycle.owned_by.avatar !== "" ? ( + {cycleOwnerDetails?.avatar && cycleOwnerDetails?.avatar !== "" ? ( {activeCycle.owned_by.display_name} ) : ( - {activeCycle.owned_by.display_name.charAt(0)} + {cycleOwnerDetails?.display_name.charAt(0)} )} - {activeCycle.owned_by.display_name} + {cycleOwnerDetails?.display_name}
    {activeCycle.assignees.length > 0 && ( diff --git a/web/components/cycles/sidebar.tsx b/web/components/cycles/sidebar.tsx index 52da51b77..4bf76f91f 100644 --- a/web/components/cycles/sidebar.tsx +++ b/web/components/cycles/sidebar.tsx @@ -6,7 +6,7 @@ import { Disclosure, Popover, Transition } from "@headlessui/react"; // services import { CycleService } from "services/cycle.service"; // hooks -import { useApplication, useCycle, useUser } from "hooks/store"; +import { useApplication, useCycle, useMember, useUser } from "hooks/store"; import useToast from "hooks/use-toast"; // components import { SidebarProgressStats } from "components/core"; @@ -73,8 +73,10 @@ export const CycleDetailsSidebar: React.FC = observer((props) => { membership: { currentProjectRole }, } = useUser(); const { getCycleById, updateCycleDetails } = useCycle(); + const { getUserDetails } = useMember(); const cycleDetails = getCycleById(cycleId); + const cycleOwnerDetails = cycleDetails ? getUserDetails(cycleDetails.owned_by) : undefined; const { setToastAlert } = useToast(); @@ -518,8 +520,8 @@ export const CycleDetailsSidebar: React.FC = observer((props) => {
    - - {cycleDetails.owned_by.display_name} + + {cycleOwnerDetails?.display_name}
    diff --git a/web/components/dashboard/widgets/overview-stats.tsx b/web/components/dashboard/widgets/overview-stats.tsx index 418f0c63f..1a4c2646b 100644 --- a/web/components/dashboard/widgets/overview-stats.tsx +++ b/web/components/dashboard/widgets/overview-stats.tsx @@ -7,7 +7,6 @@ import { useDashboard } from "hooks/store"; import { WidgetLoader } from "components/dashboard/widgets"; // helpers import { renderFormattedPayloadDate } from "helpers/date-time.helper"; -import { cn } from "helpers/common.helper"; // types import { TOverviewStatsWidgetResponse } from "@plane/types"; diff --git a/web/components/headers/cycle-issues.tsx b/web/components/headers/cycle-issues.tsx index fc0075030..8e2ceab10 100644 --- a/web/components/headers/cycle-issues.tsx +++ b/web/components/headers/cycle-issues.tsx @@ -18,6 +18,7 @@ import useLocalStorage from "hooks/use-local-storage"; import { DisplayFiltersSelection, FiltersDropdown, FilterSelection, LayoutSelection } from "components/issues"; import { ProjectAnalyticsModal } from "components/analytics"; import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle"; +import { BreadcrumbLink } from "components/common"; // ui import { Breadcrumbs, Button, ContrastIcon, CustomMenu } from "@plane/ui"; // icons @@ -151,25 +152,33 @@ export const CycleIssuesHeader: React.FC = observer(() => { - {currentProjectDetails?.name.charAt(0)} - - ) + link={ + + {currentProjectDetails?.name.charAt(0)} + + ) + } + /> } - label={currentProjectDetails?.name ?? "Project"} - link={`/${workspaceSlug}/projects/${currentProjectDetails?.id}/issues`} /> } - label="Cycles" - link={`/${workspaceSlug}/projects/${projectId}/cycles`} + link={ + } + /> + } /> { // router @@ -32,29 +33,32 @@ export const CyclesHeader: FC = observer(() => { return (
    - +
    - {currentProjectDetails?.name.charAt(0)} - - ) + link={ + + {currentProjectDetails?.name.charAt(0)} + + ) + } + /> } - link={`/${workspaceSlug}/projects/${currentProjectDetails?.id}/issues`} /> } - label="Cycles" + link={} />} />
    diff --git a/web/components/headers/global-issues.tsx b/web/components/headers/global-issues.tsx index debcbc213..cca1a972b 100644 --- a/web/components/headers/global-issues.tsx +++ b/web/components/headers/global-issues.tsx @@ -8,6 +8,7 @@ import { useLabel, useMember, useUser, useIssues } from "hooks/store"; import { DisplayFiltersSelection, FiltersDropdown, FilterSelection } from "components/issues"; import { CreateUpdateWorkspaceViewModal } from "components/workspace"; import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle"; +import { BreadcrumbLink } from "components/common"; // ui import { Breadcrumbs, Button, LayersIcon, PhotoFilterIcon, Tooltip } from "@plane/ui"; // icons @@ -108,18 +109,22 @@ export const GlobalIssuesHeader: React.FC = observer((props) => { setCreateViewModal(false)} />
    - + - ) : ( - - ) + link={ + + ) : ( + + ) + } + /> } - label={`All ${activeLayout === "spreadsheet" ? "Issues" : "Views"}`} />
    diff --git a/web/components/headers/module-issues.tsx b/web/components/headers/module-issues.tsx index 84a284f2e..5ec67a3d7 100644 --- a/web/components/headers/module-issues.tsx +++ b/web/components/headers/module-issues.tsx @@ -18,6 +18,7 @@ import useLocalStorage from "hooks/use-local-storage"; import { DisplayFiltersSelection, FiltersDropdown, FilterSelection, LayoutSelection } from "components/issues"; import { ProjectAnalyticsModal } from "components/analytics"; import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle"; +import { BreadcrumbLink } from "components/common"; // ui import { Breadcrumbs, Button, CustomMenu, DiceIcon } from "@plane/ui"; // icons @@ -154,25 +155,33 @@ export const ModuleIssuesHeader: React.FC = observer(() => { - {currentProjectDetails?.name.charAt(0)} - - ) + link={ + + {currentProjectDetails?.name.charAt(0)} + + ) + } + /> } - label={currentProjectDetails?.name ?? "Project"} - link={`/${workspaceSlug}/projects/${currentProjectDetails?.id}/issues`} /> } - label="Modules" - link={`/${workspaceSlug}/projects/${projectId}/modules`} + link={ + } + /> + } /> { // router @@ -33,29 +34,32 @@ export const ModulesListHeader: React.FC = observer(() => { return (
    - +
    - {currentProjectDetails?.name.charAt(0)} - - ) + link={ + + {currentProjectDetails?.name.charAt(0)} + + ) + } + /> } - link={`/${workspaceSlug}/projects/${currentProjectDetails?.id}/issues`} /> } - label="Modules" + link={} />} />
    diff --git a/web/components/headers/page-details.tsx b/web/components/headers/page-details.tsx index d2a959817..83595af60 100644 --- a/web/components/headers/page-details.tsx +++ b/web/components/headers/page-details.tsx @@ -10,6 +10,7 @@ import { Breadcrumbs, Button } from "@plane/ui"; import { renderEmoji } from "helpers/emoji.helper"; // components import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle"; +import { BreadcrumbLink } from "components/common"; export interface IPagesHeaderProps { showButton?: boolean; @@ -29,35 +30,47 @@ export const PageDetailsHeader: FC = observer((props) => { return (
    - +
    - {currentProjectDetails?.name.charAt(0)} - - ) + link={ + + {currentProjectDetails?.name.charAt(0)} + + ) + } + /> } - link={`/${workspaceSlug}/projects/${currentProjectDetails?.id}/issues`} /> } - label="Pages" - link={`/${workspaceSlug}/projects/${currentProjectDetails?.id}/pages`} + link={ + } + /> + } /> } - label={pageDetails?.name ?? "Page"} + link={ + } + /> + } />
    diff --git a/web/components/headers/pages.tsx b/web/components/headers/pages.tsx index 2afb549a0..28116b323 100644 --- a/web/components/headers/pages.tsx +++ b/web/components/headers/pages.tsx @@ -11,6 +11,7 @@ import { renderEmoji } from "helpers/emoji.helper"; import { EUserProjectRoles } from "constants/project"; // components import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle"; +import { BreadcrumbLink } from "components/common"; export const PagesHeader = observer(() => { // router @@ -31,29 +32,32 @@ export const PagesHeader = observer(() => { return (
    - +
    - {currentProjectDetails?.name.charAt(0)} - - ) + link={ + + {currentProjectDetails?.name.charAt(0)} + + ) + } + /> } - link={`/${workspaceSlug}/projects/${currentProjectDetails?.id}/issues`} /> } - label="Pages" + link={} />} />
    diff --git a/web/components/headers/profile-preferences.tsx b/web/components/headers/profile-preferences.tsx index 0c6329ac9..e9f37bf6e 100644 --- a/web/components/headers/profile-preferences.tsx +++ b/web/components/headers/profile-preferences.tsx @@ -1,12 +1,13 @@ // components import { Breadcrumbs } from "@plane/ui"; +import { BreadcrumbLink } from "components/common"; export const ProfilePreferencesHeader = () => (
    - + } />
    diff --git a/web/components/headers/profile-settings.tsx b/web/components/headers/profile-settings.tsx index 76e5e6fcc..24c69f093 100644 --- a/web/components/headers/profile-settings.tsx +++ b/web/components/headers/profile-settings.tsx @@ -2,6 +2,7 @@ import { FC } from "react"; // ui import { Breadcrumbs } from "@plane/ui"; import { Settings } from "lucide-react"; +import { BreadcrumbLink } from "components/common"; interface IProfileSettingHeader { title: string; @@ -17,11 +18,15 @@ export const ProfileSettingsHeader: FC = (props) => { } - link="/profile" + link={ + } + /> + } /> - + } />
    diff --git a/web/components/headers/project-archived-issue-details.tsx b/web/components/headers/project-archived-issue-details.tsx index e393450af..3b3e05f1a 100644 --- a/web/components/headers/project-archived-issue-details.tsx +++ b/web/components/headers/project-archived-issue-details.tsx @@ -16,6 +16,7 @@ import { IssueArchiveService } from "services/issue"; import { renderEmoji } from "helpers/emoji.helper"; // components import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle"; +import { BreadcrumbLink } from "components/common"; const issueArchiveService = new IssueArchiveService(); @@ -41,37 +42,50 @@ export const ProjectArchivedIssueDetailsHeader: FC = observer(() => { return (
    - +
    - {currentProjectDetails?.name.charAt(0)} - - ) + link={ + + {currentProjectDetails?.name.charAt(0)} + + ) + } + /> } - label={currentProjectDetails?.name ?? "Project"} - link={`/${workspaceSlug}/projects`} /> } - label="Archived Issues" - link={`/${workspaceSlug}/projects/${projectId}/archived-issues`} + link={ + } + /> + } /> } /> diff --git a/web/components/headers/project-archived-issues.tsx b/web/components/headers/project-archived-issues.tsx index ee1265374..b7ca78ede 100644 --- a/web/components/headers/project-archived-issues.tsx +++ b/web/components/headers/project-archived-issues.tsx @@ -11,6 +11,7 @@ import { Breadcrumbs, LayersIcon } from "@plane/ui"; // components import { DisplayFiltersSelection, FilterSelection, FiltersDropdown } from "components/issues"; import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle"; +import { BreadcrumbLink } from "components/common"; // helpers import { renderEmoji } from "helpers/emoji.helper"; // types @@ -71,7 +72,7 @@ export const ProjectArchivedIssuesHeader: FC = observer(() => { return (
    - +
    diff --git a/web/components/headers/project-draft-issues.tsx b/web/components/headers/project-draft-issues.tsx index 10f07f779..0fe6a74c5 100644 --- a/web/components/headers/project-draft-issues.tsx +++ b/web/components/headers/project-draft-issues.tsx @@ -6,6 +6,7 @@ import { useIssues, useLabel, useMember, useProject, useProjectState } from "hoo // components import { DisplayFiltersSelection, FiltersDropdown, FilterSelection, LayoutSelection } from "components/issues"; import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle"; +import { BreadcrumbLink } from "components/common"; // ui import { Breadcrumbs, LayersIcon } from "@plane/ui"; // helper @@ -75,30 +76,35 @@ export const ProjectDraftIssueHeader: FC = observer(() => { return (
    - +
    - {currentProjectDetails?.name.charAt(0)} - - ) + link={ + + {currentProjectDetails?.name.charAt(0)} + + ) + } + /> } - label={currentProjectDetails?.name ?? "Project"} - link={`/${workspaceSlug}/projects`} /> } - label="Draft Issues" + link={ + } /> + } />
    diff --git a/web/components/headers/project-inbox.tsx b/web/components/headers/project-inbox.tsx index 29ea9fc47..b5260edd7 100644 --- a/web/components/headers/project-inbox.tsx +++ b/web/components/headers/project-inbox.tsx @@ -9,6 +9,7 @@ import { Breadcrumbs, Button, LayersIcon } from "@plane/ui"; // components import { CreateInboxIssueModal } from "components/inbox"; import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle"; +import { BreadcrumbLink } from "components/common"; // helper import { renderEmoji } from "helpers/emoji.helper"; @@ -24,30 +25,35 @@ export const ProjectInboxHeader: FC = observer(() => { return (
    - +
    - {currentProjectDetails?.name.charAt(0)} - - ) + link={ + + {currentProjectDetails?.name.charAt(0)} + + ) + } + /> } - label={currentProjectDetails?.name ?? "Project"} - link={`/${workspaceSlug}/projects`} /> } - label="Inbox Issues" + link={ + } /> + } />
    diff --git a/web/components/headers/project-issue-details.tsx b/web/components/headers/project-issue-details.tsx index 7b45d3fcf..8d3a22682 100644 --- a/web/components/headers/project-issue-details.tsx +++ b/web/components/headers/project-issue-details.tsx @@ -14,6 +14,7 @@ import { IssueService } from "services/issue"; import { ISSUE_DETAILS } from "constants/fetch-keys"; // components import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle"; +import { BreadcrumbLink } from "components/common"; // services const issueService = new IssueService(); @@ -35,37 +36,50 @@ export const ProjectIssueDetailsHeader: FC = observer(() => { return (
    - +
    - {currentProjectDetails?.name.charAt(0)} - - ) + link={ + + {currentProjectDetails?.name.charAt(0)} + + ) + } + /> } - label={currentProjectDetails?.name ?? "Project"} - link={`/${workspaceSlug}/projects`} /> } - label="Issues" - link={`/${workspaceSlug}/projects/${projectId}/issues`} + link={ + } + /> + } /> } /> diff --git a/web/components/headers/project-issues.tsx b/web/components/headers/project-issues.tsx index 04a7ecb64..29ecb16c7 100644 --- a/web/components/headers/project-issues.tsx +++ b/web/components/headers/project-issues.tsx @@ -9,6 +9,7 @@ import { useApplication, useLabel, useProject, useProjectState, useUser, useInbo import { DisplayFiltersSelection, FiltersDropdown, FilterSelection, LayoutSelection } from "components/issues"; import { ProjectAnalyticsModal } from "components/analytics"; import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle"; +import { BreadcrumbLink } from "components/common"; // ui import { Breadcrumbs, Button, LayersIcon } from "@plane/ui"; // types @@ -106,7 +107,7 @@ export const ProjectIssuesHeader: React.FC = observer(() => { />
    - +
    diff --git a/web/components/headers/project-settings.tsx b/web/components/headers/project-settings.tsx index eff05aba5..fdb033a21 100644 --- a/web/components/headers/project-settings.tsx +++ b/web/components/headers/project-settings.tsx @@ -11,6 +11,7 @@ import { useProject, useUser } from "hooks/store"; import { EUserProjectRoles, PROJECT_SETTINGS_LINKS } from "constants/project"; // components import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle"; +import { BreadcrumbLink } from "components/common"; export interface IProjectSettingHeader { title: string; @@ -38,22 +39,26 @@ export const ProjectSettingHeader: FC = observer((props) - {currentProjectDetails?.name.charAt(0)} - - ) + link={ + + {currentProjectDetails?.name.charAt(0)} + + ) + } + /> } - link={`/${workspaceSlug}/projects/${currentProjectDetails?.id}/issues`} />
    - + } />
    @@ -62,13 +67,18 @@ export const ProjectSettingHeader: FC = observer((props) className="flex-shrink-0 block sm:block md:hidden lg:hidden" maxHeight="lg" customButton={ - {title} + + {title} + } placement="bottom-start" closeOnSelect > {PROJECT_SETTINGS_LINKS.map((item) => ( - router.push(`/${workspaceSlug}/projects/${projectId}${item.href}`)}> + router.push(`/${workspaceSlug}/projects/${projectId}${item.href}`)} + > {item.label} ))} diff --git a/web/components/headers/project-view-issues.tsx b/web/components/headers/project-view-issues.tsx index abe13c4e2..050400a2c 100644 --- a/web/components/headers/project-view-issues.tsx +++ b/web/components/headers/project-view-issues.tsx @@ -17,6 +17,7 @@ import { // components import { DisplayFiltersSelection, FiltersDropdown, FilterSelection, LayoutSelection } from "components/issues"; import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle"; +import { BreadcrumbLink } from "components/common"; // ui import { Breadcrumbs, Button, CustomMenu, PhotoFilterIcon } from "@plane/ui"; // helpers @@ -112,29 +113,37 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => { - {renderEmoji(currentProjectDetails.emoji)} - - ) : currentProjectDetails?.icon_prop ? ( -
    - {renderEmoji(currentProjectDetails.icon_prop)} -
    - ) : ( - - {currentProjectDetails?.name.charAt(0)} - - ) + link={ + + {renderEmoji(currentProjectDetails.emoji)} + + ) : currentProjectDetails?.icon_prop ? ( +
    + {renderEmoji(currentProjectDetails.icon_prop)} +
    + ) : ( + + {currentProjectDetails?.name.charAt(0)} + + ) + } + /> } - link={`/${workspaceSlug}/projects/${currentProjectDetails?.id}/issues`} /> } - label="Views" - link={`/${workspaceSlug}/projects/${currentProjectDetails?.id}/views`} + link={ + } + /> + } /> { <>
    - +
    - {renderEmoji(currentProjectDetails.emoji)} - - ) : currentProjectDetails?.icon_prop ? ( -
    - {renderEmoji(currentProjectDetails.icon_prop)} -
    - ) : ( - - {currentProjectDetails?.name.charAt(0)} - - ) + link={ + + {renderEmoji(currentProjectDetails.emoji)} + + ) : currentProjectDetails?.icon_prop ? ( +
    + {renderEmoji(currentProjectDetails.icon_prop)} +
    + ) : ( + + {currentProjectDetails?.name.charAt(0)} + + ) + } + /> } - link={`/${workspaceSlug}/projects/${currentProjectDetails?.id}/issues`} /> } - label="Views" + link={ + } /> + } />
    diff --git a/web/components/headers/projects.tsx b/web/components/headers/projects.tsx index 96929f7b0..33192930e 100644 --- a/web/components/headers/projects.tsx +++ b/web/components/headers/projects.tsx @@ -8,6 +8,7 @@ import { Breadcrumbs, Button } from "@plane/ui"; import { EUserWorkspaceRoles } from "constants/workspace"; // components import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle"; +import { BreadcrumbLink } from "components/common"; export const ProjectsHeader = observer(() => { // store hooks @@ -25,13 +26,12 @@ export const ProjectsHeader = observer(() => { return (
    - +
    } - label="Projects" + link={} />} />
    diff --git a/web/components/headers/user-profile.tsx b/web/components/headers/user-profile.tsx index dca0dc7e6..d54f73009 100644 --- a/web/components/headers/user-profile.tsx +++ b/web/components/headers/user-profile.tsx @@ -1,15 +1,16 @@ // ui import { Breadcrumbs } from "@plane/ui"; +import { BreadcrumbLink } from "components/common"; // components import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle"; export const UserProfileHeader = () => (
    - +
    - + } />
    diff --git a/web/components/headers/workspace-active-cycles.tsx b/web/components/headers/workspace-active-cycles.tsx index 90cbccd81..195b89471 100644 --- a/web/components/headers/workspace-active-cycles.tsx +++ b/web/components/headers/workspace-active-cycles.tsx @@ -1,9 +1,10 @@ import { observer } from "mobx-react-lite"; // ui import { Breadcrumbs, ContrastIcon } from "@plane/ui"; +import { BreadcrumbLink } from "components/common"; +import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle"; // icons import { Crown } from "lucide-react"; -import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle"; export const WorkspaceActiveCycleHeader = observer(() => (
    @@ -13,8 +14,12 @@ export const WorkspaceActiveCycleHeader = observer(() => ( } - label="Active Cycles" + link={ + } + /> + } /> diff --git a/web/components/headers/workspace-analytics.tsx b/web/components/headers/workspace-analytics.tsx index 2ae373471..8bb4c9251 100644 --- a/web/components/headers/workspace-analytics.tsx +++ b/web/components/headers/workspace-analytics.tsx @@ -4,6 +4,7 @@ import { ArrowLeft, BarChart2 } from "lucide-react"; import { Breadcrumbs } from "@plane/ui"; // components import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle"; +import { BreadcrumbLink } from "components/common"; export const WorkspaceAnalyticsHeader = () => { const router = useRouter(); @@ -28,8 +29,9 @@ export const WorkspaceAnalyticsHeader = () => { } - label="Analytics" + link={ + } /> + } />
    diff --git a/web/components/headers/workspace-dashboard.tsx b/web/components/headers/workspace-dashboard.tsx index d576cb963..b7c05929c 100644 --- a/web/components/headers/workspace-dashboard.tsx +++ b/web/components/headers/workspace-dashboard.tsx @@ -6,7 +6,7 @@ import { useTheme } from "next-themes"; import githubBlackImage from "/public/logos/github-black.png"; import githubWhiteImage from "/public/logos/github-white.png"; // components -import { ProductUpdatesModal } from "components/common"; +import { BreadcrumbLink, ProductUpdatesModal } from "components/common"; import { Breadcrumbs } from "@plane/ui"; import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle"; @@ -25,8 +25,9 @@ export const WorkspaceDashboardHeader = () => { } - label="Dashboard" + link={ + } /> + } />
    diff --git a/web/components/headers/workspace-settings.tsx b/web/components/headers/workspace-settings.tsx index 625b7991c..5ced55204 100644 --- a/web/components/headers/workspace-settings.tsx +++ b/web/components/headers/workspace-settings.tsx @@ -8,6 +8,7 @@ import { observer } from "mobx-react-lite"; // components import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle"; import { WORKSPACE_SETTINGS_LINKS } from "constants/workspace"; +import { BreadcrumbLink } from "components/common"; export interface IWorkspaceSettingHeader { title: string; @@ -27,12 +28,16 @@ export const WorkspaceSettingHeader: FC = observer((pro } - link={`/${workspaceSlug}/settings`} + link={ + } + /> + } />
    - + } />
    @@ -40,7 +45,9 @@ export const WorkspaceSettingHeader: FC = observer((pro className="flex-shrink-0 block sm:block md:hidden lg:hidden" maxHeight="lg" customButton={ - {title} + + {title} + } placement="bottom-start" closeOnSelect diff --git a/web/components/issues/draft-issue-form.tsx b/web/components/issues/draft-issue-form.tsx index 79b91ef40..cfd6370fa 100644 --- a/web/components/issues/draft-issue-form.tsx +++ b/web/components/issues/draft-issue-form.tsx @@ -170,17 +170,6 @@ export const DraftIssueForm: FC = observer((props) => { // handleClose(); // }; - useEffect(() => { - if (!isOpen || data) return; - - setLocalStorageValue( - JSON.stringify({ - ...payload, - }) - ); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [JSON.stringify(payload), isOpen, data]); - // const onClose = () => { // handleClose(); // }; @@ -256,14 +245,6 @@ export const DraftIssueForm: FC = observer((props) => { .finally(() => setIAmFeelingLucky(false)); }; - useEffect(() => { - reset({ - ...defaultValues, - ...(prePopulatedData ?? {}), - ...(data ?? {}), - }); - }, [prePopulatedData, reset, data]); - useEffect(() => { setFocus("name"); }, [setFocus]); diff --git a/web/components/issues/issue-layouts/empty-states/module.tsx b/web/components/issues/issue-layouts/empty-states/module.tsx index aa3a8dc19..109a903a2 100644 --- a/web/components/issues/issue-layouts/empty-states/module.tsx +++ b/web/components/issues/issue-layouts/empty-states/module.tsx @@ -2,7 +2,7 @@ import { useState } from "react"; import { observer } from "mobx-react-lite"; import { PlusIcon } from "lucide-react"; // hooks -import { useApplication, useIssueDetail, useIssues, useUser } from "hooks/store"; +import { useApplication, useIssues, useUser } from "hooks/store"; import useToast from "hooks/use-toast"; // components import { EmptyState } from "components/common"; @@ -29,7 +29,6 @@ export const ModuleEmptyState: React.FC = observer((props) => { const [moduleIssuesListModal, setModuleIssuesListModal] = useState(false); // store hooks const { issues } = useIssues(EIssuesStoreType.MODULE); - const { updateIssue, fetchIssue } = useIssueDetail(); const { commandPalette: { toggleCreateIssueModal }, diff --git a/web/components/issues/issue-layouts/spreadsheet/base-spreadsheet-root.tsx b/web/components/issues/issue-layouts/spreadsheet/base-spreadsheet-root.tsx index a5667f99d..54df6ca24 100644 --- a/web/components/issues/issue-layouts/spreadsheet/base-spreadsheet-root.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/base-spreadsheet-root.tsx @@ -97,6 +97,7 @@ export const BaseSpreadsheetRoot = observer((props: IBaseSpreadsheetRoot) => { portalElement={portalElement} /> ), + // eslint-disable-next-line react-hooks/exhaustive-deps [handleIssues] ); diff --git a/web/components/issues/issue-modal/form.tsx b/web/components/issues/issue-modal/form.tsx index 703a9783f..31cb9dd66 100644 --- a/web/components/issues/issue-modal/form.tsx +++ b/web/components/issues/issue-modal/form.tsx @@ -132,6 +132,7 @@ export const IssueFormRoot: FC = observer((props) => { parent_id: formData.parent_id, }); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [projectId]); const issueName = watch("name"); diff --git a/web/components/project/form.tsx b/web/components/project/form.tsx index f4ab3e846..5be7033a4 100644 --- a/web/components/project/form.tsx +++ b/web/components/project/form.tsx @@ -1,4 +1,4 @@ -import { FC, useEffect } from "react"; +import { FC, useEffect, useState } from "react"; import { Controller, useForm } from "react-hook-form"; // hooks import { useApplication, useProject, useWorkspace } from "hooks/store"; @@ -29,6 +29,8 @@ const projectService = new ProjectService(); export const ProjectDetailsForm: FC = (props) => { const { project, workspaceSlug, isAdmin } = props; + // states + const [isLoading, setIsLoading] = useState(false); // store hooks const { eventTracker: { postHogEventTracker }, @@ -45,7 +47,7 @@ export const ProjectDetailsForm: FC = (props) => { setValue, setError, reset, - formState: { errors, isSubmitting }, + formState: { errors }, } = useForm({ defaultValues: { ...project, @@ -114,6 +116,7 @@ export const ProjectDetailsForm: FC = (props) => { const onSubmit = async (formData: IProject) => { if (!workspaceSlug) return; + setIsLoading(true); const payload: Partial = { name: formData.name, @@ -139,6 +142,10 @@ export const ProjectDetailsForm: FC = (props) => { else await handleUpdateChange(payload); }); else await handleUpdateChange(payload); + + setTimeout(() => { + setIsLoading(false); + }, 300); }; const currentNetwork = NETWORK_CHOICES.find((n) => n.key === project?.network); @@ -308,8 +315,8 @@ export const ProjectDetailsForm: FC = (props) => {
    <> - Created on {renderFormattedDate(project?.created_at)} diff --git a/web/components/workspace/settings/workspace-details.tsx b/web/components/workspace/settings/workspace-details.tsx index 3063855fd..87313c87d 100644 --- a/web/components/workspace/settings/workspace-details.tsx +++ b/web/components/workspace/settings/workspace-details.tsx @@ -32,6 +32,7 @@ const fileService = new FileService(); export const WorkspaceDetails: FC = observer(() => { // states + const [isLoading, setIsLoading] = useState(false); const [deleteWorkspaceModal, setDeleteWorkspaceModal] = useState(false); const [isImageRemoving, setIsImageRemoving] = useState(false); const [isImageUploadModalOpen, setIsImageUploadModalOpen] = useState(false); @@ -51,7 +52,7 @@ export const WorkspaceDetails: FC = observer(() => { control, reset, watch, - formState: { errors, isSubmitting }, + formState: { errors }, } = useForm({ defaultValues: { ...defaultValues, ...currentWorkspace }, }); @@ -59,6 +60,8 @@ export const WorkspaceDetails: FC = observer(() => { const onSubmit = async (formData: IWorkspace) => { if (!currentWorkspace) return; + setIsLoading(true); + const payload: Partial = { logo: formData.logo, name: formData.name, @@ -83,6 +86,9 @@ export const WorkspaceDetails: FC = observer(() => { }); console.error(err); }); + setTimeout(() => { + setIsLoading(false); + }, 300); }; const handleRemoveLogo = () => { @@ -289,8 +295,8 @@ export const WorkspaceDetails: FC = observer(() => { {isAdmin && (
    -
    )} diff --git a/web/layouts/admin-layout/header.tsx b/web/layouts/admin-layout/header.tsx index f86abf6e6..2607fe91d 100644 --- a/web/layouts/admin-layout/header.tsx +++ b/web/layouts/admin-layout/header.tsx @@ -5,6 +5,7 @@ import { observer } from "mobx-react-lite"; import { Breadcrumbs } from "@plane/ui"; // icons import { Settings } from "lucide-react"; +import { BreadcrumbLink } from "components/common"; export interface IInstanceAdminHeader { title?: string; @@ -21,11 +22,15 @@ export const InstanceAdminHeader: FC = observer((props) => } - label="Settings" - link="/god-mode" + link={ + } + /> + } /> - + } />
    )} diff --git a/web/lib/app-provider.tsx b/web/lib/app-provider.tsx index 027800cd8..dad6253c9 100644 --- a/web/lib/app-provider.tsx +++ b/web/lib/app-provider.tsx @@ -47,7 +47,7 @@ export const AppProvider: FC = observer((props) => { - {/* = observer((props) => { posthogHost={envConfig?.posthog_host || null} > {children} - */} - {children} + diff --git a/web/lib/wrappers/posthog-wrapper.tsx b/web/lib/wrappers/posthog-wrapper.tsx index 6ce830517..f310f0c39 100644 --- a/web/lib/wrappers/posthog-wrapper.tsx +++ b/web/lib/wrappers/posthog-wrapper.tsx @@ -40,9 +40,9 @@ const PosthogWrapper: FC = (props) => { posthog.init(posthogAPIKey, { api_host: posthogHost || "https://app.posthog.com", // Enable debug mode in development - loaded: (posthog) => { - if (process.env.NODE_ENV === "development") posthog.debug(); - }, + // loaded: (posthog) => { + // if (process.env.NODE_ENV === "development") posthog.debug(); + // }, autocapture: false, capture_pageview: false, // Disable automatic pageview capture, as we capture manually }); diff --git a/web/pages/profile/index.tsx b/web/pages/profile/index.tsx index 3174c53f3..294ef3574 100644 --- a/web/pages/profile/index.tsx +++ b/web/pages/profile/index.tsx @@ -39,6 +39,7 @@ const fileService = new FileService(); const ProfileSettingsPage: NextPageWithLayout = observer(() => { // states + const [isLoading, setIsLoading] = useState(false); const [isRemoving, setIsRemoving] = useState(false); const [isImageUploadModalOpen, setIsImageUploadModalOpen] = useState(false); const [deactivateAccountModal, setDeactivateAccountModal] = useState(false); @@ -48,7 +49,7 @@ const ProfileSettingsPage: NextPageWithLayout = observer(() => { reset, watch, control, - formState: { errors, isSubmitting }, + formState: { errors }, } = useForm({ defaultValues }); // toast alert const { setToastAlert } = useToast(); @@ -62,6 +63,7 @@ const ProfileSettingsPage: NextPageWithLayout = observer(() => { }, [myProfile, reset]); const onSubmit = async (formData: IUser) => { + setIsLoading(true); const payload: Partial = { first_name: formData.first_name, last_name: formData.last_name, @@ -87,6 +89,9 @@ const ProfileSettingsPage: NextPageWithLayout = observer(() => { message: "There was some error in updating your profile. Please try again.", }) ); + setTimeout(() => { + setIsLoading(false); + }, 300); }; const handleDelete = (url: string | null | undefined, updateUser: boolean = false) => { @@ -388,8 +393,8 @@ const ProfileSettingsPage: NextPageWithLayout = observer(() => {
    -