[WEB-5396] chore: refactor pages to use function declarations (#4669)

This commit is contained in:
Aaron
2025-11-11 18:24:38 +05:30
committed by GitHub
parent 3c31b72819
commit b21e796802
128 changed files with 1197 additions and 1116 deletions
@@ -102,8 +102,8 @@ export class IframelyController {
errorCode = "TIMEOUT";
break;
default:
errorMessage = "An unexpected error occurred";
errorCode = "SERVER_ERROR";
errorMessage = "An unexpected error occurred";
errorCode = "SERVER_ERROR";
}
return res.status(status).json({
+1 -1
View File
@@ -199,7 +199,7 @@ class PlaneOAuthService {
*/
getPlaneOAuthRedirectUrl(clientId: string, redirectUri: string, state: string): string {
try {
const baseUrl = env.IS_MULTI_TENANT === "1" ? env.API_BASE_URL : env.APP_BASE_URL
const baseUrl = env.IS_MULTI_TENANT === "1" ? env.API_BASE_URL : env.APP_BASE_URL;
const data = new URLSearchParams({
client_id: clientId,
response_type: "code",
+1 -1
View File
@@ -4,7 +4,7 @@ import { observer } from "mobx-react";
// hooks
import { usePublish } from "@/hooks/store/publish";
import CreateIssueModal from "@/plane-web/components/intake/create/create-issue-modal";
import type { Route } from "./+types/layout";
import type { Route } from "./+types/page";
const IssuesPage = observer((props: Route.ComponentProps) => {
const { params } = props;
+1 -1
View File
@@ -6,7 +6,7 @@ import { useMember } from "@/hooks/store/use-member";
import { useStates } from "@/hooks/store/use-state";
// components
import { PageDetailsMainContent } from "@/plane-web/components/pages";
import type { Route } from "./+types/layout";
import type { Route } from "./+types/page";
export default function PageDetailsPage(props: Route.ComponentProps) {
const { params } = props;
@@ -1,7 +1,6 @@
"use client";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
import { Outlet } from "react-router";
import { AuthenticationWrapper } from "@/lib/wrappers/authentication-wrapper";
import { WithFeatureFlagHOC } from "@/plane-web/components/feature-flags";
@@ -13,11 +12,12 @@ import { PiChatLayout } from "@/plane-web/components/pi-chat/layout";
import { useWorkspaceFeatures } from "@/plane-web/hooks/store";
import { WorkspaceAuthWrapper } from "@/plane-web/layouts/workspace-wrapper";
import { EWorkspaceFeatures } from "@/plane-web/types/workspace-feature";
import type { Route } from "./+types/layout";
import { PiAppSidebar } from "./sidebar";
function PiLayout() {
function PiLayout({ params }: Route.ComponentProps) {
// router
const { workspaceSlug } = useParams();
const { workspaceSlug } = params;
const { isWorkspaceFeatureEnabled } = useWorkspaceFeatures();
return (
@@ -11,7 +11,7 @@ import { useUser } from "@/hooks/store/user/user-user";
import { NewConversation } from "@/plane-web/components/pi-chat/conversation/new-converstaion";
import { InputBox } from "@/plane-web/components/pi-chat/input";
const NewChatPage = observer(() => {
function NewChatPage() {
// store hooks
const { data: currentUser } = useUser();
@@ -27,6 +27,6 @@ const NewChatPage = observer(() => {
</div>
</>
);
});
}
export default NewChatPage;
export default observer(NewChatPage);
@@ -2,14 +2,12 @@
import { useEffect } from "react";
import { observer } from "mobx-react";
import { cn } from "@plane/utils";
import { PageHead } from "@/components/core/page-title";
import { PiChatDetail } from "@/plane-web/components/pi-chat/detail";
import { AllChats } from "@/plane-web/components/pi-chat/list/root";
import { usePiChat } from "@/plane-web/hooks/store/use-pi-chat";
const NewChatPage = observer(() => {
function NewChatPage() {
// store hooks
const { initPiChat } = usePiChat();
@@ -22,6 +20,6 @@ const NewChatPage = observer(() => {
<PiChatDetail isFullScreen />
</>
);
});
}
export default NewChatPage;
export default observer(NewChatPage);
@@ -8,7 +8,7 @@ import { CustomerUpgrade } from "@/plane-web/components/customers";
import { EpicPeekOverview } from "@/plane-web/components/epics/peek-overview";
import { useCustomers } from "@/plane-web/hooks/store";
const CustomersLayout = observer(() => {
function CustomersLayout() {
// hooks
const { loader, isCustomersFeatureEnabled } = useCustomers();
// derived values
@@ -30,6 +30,6 @@ const CustomersLayout = observer(() => {
)}
</WorkspaceAccessWrapper>
);
});
}
export default CustomersLayout;
export default observer(CustomersLayout);
@@ -1,6 +1,5 @@
"use client";
import { useParams } from "next/navigation";
import { Outlet } from "react-router";
import useSWR from "swr";
// plane web components
@@ -9,19 +8,17 @@ import { DashboardsFeatureFlagFallback } from "@/plane-web/components/dashboards
import { WithFeatureFlagHOC } from "@/plane-web/components/feature-flags";
// plane web hooks
import { useDashboards } from "@/plane-web/hooks/store";
import type { Route } from "./+types/layout";
export default function WorkspaceDashboardsLayout() {
export default function WorkspaceDashboardsLayout({ params }: Route.ComponentProps) {
// navigation
const { workspaceSlug } = useParams();
const { workspaceSlug } = params;
// store hooks
const {
workspaceDashboards: { fetchDashboards },
} = useDashboards();
useSWR(
workspaceSlug ? `WORKSPACE_DASHBOARDS_LIST_${workspaceSlug.toString()}` : null,
workspaceSlug ? () => fetchDashboards() : null
);
useSWR(`WORKSPACE_DASHBOARDS_LIST_${workspaceSlug}`, () => fetchDashboards());
return (
<WorkspaceAccessWrapper pageKey="dashboards">
@@ -1,8 +1,6 @@
"use client";
import React from "react";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
import { useTheme } from "next-themes";
import useSWR from "swr";
import { useTranslation } from "@plane/i18n";
@@ -23,11 +21,12 @@ import { useFlag, useWorkspaceFeatures } from "@/plane-web/hooks/store";
import { useProjectAdvanced } from "@/plane-web/hooks/store/projects/use-projects";
import { useInitiatives } from "@/plane-web/hooks/store/use-initiatives";
import { EWorkspaceFeatures } from "@/plane-web/types/workspace-feature";
import type { Route } from "./+types/page";
const InitiativeDetailsPage = observer(() => {
function InitiativeDetailsPage({ params }: Route.ComponentProps) {
// router
const router = useAppRouter();
const { workspaceSlug, initiativeId } = useParams();
const { workspaceSlug, initiativeId } = params;
// hooks
const { t } = useTranslation();
@@ -42,20 +41,17 @@ const InitiativeDetailsPage = observer(() => {
const { isWorkspaceFeatureEnabled } = useWorkspaceFeatures();
// fetching issue details
const { isLoading, error } = useSWR(
workspaceSlug && initiativeId ? `INITIATIVE_DETAIL_${workspaceSlug}_${initiativeId}` : null,
workspaceSlug && initiativeId
? () => fetchInitiativeDetails(workspaceSlug.toString(), initiativeId.toString())
: null
const { isLoading, error } = useSWR(`INITIATIVE_DETAIL_${workspaceSlug}_${initiativeId}`, () =>
fetchInitiativeDetails(workspaceSlug, initiativeId)
);
// derived values
const initiativeDetails = getInitiativeById(initiativeId.toString());
const initiativeDetails = getInitiativeById(initiativeId);
const loader = !initiativeDetails || isLoading;
const pageTitle = initiativeDetails ? `Initiative - ${initiativeDetails.name}` : "Initiative";
const isProjectGroupingFeatureFlagEnabled = useFlag(workspaceSlug, "PROJECT_GROUPING");
const isProjectGroupingEnabled =
isWorkspaceFeatureEnabled(EWorkspaceFeatures.IS_PROJECT_GROUPING_ENABLED) &&
useFlag(workspaceSlug.toString(), "PROJECT_GROUPING");
isWorkspaceFeatureEnabled(EWorkspaceFeatures.IS_PROJECT_GROUPING_ENABLED) && isProjectGroupingFeatureFlagEnabled;
// fetch initiative project analytics count
useSWR(
@@ -72,18 +68,12 @@ const InitiativeDetailsPage = observer(() => {
);
// fetch initiative project attributes
useSWR(
workspaceSlug &&
isProjectGroupingEnabled &&
initiativeDetails?.project_ids &&
initiativeDetails?.project_ids.length > 0
isProjectGroupingEnabled && initiativeDetails?.project_ids && initiativeDetails?.project_ids.length > 0
? ["initiativeProjectAttributes", workspaceSlug, isProjectGroupingEnabled, ...initiativeDetails?.project_ids]
: null,
workspaceSlug &&
isProjectGroupingEnabled &&
initiativeDetails?.project_ids &&
initiativeDetails?.project_ids.length > 0
isProjectGroupingEnabled && initiativeDetails?.project_ids && initiativeDetails?.project_ids.length > 0
? () =>
fetchProjectAttributes(workspaceSlug.toString(), {
fetchProjectAttributes(workspaceSlug, {
project_ids: initiativeDetails?.project_ids?.join(","),
})
: null
@@ -118,13 +108,10 @@ const InitiativeDetailsPage = observer(() => {
</div>
</Loader>
) : (
workspaceSlug &&
initiativeDetails && (
<InitiativeDetailRoot workspaceSlug={workspaceSlug.toString()} initiativeId={initiativeId.toString()} />
)
<InitiativeDetailRoot workspaceSlug={workspaceSlug} initiativeId={initiativeId} />
)}
</>
);
});
}
export default InitiativeDetailsPage;
export default observer(InitiativeDetailsPage);
@@ -1,8 +1,6 @@
"use client";
import React from "react";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
import { useTheme } from "next-themes";
import useSWR from "swr";
import { useTranslation } from "@plane/i18n";
@@ -18,16 +16,16 @@ import { useProject } from "@/hooks/store/use-project";
import { useAppRouter } from "@/hooks/use-app-router";
import { InitiativeScopeRoot } from "@/plane-web/components/initiatives/scope/root";
// Plane-web
import { useFlag } from "@/plane-web/hooks/store";
import * as store from "@/plane-web/hooks/store";
import { useFlag, useWorkspaceFeatures } from "@/plane-web/hooks/store";
import { useProjectAdvanced } from "@/plane-web/hooks/store/projects/use-projects";
import { useInitiatives } from "@/plane-web/hooks/store/use-initiatives";
import { EWorkspaceFeatures } from "@/plane-web/types/workspace-feature";
import type { Route } from "./+types/page";
const IssueDetailsPage = observer(() => {
function IssueDetailsPage({ params }: Route.ComponentProps) {
// router
const router = useAppRouter();
const { workspaceSlug, initiativeId } = useParams();
const { workspaceSlug, initiativeId } = params;
// hooks
const { resolvedTheme } = useTheme();
// store hooks
@@ -43,38 +41,32 @@ const IssueDetailsPage = observer(() => {
const { t } = useTranslation();
const { isWorkspaceFeatureEnabled } = store.useWorkspaceFeatures();
const { isWorkspaceFeatureEnabled } = useWorkspaceFeatures();
// fetching issue details
const { isLoading, error } = useSWR(
workspaceSlug && initiativeId ? `INITIATIVE_DETAIL_${workspaceSlug}_${initiativeId}` : null,
workspaceSlug && initiativeId
? () => fetchInitiativeDetails(workspaceSlug.toString(), initiativeId.toString())
: null
const { isLoading, error } = useSWR(`INITIATIVE_DETAIL_${workspaceSlug}_${initiativeId}`, () =>
fetchInitiativeDetails(workspaceSlug, initiativeId)
);
// fetch initiative epics
const { isLoading: isEpicsLoading } = useSWR(
workspaceSlug && initiativeId ? `INITIATIVE_EPICS_${workspaceSlug}_${initiativeId}` : null,
workspaceSlug && initiativeId
? () => fetchInitiativeEpicsDetail(workspaceSlug.toString(), initiativeId.toString())
: null
const { isLoading: isEpicsLoading } = useSWR(`INITIATIVE_EPICS_${workspaceSlug}_${initiativeId}`, () =>
fetchInitiativeEpicsDetail(workspaceSlug, initiativeId)
);
// derived values
const initiativeDetails = getInitiativeById(initiativeId.toString());
const initiativeDetails = getInitiativeById(initiativeId);
const loader = !initiativeDetails || isLoading || isEpicsLoading;
const pageTitle = initiativeDetails ? `Initiative - ${initiativeDetails.name} | Scope` : "Initiative | Scope";
const isProjectGroupingFeatureFlagEnabled = useFlag(workspaceSlug, "PROJECT_GROUPING");
const isProjectGroupingEnabled =
isWorkspaceFeatureEnabled(EWorkspaceFeatures.IS_PROJECT_GROUPING_ENABLED) &&
useFlag(workspaceSlug.toString(), "PROJECT_GROUPING");
isWorkspaceFeatureEnabled(EWorkspaceFeatures.IS_PROJECT_GROUPING_ENABLED) && isProjectGroupingFeatureFlagEnabled;
// fetch initiative project analytics count
useSWR(
workspaceSlug && initiativeDetails?.project_ids && initiativeDetails?.project_ids.length > 0
initiativeDetails?.project_ids && initiativeDetails?.project_ids.length > 0
? ["initiativeProjectAnalyticsCount", workspaceSlug, ...initiativeDetails?.project_ids]
: null,
workspaceSlug && initiativeDetails?.project_ids && initiativeDetails?.project_ids.length > 0
initiativeDetails?.project_ids && initiativeDetails?.project_ids.length > 0
? () =>
fetchProjectAnalyticsCount(workspaceSlug.toString(), {
fetchProjectAnalyticsCount(workspaceSlug, {
project_ids: initiativeDetails?.project_ids?.join(","),
fields: "total_issues,completed_issues",
})
@@ -82,18 +74,12 @@ const IssueDetailsPage = observer(() => {
);
// fetch initiative project attributes
useSWR(
workspaceSlug &&
isProjectGroupingEnabled &&
initiativeDetails?.project_ids &&
initiativeDetails?.project_ids.length > 0
isProjectGroupingEnabled && initiativeDetails?.project_ids && initiativeDetails?.project_ids.length > 0
? ["initiativeProjectAttributes", workspaceSlug, isProjectGroupingEnabled, ...initiativeDetails?.project_ids]
: null,
workspaceSlug &&
isProjectGroupingEnabled &&
initiativeDetails?.project_ids &&
initiativeDetails?.project_ids.length > 0
isProjectGroupingEnabled && initiativeDetails?.project_ids && initiativeDetails?.project_ids.length > 0
? () =>
fetchProjectAttributes(workspaceSlug.toString(), {
fetchProjectAttributes(workspaceSlug, {
project_ids: initiativeDetails?.project_ids?.join(","),
})
: null
@@ -115,10 +101,10 @@ const IssueDetailsPage = observer(() => {
) : loader ? (
<ListLayoutLoader />
) : (
workspaceSlug && initiativeDetails && <InitiativeScopeRoot />
initiativeDetails && <InitiativeScopeRoot />
)}
</>
);
});
}
export default IssueDetailsPage;
export default observer(IssueDetailsPage);
@@ -7,7 +7,7 @@ import { useWorkspace } from "@/hooks/store/use-workspace";
// plane web components
import { InitiativesPageRoot } from "@/plane-web/components/initiatives/layout/page";
const InitiativesPage = observer(() => {
function InitiativesPage() {
// store hooks
const { currentWorkspace } = useWorkspace();
@@ -20,5 +20,5 @@ const InitiativesPage = observer(() => {
<InitiativesPageRoot />
</>
);
});
export default InitiativesPage;
}
export default observer(InitiativesPage);
@@ -1,7 +1,6 @@
"use client";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// components
import { Outlet } from "react-router";
import { PageHead } from "@/components/core/page-title";
@@ -13,10 +12,11 @@ import { InitiativesUpgrade } from "@/plane-web/components/initiatives/upgrade";
// plane web hooks
import { useWorkspaceFeatures } from "@/plane-web/hooks/store";
import { EWorkspaceFeatures } from "@/plane-web/types/workspace-feature";
import type { Route } from "./+types/layout";
const InitiativesLayout = observer(() => {
function InitiativesLayout({ params }: Route.ComponentProps) {
// router
const { workspaceSlug } = useParams();
const { workspaceSlug } = params;
// store
const { currentWorkspace } = useWorkspace();
// plane web stores
@@ -31,7 +31,7 @@ const InitiativesLayout = observer(() => {
<WorkspaceAccessWrapper pageKey="initiatives">
{shouldUpgrade ? (
<div className="h-full w-full max-w-5xl mx-auto flex items-center justify-center">
<InitiativesUpgrade workspaceSlug={workspaceSlug?.toString()} redirect />
<InitiativesUpgrade workspaceSlug={workspaceSlug} redirect />
</div>
) : (
<>
@@ -41,6 +41,6 @@ const InitiativesLayout = observer(() => {
)}
</WorkspaceAccessWrapper>
);
});
}
export default InitiativesLayout;
export default observer(InitiativesLayout);
@@ -12,13 +12,8 @@ import { AutomationsListWrapper } from "@/plane-web/components/automations/list/
import type { Route } from "./+types/layout";
import { ProjectAutomationDetailsHeader } from "./header";
const AutomationDetailsLayout: React.FC<Route.ComponentProps> = observer((props) => {
const {
params: { automationId: automationIdParam, projectId: projectIdParam, workspaceSlug: workspaceSlugParam },
} = props;
const automationId = automationIdParam?.toString();
const projectId = projectIdParam?.toString();
const workspaceSlug = workspaceSlugParam?.toString();
function AutomationDetailsLayout({ params }: Route.ComponentProps) {
const { automationId, projectId, workspaceSlug } = params;
return (
<AutomationsListWrapper projectId={projectId} workspaceSlug={workspaceSlug}>
@@ -38,6 +33,6 @@ const AutomationDetailsLayout: React.FC<Route.ComponentProps> = observer((props)
</AutomationsDetailsWrapper>
</AutomationsListWrapper>
);
});
}
export default AutomationDetailsLayout;
export default observer(AutomationDetailsLayout);
@@ -1,6 +1,5 @@
"use client";
import React from "react";
import { observer } from "mobx-react";
// plane imports
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
@@ -13,19 +12,11 @@ import { useUserPermissions } from "@/hooks/store/user/user-permissions";
// plane web components
import { AutomationDetailsMainContentRoot } from "@/plane-web/components/automations/details/main-content/root";
import { AutomationDetailsSidebarRoot } from "@/plane-web/components/automations/details/sidebar/root";
import type { Route } from "./+types/page";
type Props = {
params: {
automationId: string;
};
};
const AutomationDetailsPage: React.FC<Props> = observer((props) => {
function AutomationDetailsPage({ params }: Route.ComponentProps) {
// params
const {
params: { automationId: automationIdParam },
} = props;
const automationId = automationIdParam?.toString();
const { automationId } = params;
// store hooks
const { workspaceUserInfo, allowPermissions } = useUserPermissions();
const { currentProjectDetails: projectDetails } = useProject();
@@ -46,6 +37,6 @@ const AutomationDetailsPage: React.FC<Props> = observer((props) => {
</div>
</>
);
});
}
export default AutomationDetailsPage;
export default observer(AutomationDetailsPage);
@@ -1,23 +1,22 @@
"use client";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// components
import { PageHead } from "@/components/core/page-title";
// hooks
import { useProject } from "@/hooks/store/use-project";
// plane web components
import { ProjectEpicsLayoutRoot } from "@/plane-web/components/issues/issue-layouts/epic-layout-root";
import type { Route } from "./+types/page";
const ProjectEpicsPage = observer(() => {
function ProjectEpicsPage({ params }: Route.ComponentProps) {
// router
const { workspaceSlug, projectId } = useParams();
const { projectId } = params;
// store hooks
const { getProjectById } = useProject();
// derived values
const project = projectId ? getProjectById(projectId.toString()) : undefined;
const project = getProjectById(projectId);
const pageTitle = project?.name ? `${project?.name} - Epics` : undefined;
if (!workspaceSlug || !projectId) return <></>;
return (
<>
@@ -29,6 +28,6 @@ const ProjectEpicsPage = observer(() => {
</div>
</>
);
});
}
export default ProjectEpicsPage;
export default observer(ProjectEpicsPage);
@@ -1,7 +1,6 @@
"use client";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
import { Outlet } from "react-router";
// plane imports
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
@@ -14,17 +13,18 @@ import { useUserPermissions } from "@/hooks/store/user/user-permissions";
// plane web imports
import { EpicsEmptyState } from "@/plane-web/components/epics/settings/empty-state";
import { useProjectAdvanced } from "@/plane-web/hooks/store/projects/use-projects";
import type { Route } from "./+types/layout";
const EpicsLayout = observer(() => {
function EpicsLayout({ params }: Route.ComponentProps) {
// router
const { workspaceSlug, projectId } = useParams();
const { workspaceSlug, projectId } = params;
// store hooks
const { getProjectById } = useProject();
const { getProjectFeatures } = useProjectAdvanced();
const { allowPermissions } = useUserPermissions();
// derived values
const project = getProjectById(projectId?.toString());
const projectFeatures = getProjectFeatures(projectId?.toString());
const project = getProjectById(projectId);
const projectFeatures = getProjectFeatures(projectId);
const isEpicsEnabled = projectFeatures?.is_epic_enabled;
const pageTitle = project?.name ? `${project?.name} - Epics` : undefined;
@@ -32,7 +32,7 @@ const EpicsLayout = observer(() => {
if (project && !isEpicsEnabled)
return (
<div className="flex items-center justify-center h-full w-full">
<EpicsEmptyState workspaceSlug={workspaceSlug.toString()} projectId={projectId.toString()} redirect />
<EpicsEmptyState workspaceSlug={workspaceSlug} projectId={projectId} redirect />
</div>
);
@@ -58,6 +58,6 @@ const EpicsLayout = observer(() => {
<Outlet />
</>
);
});
}
export default EpicsLayout;
export default observer(EpicsLayout);
@@ -1,12 +1,12 @@
"use client";
import { useParams } from "next/navigation";
// components
import { ProjectOverviewRoot } from "@/plane-web/components/project-overview/details/root";
import type { Route } from "./+types/page";
const ProjectOverviewPage = () => {
const { workspaceSlug, projectId } = useParams();
return <ProjectOverviewRoot workspaceSlug={workspaceSlug?.toString()} projectId={projectId?.toString()} />;
};
function ProjectOverviewPage({ params }: Route.ComponentProps) {
const { workspaceSlug, projectId } = params;
return <ProjectOverviewRoot workspaceSlug={workspaceSlug} projectId={projectId} />;
}
export default ProjectOverviewPage;
@@ -4,6 +4,8 @@ import { observer } from "mobx-react";
// plane web imports
import { PiChatDetail } from "@/plane-web/components/pi-chat/detail";
const PiChatPage = observer(() => <PiChatDetail isFullScreen isProjectLevel />);
function PiChatPage() {
return <PiChatDetail isFullScreen isProjectLevel />;
}
export default PiChatPage;
export default observer(PiChatPage);
@@ -1,7 +1,6 @@
"use client";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
import { Outlet } from "react-router";
// plane web imports
import { WithFeatureFlagHOC } from "@/plane-web/components/feature-flags";
@@ -9,13 +8,14 @@ import { EmptyPiChat } from "@/plane-web/components/pi-chat/empty";
import { PiChatLayout } from "@/plane-web/components/pi-chat/layout";
import { useWorkspaceFeatures } from "@/plane-web/hooks/store";
import { EWorkspaceFeatures } from "@/plane-web/types/workspace-feature";
import type { Route } from "./+types/layout";
export default observer(function Layout() {
function Layout({ params }: Route.ComponentProps) {
// router
const { workspaceSlug } = useParams();
const { workspaceSlug } = params;
const { isWorkspaceFeatureEnabled } = useWorkspaceFeatures();
return isWorkspaceFeatureEnabled(EWorkspaceFeatures.IS_PI_ENABLED) ? (
<WithFeatureFlagHOC workspaceSlug={workspaceSlug?.toString()} flag="PI_CHAT" fallback={<EmptyPiChat />}>
<WithFeatureFlagHOC workspaceSlug={workspaceSlug} flag="PI_CHAT" fallback={<EmptyPiChat />}>
<PiChatLayout isFullScreen isProjectLevel shouldRenderSidebarToggle>
<Outlet />
</PiChatLayout>
@@ -23,4 +23,6 @@ export default observer(function Layout() {
) : (
<EmptyPiChat />
);
});
}
export default observer(Layout);
@@ -11,7 +11,7 @@ import { useUser } from "@/hooks/store/user/user-user";
import { NewConversation } from "@/plane-web/components/pi-chat/conversation/new-converstaion";
import { InputBox } from "@/plane-web/components/pi-chat/input";
const NewChatPage = observer(() => {
function NewChatPage() {
// store hooks
const { data: currentUser } = useUser();
@@ -27,6 +27,6 @@ const NewChatPage = observer(() => {
</div>
</>
);
});
}
export default NewChatPage;
export default observer(NewChatPage);
@@ -4,7 +4,7 @@ import { observer } from "mobx-react";
import { PiChatDetail } from "@/plane-web/components/pi-chat/detail";
import { usePiChat } from "@/plane-web/hooks/store/use-pi-chat";
const NewChatPage = observer(() => {
function NewChatPage() {
// store hooks
const { initPiChat } = usePiChat();
@@ -12,5 +12,5 @@ const NewChatPage = observer(() => {
initPiChat();
}, []);
return <PiChatDetail isFullScreen isProjectLevel />;
});
export default NewChatPage;
}
export default observer(NewChatPage);
@@ -1,19 +1,19 @@
"use client";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// plane web components
import { SidebarHamburgerToggle } from "@/components/core/sidebar/sidebar-menu-hamburger-toggle";
import { isSidebarToggleVisible } from "@/plane-web/components/desktop";
import { WithFeatureFlagHOC } from "@/plane-web/components/feature-flags";
import { AppSearchRoot } from "@/plane-web/components/workspace/search";
import type { Route } from "./+types/page";
const AppSearchPage = observer(() => {
function AppSearchPage({ params }: Route.ComponentProps) {
// router
const { workspaceSlug } = useParams();
const { workspaceSlug } = params;
return (
<WithFeatureFlagHOC workspaceSlug={workspaceSlug?.toString()} flag="ADVANCED_SEARCH" fallback={<></>}>
<WithFeatureFlagHOC workspaceSlug={workspaceSlug} flag="ADVANCED_SEARCH" fallback={<></>}>
{isSidebarToggleVisible() && (
<div className="block bg-custom-sidebar-background-100 p-4 md:hidden">
<SidebarHamburgerToggle />
@@ -22,6 +22,6 @@ const AppSearchPage = observer(() => {
<AppSearchRoot />
</WithFeatureFlagHOC>
);
});
}
export default AppSearchPage;
export default observer(AppSearchPage);
@@ -1,6 +1,5 @@
"use client";
import { useParams } from "next/navigation";
import { Outlet } from "react-router";
import { ETeamspaceNavigationItem } from "@plane/constants";
// components
@@ -11,13 +10,14 @@ import { PageHead } from "@/components/core/page-title";
import { TeamspaceDetailHeader } from "@/plane-web/components/teamspaces/headers/detail-header";
// plane web hooks
import { useTeamspaces } from "@/plane-web/hooks/store";
import type { Route } from "./+types/layout";
export default function TeamspaceOverviewLayout() {
const { teamspaceId } = useParams();
export default function TeamspaceOverviewLayout({ params }: Route.ComponentProps) {
const { teamspaceId } = params;
// store hooks
const { getTeamspaceById } = useTeamspaces();
// derived values
const currentTeam = getTeamspaceById(teamspaceId?.toString());
const currentTeam = getTeamspaceById(teamspaceId);
const pageTitle = currentTeam?.name ? `Teamspace ${currentTeam?.name} - Overview` : undefined;
return (
@@ -1,7 +1,6 @@
"use client";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
import useSWR from "swr";
// components
import { LogoSpinner } from "@/components/common/logo-spinner";
@@ -11,28 +10,29 @@ import { TeamsOverviewRoot } from "@/plane-web/components/teamspaces/overview/ro
import { useFlag, useTeamspaces, useWorkspaceFeatures } from "@/plane-web/hooks/store";
import { useProjectAdvanced } from "@/plane-web/hooks/store/projects/use-projects";
import { EWorkspaceFeatures } from "@/plane-web/types/workspace-feature";
import type { Route } from "./+types/page";
const TeamspaceOverviewPage = observer(() => {
function TeamspaceOverviewPage({ params }: Route.ComponentProps) {
// router
const { workspaceSlug, teamspaceId } = useParams();
const { workspaceSlug, teamspaceId } = params;
// store
const { fetchProjectAttributes } = useProjectAdvanced();
const { loader, getTeamspaceById, getTeamspaceProjectIds } = useTeamspaces();
const { isWorkspaceFeatureEnabled } = useWorkspaceFeatures();
// derived values
const teamspace = getTeamspaceById(teamspaceId?.toString());
const teamspaceProjectIds = getTeamspaceProjectIds(teamspaceId?.toString());
const teamspace = getTeamspaceById(teamspaceId);
const teamspaceProjectIds = getTeamspaceProjectIds(teamspaceId);
const isProjectGroupingFeatureFlagEnabled = useFlag(workspaceSlug, "PROJECT_GROUPING");
const isProjectGroupingEnabled =
isWorkspaceFeatureEnabled(EWorkspaceFeatures.IS_PROJECT_GROUPING_ENABLED) &&
useFlag(workspaceSlug.toString(), "PROJECT_GROUPING");
isWorkspaceFeatureEnabled(EWorkspaceFeatures.IS_PROJECT_GROUPING_ENABLED) && isProjectGroupingFeatureFlagEnabled;
// fetch team project attributes
useSWR(
workspaceSlug && isProjectGroupingEnabled && teamspaceProjectIds && teamspaceProjectIds.length > 0
isProjectGroupingEnabled && teamspaceProjectIds && teamspaceProjectIds.length > 0
? ["teamspaceProjectAttributes", workspaceSlug, isProjectGroupingEnabled, ...teamspaceProjectIds]
: null,
workspaceSlug && isProjectGroupingEnabled && teamspaceProjectIds && teamspaceProjectIds.length > 0
isProjectGroupingEnabled && teamspaceProjectIds && teamspaceProjectIds.length > 0
? () =>
fetchProjectAttributes(workspaceSlug.toString(), {
fetchProjectAttributes(workspaceSlug, {
project_ids: teamspaceProjectIds?.join(","),
})
: null
@@ -46,9 +46,9 @@ const TeamspaceOverviewPage = observer(() => {
);
// Empty state if teamspace is not found
if (!teamspaceId || !teamspace) return null;
if (!teamspace) return null;
return <TeamsOverviewRoot teamspaceId={teamspaceId.toString()} />;
});
return <TeamsOverviewRoot teamspaceId={teamspaceId} />;
}
export default TeamspaceOverviewPage;
export default observer(TeamspaceOverviewPage);
@@ -1,6 +1,5 @@
"use client";
import { useParams } from "next/navigation";
import { Outlet } from "react-router";
import { ETeamspaceNavigationItem } from "@plane/constants";
// components
@@ -11,13 +10,14 @@ import { PageHead } from "@/components/core/page-title";
import { TeamspaceDetailHeader } from "@/plane-web/components/teamspaces/headers/detail-header";
// plane web hooks
import { useTeamspaces } from "@/plane-web/hooks/store";
import type { Route } from "./+types/layout";
export default function TeamspaceCyclesLayout() {
const { teamspaceId } = useParams();
export default function TeamspaceCyclesLayout({ params }: Route.ComponentProps) {
const { teamspaceId } = params;
// store hooks
const { getTeamspaceById } = useTeamspaces();
// derived values
const currentTeam = getTeamspaceById(teamspaceId?.toString());
const currentTeam = getTeamspaceById(teamspaceId);
const pageTitle = currentTeam?.name ? `Teamspace ${currentTeam?.name} - Cycles` : undefined;
return (
@@ -1,7 +1,6 @@
"use client";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
import useSWR from "swr";
// ui
import { Tabs, Loader } from "@plane/ui";
@@ -12,6 +11,7 @@ import { TeamCurrentCyclesRoot } from "@/plane-web/components/teamspaces/cycles/
import { TeamUpcomingCyclesRoot } from "@/plane-web/components/teamspaces/cycles/upcoming";
// plane web hooks
import { useTeamspaceCycles } from "@/plane-web/hooks/store";
import type { Route } from "./+types/page";
const TeamspaceCyclesLoader = ({ height }: { height: string }) =>
Array.from({ length: 3 }).map((_, index) => (
@@ -20,22 +20,18 @@ const TeamspaceCyclesLoader = ({ height }: { height: string }) =>
</Loader>
));
const TeamspaceCyclesPage = observer(() => {
const { workspaceSlug, teamspaceId } = useParams();
function TeamspaceCyclesPage({ params }: Route.ComponentProps) {
const { workspaceSlug, teamspaceId } = params;
// store hooks
const { getTeamspaceCyclesLoader, fetchTeamspaceCycles } = useTeamspaceCycles();
// derived values
const teamspaceCyclesLoader = getTeamspaceCyclesLoader(teamspaceId!.toString());
const teamspaceCyclesLoader = getTeamspaceCyclesLoader(teamspaceId);
const isTeamspaceCyclesLoading = teamspaceCyclesLoader === "init-loader";
// fetch teamspace cycles
useSWR(
workspaceSlug && teamspaceId ? ["teamspaceCycles", workspaceSlug, teamspaceId] : null,
() => fetchTeamspaceCycles(workspaceSlug!.toString(), teamspaceId!.toString()),
{
revalidateOnFocus: false,
revalidateIfStale: false,
}
);
useSWR(["teamspaceCycles", workspaceSlug, teamspaceId], () => fetchTeamspaceCycles(workspaceSlug, teamspaceId), {
revalidateOnFocus: false,
revalidateIfStale: false,
});
const TEAM_CYCLES_TABS = [
{
@@ -44,7 +40,7 @@ const TeamspaceCyclesPage = observer(() => {
content: isTeamspaceCyclesLoading ? (
<TeamspaceCyclesLoader height="256px" />
) : (
<TeamCurrentCyclesRoot teamspaceId={teamspaceId!.toString()} workspaceSlug={workspaceSlug!.toString()} />
<TeamCurrentCyclesRoot teamspaceId={teamspaceId} workspaceSlug={workspaceSlug} />
),
},
{
@@ -53,7 +49,7 @@ const TeamspaceCyclesPage = observer(() => {
content: isTeamspaceCyclesLoading ? (
<TeamspaceCyclesLoader height="98px" />
) : (
<TeamUpcomingCyclesRoot teamspaceId={teamspaceId!.toString()} workspaceSlug={workspaceSlug!.toString()} />
<TeamUpcomingCyclesRoot teamspaceId={teamspaceId} workspaceSlug={workspaceSlug} />
),
},
{
@@ -62,7 +58,7 @@ const TeamspaceCyclesPage = observer(() => {
content: isTeamspaceCyclesLoading ? (
<TeamspaceCyclesLoader height="98px" />
) : (
<TeamCompletedCyclesRoot teamspaceId={teamspaceId!.toString()} workspaceSlug={workspaceSlug!.toString()} />
<TeamCompletedCyclesRoot teamspaceId={teamspaceId} workspaceSlug={workspaceSlug} />
),
},
];
@@ -78,9 +74,9 @@ const TeamspaceCyclesPage = observer(() => {
tabListClassName="my-2 max-w-64"
tabPanelClassName="h-full w-full overflow-hidden overflow-y-auto"
/>
<CyclePeekOverview workspaceSlug={workspaceSlug!.toString()} isArchived={false} />
<CyclePeekOverview workspaceSlug={workspaceSlug} isArchived={false} />
</div>
);
});
}
export default TeamspaceCyclesPage;
export default observer(TeamspaceCyclesPage);
@@ -1,6 +1,5 @@
"use client";
import { useParams } from "next/navigation";
import { Outlet } from "react-router";
import { ETeamspaceNavigationItem } from "@plane/constants";
// components
@@ -11,13 +10,14 @@ import { PageHead } from "@/components/core/page-title";
import { TeamspaceDetailHeader } from "@/plane-web/components/teamspaces/headers/detail-header";
// plane web hooks
import { useTeamspaces } from "@/plane-web/hooks/store";
import type { Route } from "./+types/layout";
export default function TeamspaceWorkItemsLayout() {
const { teamspaceId } = useParams();
export default function TeamspaceWorkItemsLayout({ params }: Route.ComponentProps) {
const { teamspaceId } = params;
// store hooks
const { getTeamspaceById } = useTeamspaces();
// derived values
const currentTeam = getTeamspaceById(teamspaceId?.toString());
const currentTeam = getTeamspaceById(teamspaceId);
const pageTitle = currentTeam?.name ? `Teamspace ${currentTeam?.name} - Issues` : undefined;
return (
@@ -1,25 +1,21 @@
"use client";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// components
import { PageHead } from "@/components/core/page-title";
// plane web components
import { TeamspaceLayoutRoot } from "@/plane-web/components/issues/issue-layouts/roots/teamspace-layout-root";
// plane web hooks
import { useTeamspaces } from "@/plane-web/hooks/store";
import type { Route } from "./+types/page";
const TeamspaceWorkItemsPage = observer(() => {
const { teamspaceId } = useParams();
function TeamspaceWorkItemsPage({ params }: Route.ComponentProps) {
const { teamspaceId } = params;
// store
const { getTeamspaceById } = useTeamspaces();
if (!teamspaceId) {
return <></>;
}
// derived values
const teamspace = getTeamspaceById(teamspaceId.toString());
const teamspace = getTeamspaceById(teamspaceId);
const pageTitle = teamspace?.name ? `${teamspace?.name} - Issues` : undefined;
return (
@@ -30,6 +26,6 @@ const TeamspaceWorkItemsPage = observer(() => {
</div>
</>
);
});
}
export default TeamspaceWorkItemsPage;
export default observer(TeamspaceWorkItemsPage);
@@ -1,39 +1,31 @@
"use client";
import { useParams } from "next/navigation";
import { Outlet } from "react-router";
import useSWR from "swr";
import { useTeamspaces, useTeamspaceViews } from "@/plane-web/hooks/store";
import type { Route } from "./+types/layout";
export default function TeamspaceDetailLayout() {
export default function TeamspaceDetailLayout({ params }: Route.ComponentProps) {
// router
const { workspaceSlug: routerWorkspaceSlug, teamspaceId: routerTeamSpaceId } = useParams();
const { workspaceSlug, teamspaceId } = params;
// store hooks
const { isCurrentUserMemberOfTeamspace, fetchTeamspaceDetails } = useTeamspaces();
const { fetchTeamspaceViews } = useTeamspaceViews();
// derived values
const workspaceSlug = routerWorkspaceSlug!.toString();
const teamspaceId = routerTeamSpaceId!.toString();
const isTeamspaceMember = isCurrentUserMemberOfTeamspace(teamspaceId);
// fetching teamspace details
useSWR(
workspaceSlug && teamspaceId && isTeamspaceMember
? `WORKSPACE_TEAMSPACES_${workspaceSlug}_${teamspaceId}_${isTeamspaceMember}`
: null,
workspaceSlug && teamspaceId && isTeamspaceMember ? () => fetchTeamspaceDetails(workspaceSlug, teamspaceId) : null,
isTeamspaceMember ? `WORKSPACE_TEAMSPACES_${workspaceSlug}_${teamspaceId}_${isTeamspaceMember}` : null,
isTeamspaceMember ? () => fetchTeamspaceDetails(workspaceSlug, teamspaceId) : null,
{ revalidateIfStale: false, revalidateOnFocus: false }
);
// fetch teamspace views
useSWR(
workspaceSlug && teamspaceId ? ["teamspaceViews", workspaceSlug, teamspaceId] : null,
() => (workspaceSlug && teamspaceId ? fetchTeamspaceViews(workspaceSlug, teamspaceId) : null),
{
revalidateOnFocus: false,
revalidateIfStale: false,
}
);
useSWR(["teamspaceViews", workspaceSlug, teamspaceId], () => fetchTeamspaceViews(workspaceSlug, teamspaceId), {
revalidateOnFocus: false,
revalidateIfStale: false,
});
return <Outlet />;
}
@@ -3,7 +3,6 @@
import { useCallback, useMemo } from "react";
import { observer } from "mobx-react";
import Link from "next/link";
import { useParams } from "next/navigation";
import useSWR from "swr";
// plane types
import { getButtonStyling } from "@plane/propel/button";
@@ -28,34 +27,32 @@ import { EPageStoreType, usePage, usePageStore } from "@/plane-web/hooks/store";
import { WorkspaceService } from "@/plane-web/services";
import { TeamspacePageVersionService } from "@/plane-web/services/teamspace/teamspace-page-version.service";
import { TeamspacePageService } from "@/plane-web/services/teamspace/teamspace-pages.service";
import type { Route } from "./+types/page";
const workspaceService = new WorkspaceService();
const teamspacePageService = new TeamspacePageService();
const teamspacePageVersionService = new TeamspacePageVersionService();
const storeType = EPageStoreType.TEAMSPACE;
const TeamspacePageDetailsPage = observer(() => {
const { workspaceSlug: routerWorkspaceSlug, teamspaceId: routerTeamSpaceId, pageId: routerPageId } = useParams();
const workspaceSlug = routerWorkspaceSlug?.toString();
const teamspaceId = routerTeamSpaceId?.toString();
const pageId = routerPageId?.toString();
function TeamspacePageDetailsPage({ params }: Route.ComponentProps) {
const { workspaceSlug, teamspaceId, pageId } = params;
// store hooks
const { createPage, fetchPageDetails } = usePageStore(storeType);
const page = usePage({
pageId: pageId?.toString() ?? "",
pageId,
storeType,
});
const { getWorkspaceBySlug } = useWorkspace();
const { uploadEditorAsset } = useEditorAsset();
// derived values
const workspaceId = workspaceSlug ? (getWorkspaceBySlug(workspaceSlug)?.id ?? "") : "";
const workspaceId = getWorkspaceBySlug(workspaceSlug)?.id ?? "";
const { id, name, updateDescription } = page ?? {};
// entity search handler
const fetchEntityCallback = useCallback(
async (payload: TSearchEntityRequestPayload) =>
await workspaceService.searchEntity(workspaceSlug?.toString() ?? "", {
await workspaceService.searchEntity(workspaceSlug, {
...payload,
team_id: teamspaceId?.toString() ?? "",
team_id: teamspaceId,
}),
[teamspaceId, workspaceSlug]
);
@@ -63,8 +60,8 @@ const TeamspacePageDetailsPage = observer(() => {
const { getEditorFileHandlers } = useEditorConfig();
// fetch page details
const { error: pageDetailsError } = useSWR(
workspaceSlug && teamspaceId && pageId ? `TEAM_PAGE_DETAILS_${pageId}` : null,
workspaceSlug && teamspaceId && pageId ? () => fetchPageDetails(teamspaceId, pageId) : null,
`TEAM_PAGE_DETAILS_${pageId}`,
() => fetchPageDetails(teamspaceId, pageId),
{
revalidateIfStale: true,
revalidateOnFocus: true,
@@ -75,23 +72,17 @@ const TeamspacePageDetailsPage = observer(() => {
const pageRootHandlers: TPageRootHandlers = useMemo(
() => ({
create: createPage,
fetchAllVersions: async (pageId) => {
if (!workspaceSlug || !teamspaceId) return;
return await teamspacePageVersionService.fetchAllVersions(workspaceSlug, teamspaceId, pageId);
},
fetchAllVersions: async (pageId) =>
await teamspacePageVersionService.fetchAllVersions(workspaceSlug, teamspaceId, pageId),
fetchDescriptionBinary: async () => {
if (!workspaceSlug || !teamspaceId || !id) return;
if (!id) return;
return await teamspacePageService.fetchDescriptionBinary(workspaceSlug, teamspaceId, id);
},
fetchEntity: fetchEntityCallback,
fetchVersionDetails: async (pageId, versionId) => {
if (!workspaceSlug || !teamspaceId) return;
return await teamspacePageVersionService.fetchVersionById(workspaceSlug, teamspaceId, pageId, versionId);
},
restoreVersion: async (pageId, versionId) => {
if (!workspaceSlug || !teamspaceId) return;
return await teamspacePageVersionService.restoreVersion(workspaceSlug, teamspaceId, pageId, versionId);
},
fetchVersionDetails: async (pageId, versionId) =>
await teamspacePageVersionService.fetchVersionById(workspaceSlug, teamspaceId, pageId, versionId),
restoreVersion: async (pageId, versionId) =>
await teamspacePageVersionService.restoreVersion(workspaceSlug, teamspaceId, pageId, versionId),
getRedirectionLink: (pageId) => {
if (pageId) {
return `/${workspaceSlug}/teamspaces/${teamspaceId}/pages/${pageId}`;
@@ -179,6 +170,6 @@ const TeamspacePageDetailsPage = observer(() => {
</div>
</>
);
});
}
export default TeamspacePageDetailsPage;
export default observer(TeamspacePageDetailsPage);
@@ -1,6 +1,5 @@
"use client";
import { useParams } from "next/navigation";
import { Outlet } from "react-router";
import { ETeamspaceNavigationItem } from "@plane/constants";
// components
@@ -11,13 +10,14 @@ import { PageHead } from "@/components/core/page-title";
import { TeamspaceDetailHeader } from "@/plane-web/components/teamspaces/headers/detail-header";
// plane web hooks
import { useTeamspaces } from "@/plane-web/hooks/store";
import type { Route } from "./+types/layout";
export default function TeamspacePagesLayout() {
const { teamspaceId } = useParams();
export default function TeamspacePagesLayout({ params }: Route.ComponentProps) {
const { teamspaceId } = params;
// store hooks
const { getTeamspaceById } = useTeamspaces();
// derived values
const currentTeam = getTeamspaceById(teamspaceId?.toString());
const currentTeam = getTeamspaceById(teamspaceId);
const pageTitle = currentTeam?.name ? `Teamspace ${currentTeam?.name} - Pages` : undefined;
return (
@@ -1,43 +1,30 @@
"use client";
import { observer } from "mobx-react";
import { useParams, useSearchParams } from "next/navigation";
import { useSearchParams } from "next/navigation";
// plane imports
import type { TPageNavigationTabs } from "@plane/types";
// components
import { PageHead } from "@/components/core/page-title";
// plane web imports
import { TeamspacePagesListView } from "@/plane-web/components/teamspaces/pages/pages-list-view";
import { EPageStoreType, usePageStore, useTeamspaces } from "@/plane-web/hooks/store";
import type { Route } from "./+types/page";
const storeType = EPageStoreType.TEAMSPACE;
const getPageType = (pageType: string | null): TPageNavigationTabs => {
switch (pageType) {
case "archived":
return "archived";
default:
return "public";
}
};
const TeamspacePagesPage = observer(() => {
const { workspaceSlug: routerWorkspaceSlug, teamspaceId: routerTeamSpaceId } = useParams();
function TeamspacePagesPage({ params }: Route.ComponentProps) {
const { workspaceSlug, teamspaceId } = params;
const searchParams = useSearchParams();
const workspaceSlug = routerWorkspaceSlug!.toString();
const teamspaceId = routerTeamSpaceId!.toString();
// store hooks
const { getTeamspaceById } = useTeamspaces();
// derived values
const currentTeamspace = getTeamspaceById(teamspaceId);
const pageTitle = currentTeamspace?.name ? `Teamspace ${currentTeamspace?.name} - Pages` : undefined;
if (!workspaceSlug || !teamspaceId) return <></>;
// Get current page type (only public/archived for teamspaces)
const currentPageType = (): TPageNavigationTabs => {
const pageType = searchParams.get("type");
if (pageType === "archived") return "archived";
return "public"; // Default to public
};
const pageType = getPageType(searchParams.get("type"));
return (
<TeamspacePagesListView pageType={currentPageType()} teamspaceId={teamspaceId} workspaceSlug={workspaceSlug} />
);
});
return <TeamspacePagesListView pageType={pageType} teamspaceId={teamspaceId} workspaceSlug={workspaceSlug} />;
}
export default TeamspacePagesPage;
@@ -1,23 +1,19 @@
"use client";
import { useParams } from "next/navigation";
import { Outlet } from "react-router";
import useSWR from "swr";
// plane web hooks
import { EPageStoreType, usePageStore } from "@/plane-web/hooks/store";
import type { Route } from "./+types/layout";
export default function TeamspacePagesLayout() {
const { workspaceSlug, teamspaceId } = useParams();
export default function TeamspacePagesLayout({ params }: Route.ComponentProps) {
const { workspaceSlug, teamspaceId } = params;
// store hooks
const { fetchPagesList } = usePageStore(EPageStoreType.TEAMSPACE);
// fetch teamspace pages
useSWR(
workspaceSlug && teamspaceId ? ["teamspacePages", workspaceSlug, teamspaceId] : null,
() => (workspaceSlug && teamspaceId ? fetchPagesList(workspaceSlug.toString(), teamspaceId.toString()) : null),
{
revalidateOnFocus: false,
revalidateIfStale: false,
}
);
useSWR(["teamspacePages", workspaceSlug, teamspaceId], () => fetchPagesList(workspaceSlug, teamspaceId), {
revalidateOnFocus: false,
revalidateIfStale: false,
});
return <Outlet />;
}
@@ -1,25 +1,20 @@
"use client";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// components
import { PageHead } from "@/components/core/page-title";
// plane web components
import { TeamspaceProjectWorkLayoutRoot } from "@/plane-web/components/issues/issue-layouts/roots/teamspace-project-root";
// plane web hooks
import { useTeamspaces } from "@/plane-web/hooks/store";
import type { Route } from "./+types/page";
const TeamspaceProjectDetailPage = observer(() => {
const { teamspaceId } = useParams();
function TeamspaceProjectDetailPage({ params }: Route.ComponentProps) {
const { teamspaceId } = params;
// store
const { getTeamspaceById } = useTeamspaces();
if (!teamspaceId) {
return <></>;
}
// derived values
const teamspace = getTeamspaceById(teamspaceId.toString());
const teamspace = getTeamspaceById(teamspaceId);
const pageTitle = teamspace?.name ? `${teamspace?.name} - Work items` : undefined;
return (
@@ -30,6 +25,6 @@ const TeamspaceProjectDetailPage = observer(() => {
</div>
</>
);
});
}
export default TeamspaceProjectDetailPage;
@@ -1,7 +1,6 @@
"use client";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
import { Outlet } from "react-router";
import { ETeamspaceNavigationItem } from "@plane/constants";
// components
@@ -12,13 +11,14 @@ import { PageHead } from "@/components/core/page-title";
import { TeamspaceDetailHeader } from "@/plane-web/components/teamspaces/headers/detail-header";
// plane web hooks
import { useTeamspaces } from "@/plane-web/hooks/store";
import type { Route } from "./+types/layout";
const TeamspaceProjectsLayout = observer(() => {
const { teamspaceId } = useParams();
function TeamspaceProjectsLayout({ params }: Route.ComponentProps) {
const { teamspaceId } = params;
// store hooks
const { getTeamspaceById } = useTeamspaces();
// derived values
const currentTeam = getTeamspaceById(teamspaceId?.toString());
const currentTeam = getTeamspaceById(teamspaceId);
const pageTitle = currentTeam?.name ? `Teamspace ${currentTeam?.name} - Projects` : undefined;
return (
@@ -30,6 +30,6 @@ const TeamspaceProjectsLayout = observer(() => {
</ContentWrapper>
</>
);
});
}
export default TeamspaceProjectsLayout;
export default observer(TeamspaceProjectsLayout);
@@ -1,7 +1,6 @@
"use client";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
import { useTheme } from "next-themes";
// plane imports
import useSWR from "swr";
@@ -19,9 +18,10 @@ import { TeamspaceProjectsWithGroupingRoot } from "@/plane-web/components/teamsp
import { TeamspaceProjectsWithoutGroupingRoot } from "@/plane-web/components/teamspaces/projects/non-grouping-root";
import { useFlag, useTeamspaces, useWorkspaceFeatures } from "@/plane-web/hooks/store";
import { EWorkspaceFeatures } from "@/plane-web/types/workspace-feature";
import type { Route } from "./+types/page";
const TeamspaceProjectsPage = observer(() => {
const { workspaceSlug, teamspaceId } = useParams();
function TeamspaceProjectsPage({ params }: Route.ComponentProps) {
const { workspaceSlug, teamspaceId } = params;
// plane hooks
const { t } = useTranslation();
// theme hook
@@ -31,19 +31,18 @@ const TeamspaceProjectsPage = observer(() => {
const { getTeamspaceById, getTeamspaceProjectIds } = useTeamspaces();
const { isWorkspaceFeatureEnabled } = useWorkspaceFeatures();
// derived values
const teamspace = teamspaceId ? getTeamspaceById(teamspaceId.toString()) : undefined;
const teamspaceProjectIds = teamspaceId ? getTeamspaceProjectIds(teamspaceId.toString()) : undefined;
const teamspace = getTeamspaceById(teamspaceId);
const teamspaceProjectIds = getTeamspaceProjectIds(teamspaceId);
const pageTitle = teamspace?.name ? `${teamspace?.name} - Projects` : undefined;
const isProjectGroupingFlagEnabled = useFlag(workspaceSlug.toString(), "PROJECT_GROUPING");
const isProjectGroupingEnabled =
isWorkspaceFeatureEnabled(EWorkspaceFeatures.IS_PROJECT_GROUPING_ENABLED) &&
useFlag(workspaceSlug.toString(), "PROJECT_GROUPING");
isWorkspaceFeatureEnabled(EWorkspaceFeatures.IS_PROJECT_GROUPING_ENABLED) && isProjectGroupingFlagEnabled;
const resolvedPath = resolvedTheme === "light" ? teamsLight : teamsDark;
// fetching workspace projects
useSWR(
workspaceSlug ? `WORKSPACE_PROJECTS_${workspaceSlug}` : null,
workspaceSlug ? () => fetchProjects(workspaceSlug.toString()) : null,
{ revalidateIfStale: false, revalidateOnFocus: false }
);
useSWR(`WORKSPACE_PROJECTS_${workspaceSlug}`, () => fetchProjects(workspaceSlug), {
revalidateIfStale: false,
revalidateOnFocus: false,
});
if (teamspaceProjectIds?.length === 0) {
return (
@@ -60,12 +59,12 @@ const TeamspaceProjectsPage = observer(() => {
<>
<PageHead title={pageTitle} />
{isProjectGroupingEnabled ? (
<TeamspaceProjectsWithGroupingRoot workspaceSlug={workspaceSlug.toString()} />
<TeamspaceProjectsWithGroupingRoot workspaceSlug={workspaceSlug} />
) : (
<TeamspaceProjectsWithoutGroupingRoot workspaceSlug={workspaceSlug.toString()} teamspace={teamspace} />
<TeamspaceProjectsWithoutGroupingRoot workspaceSlug={workspaceSlug} teamspace={teamspace} />
)}
</>
);
});
}
export default TeamspaceProjectsPage;
export default observer(TeamspaceProjectsPage);
@@ -1,7 +1,6 @@
"use client";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
import useSWR from "swr";
// assets
import emptyView from "@/app/assets/empty-state/view.svg?url";
@@ -14,24 +13,22 @@ import { useAppRouter } from "@/hooks/use-app-router";
import { TeamspaceViewLayoutRoot } from "@/plane-web/components/issues/issue-layouts/roots/teamspace-view-layout-root";
// plane web hooks
import { useTeamspaces, useTeamspaceViews } from "@/plane-web/hooks/store";
import type { Route } from "./+types/page";
const TeamspaceViewWorkItemsPage = observer(() => {
function TeamspaceViewWorkItemsPage({ params }: Route.ComponentProps) {
// router
const router = useAppRouter();
const { workspaceSlug, teamspaceId, viewId } = useParams();
const { workspaceSlug, teamspaceId, viewId } = params;
// store hooks
const { getTeamspaceById } = useTeamspaces();
const { fetchTeamspaceViewDetails, getViewById } = useTeamspaceViews();
// derived values
const teamspaceView = teamspaceId && viewId ? getViewById(teamspaceId.toString(), viewId.toString()) : undefined;
const teamspace = teamspaceId ? getTeamspaceById(teamspaceId.toString()) : undefined;
const teamspaceView = getViewById(teamspaceId, viewId);
const teamspace = getTeamspaceById(teamspaceId);
const pageTitle = teamspace?.name && teamspaceView?.name ? `${teamspace?.name} - ${teamspaceView?.name}` : undefined;
// fetch teamspace view details
const { error } = useSWR(
workspaceSlug && teamspaceId && viewId ? `TEAMSPACE_VIEW_DETAILS_${viewId.toString()}` : null,
workspaceSlug && teamspaceId && viewId
? () => fetchTeamspaceViewDetails(workspaceSlug.toString(), teamspaceId.toString(), viewId.toString())
: null
const { error } = useSWR(`TEAMSPACE_VIEW_DETAILS_${viewId}`, () =>
fetchTeamspaceViewDetails(workspaceSlug, teamspaceId, viewId)
);
if (error) {
@@ -54,6 +51,6 @@ const TeamspaceViewWorkItemsPage = observer(() => {
<TeamspaceViewLayoutRoot />
</>
);
});
}
export default TeamspaceViewWorkItemsPage;
export default observer(TeamspaceViewWorkItemsPage);
@@ -1,6 +1,5 @@
"use client";
import { useParams } from "next/navigation";
import { Outlet } from "react-router";
import { ETeamspaceNavigationItem } from "@plane/constants";
// components
@@ -11,13 +10,14 @@ import { PageHead } from "@/components/core/page-title";
import { TeamspaceDetailHeader } from "@/plane-web/components/teamspaces/headers/detail-header";
// plane web hooks
import { useTeamspaces } from "@/plane-web/hooks/store";
import type { Route } from "./+types/layout";
export default function TeamspaceViewsLayout() {
const { teamspaceId } = useParams();
export default function TeamspaceViewsLayout({ params }: Route.ComponentProps) {
const { teamspaceId } = params;
// store hooks
const { getTeamspaceById } = useTeamspaces();
// derived values
const currentTeam = getTeamspaceById(teamspaceId?.toString());
const currentTeam = getTeamspaceById(teamspaceId);
const pageTitle = currentTeam?.name ? `Teamspace ${currentTeam?.name} - Views` : undefined;
return (
@@ -2,7 +2,6 @@
import { useCallback } from "react";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// plane imports
import type { EViewAccess, TViewFilterProps } from "@plane/types";
import { calculateTotalFilters } from "@plane/utils";
@@ -11,11 +10,10 @@ import { ViewAppliedFiltersList } from "@/components/views/applied-filters";
// plane web imports
import { TeamspaceViewsList } from "@/plane-web/components/teamspaces/views/views-list";
import { useTeamspaceViews } from "@/plane-web/hooks/store";
import type { Route } from "./+types/page";
const TeamspaceViewsPage = observer(() => {
const { workspaceSlug: routerWorkspaceSlug, teamspaceId: routerTeamSpaceId } = useParams();
const workspaceSlug = routerWorkspaceSlug!.toString();
const teamspaceId = routerTeamSpaceId!.toString();
function TeamspaceViewsPage({ params }: Route.ComponentProps) {
const { teamspaceId } = params;
// store hooks
const { getTeamspaceViewsFilters, updateFilters, clearAllFilters } = useTeamspaceViews();
// derived values
@@ -43,8 +41,6 @@ const TeamspaceViewsPage = observer(() => {
[teamspaceId, teamspaceViewsFilters?.filters, updateFilters]
);
if (!workspaceSlug || !teamspaceId) return <></>;
return (
<div className="flex flex-col w-full h-full">
{isFiltersApplied && (
@@ -62,6 +58,6 @@ const TeamspaceViewsPage = observer(() => {
</div>
</div>
);
});
}
export default TeamspaceViewsPage;
export default observer(TeamspaceViewsPage);
@@ -4,6 +4,8 @@ import { observer } from "mobx-react";
// plane web components
import TeamspacesListRoot from "@/plane-web/components/teamspaces/list/root";
const TeamspacesListPage = observer(() => <TeamspacesListRoot />);
function TeamspacesListPage() {
return <TeamspacesListRoot />;
}
export default TeamspacesListPage;
export default observer(TeamspacesListPage);
@@ -11,7 +11,7 @@ import { TeamspaceUpgrade } from "@/plane-web/components/teamspaces/upgrade";
// plane web hooks
import { useTeamspaces } from "@/plane-web/hooks/store";
const TeamspacesLayout = observer(() => {
function TeamspacesLayout() {
// store
const { currentWorkspace } = useWorkspace();
// plane web stores
@@ -35,6 +35,6 @@ const TeamspacesLayout = observer(() => {
)}
</WorkspaceAccessWrapper>
);
});
}
export default TeamspacesLayout;
export default observer(TeamspacesLayout);
@@ -1,8 +1,6 @@
"use client";
import React from "react";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// plane imports
import { E_FEATURE_FLAGS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
@@ -23,10 +21,11 @@ import { CustomerUpgrade, CustomerSettingsRoot } from "@/plane-web/components/cu
import { WithFeatureFlagHOC } from "@/plane-web/components/feature-flags";
import { useCustomers, useFlag, useWorkspaceFeatures } from "@/plane-web/hooks/store";
import { EWorkspaceFeatures } from "@/plane-web/types/workspace-feature";
import type { Route } from "./+types/page";
const CustomerSettingsPage = observer(() => {
function CustomerSettingsPage({ params }: Route.ComponentProps) {
// router
const { workspaceSlug } = useParams();
const { workspaceSlug } = params;
// store hooks
const { getWorkspaceRoleByWorkspaceSlug } = useUserPermissions();
const { currentWorkspace } = useWorkspace();
@@ -35,50 +34,46 @@ const CustomerSettingsPage = observer(() => {
const { t } = useTranslation();
// derived values
const currentWorkspaceRole = getWorkspaceRoleByWorkspaceSlug(workspaceSlug.toString());
const currentWorkspaceRole = getWorkspaceRoleByWorkspaceSlug(workspaceSlug);
const pageTitle = currentWorkspace?.name ? `${currentWorkspace.name} - Customers` : undefined;
const isAdmin = currentWorkspaceRole === EUserWorkspaceRoles.ADMIN;
const { isCustomersFeatureEnabled } = useCustomers();
const isFeatureFlagEnabled = useFlag(workspaceSlug?.toString(), E_FEATURE_FLAGS.CUSTOMERS);
const isFeatureFlagEnabled = useFlag(workspaceSlug, E_FEATURE_FLAGS.CUSTOMERS);
if (!workspaceSlug || !currentWorkspace?.id) return <></>;
if (!currentWorkspace?.id) return <></>;
if (!isAdmin) return <NotAuthorizedView section="settings" className="h-auto" />;
const toggleCustomersFeature = async () => {
try {
try {
const payload = {
[EWorkspaceFeatures.IS_CUSTOMERS_ENABLED]: !isCustomersFeatureEnabled,
};
const toggleCustomersFeaturePromise = updateWorkspaceFeature(workspaceSlug.toString(), payload);
setPromiseToast(toggleCustomersFeaturePromise, {
loading: isCustomersFeatureEnabled
? t("customers.settings.toasts.disable.loading")
: t("customers.settings.toasts.enable.loading"),
success: {
title: isCustomersFeatureEnabled
? t("customers.settings.toasts.disable.success.title")
: t("customers.settings.toasts.enable.success.title"),
message: () =>
isCustomersFeatureEnabled
? t("customers.settings.toasts.disable.success.message")
: t("customers.settings.toasts.enable.success.message"),
},
error: {
title: isCustomersFeatureEnabled
? t("customers.settings.toasts.disable.error.title")
: t("customers.settings.toasts.enable.error.title"),
message: () =>
isCustomersFeatureEnabled
? t("customers.settings.toasts.disable.error.message")
: t("customers.settings.toasts.enable.error.message"),
},
});
await toggleCustomersFeaturePromise;
} catch (error) {
console.error(error);
}
const payload = {
[EWorkspaceFeatures.IS_CUSTOMERS_ENABLED]: !isCustomersFeatureEnabled,
};
const toggleCustomersFeaturePromise = updateWorkspaceFeature(workspaceSlug, payload);
setPromiseToast(toggleCustomersFeaturePromise, {
loading: isCustomersFeatureEnabled
? t("customers.settings.toasts.disable.loading")
: t("customers.settings.toasts.enable.loading"),
success: {
title: isCustomersFeatureEnabled
? t("customers.settings.toasts.disable.success.title")
: t("customers.settings.toasts.enable.success.title"),
message: () =>
isCustomersFeatureEnabled
? t("customers.settings.toasts.disable.success.message")
: t("customers.settings.toasts.enable.success.message"),
},
error: {
title: isCustomersFeatureEnabled
? t("customers.settings.toasts.disable.error.title")
: t("customers.settings.toasts.enable.error.title"),
message: () =>
isCustomersFeatureEnabled
? t("customers.settings.toasts.disable.error.message")
: t("customers.settings.toasts.enable.error.message"),
},
});
await toggleCustomersFeaturePromise;
} catch (error) {
console.error(error);
}
@@ -101,7 +96,7 @@ const CustomerSettingsPage = observer(() => {
</>
}
/>
<WithFeatureFlagHOC flag="CUSTOMERS" fallback={<CustomerUpgrade />} workspaceSlug={workspaceSlug?.toString()}>
<WithFeatureFlagHOC flag="CUSTOMERS" fallback={<CustomerUpgrade />} workspaceSlug={workspaceSlug}>
<CustomerSettingsRoot
workspaceId={currentWorkspace?.id}
toggleCustomersFeature={toggleCustomersFeature}
@@ -111,6 +106,6 @@ const CustomerSettingsPage = observer(() => {
</div>
</SettingsContentWrapper>
);
});
}
export default CustomerSettingsPage;
export default observer(CustomerSettingsPage);
@@ -1,6 +1,5 @@
"use client";
import type { FC } from "react";
import { Fragment, useEffect } from "react";
import { observer } from "mobx-react";
import useSWR from "swr";
@@ -11,7 +10,7 @@ import { AsanaDashboardRoot } from "@/plane-web/components/importers/asana/dashb
import { DashboardLoaderRoot } from "@/plane-web/components/importers/common/dashboard";
import { useAsanaImporter } from "@/plane-web/hooks/store";
const AsanaImporter: FC = observer(() => {
function AsanaImporter() {
const {
user,
workspace,
@@ -78,6 +77,6 @@ const AsanaImporter: FC = observer(() => {
)}
</Fragment>
);
});
}
export default AsanaImporter;
export default observer(AsanaImporter);
@@ -1,6 +1,5 @@
"use client";
import type { FC } from "react";
import { Fragment, useEffect } from "react";
import { observer } from "mobx-react";
import useSWR from "swr";
@@ -12,7 +11,7 @@ import { ClickUpDashboardRoot } from "@/plane-web/components/importers/clickup/d
import { DashboardLoaderRoot } from "@/plane-web/components/importers/common/dashboard";
import { useClickUpImporter, useFlag } from "@/plane-web/hooks/store";
const ClickUpImporter: FC = observer(() => {
function ClickUpImporter() {
const {
user,
workspace,
@@ -62,6 +61,6 @@ const ClickUpImporter: FC = observer(() => {
)}
</Fragment>
);
});
}
export default ClickUpImporter;
export default observer(ClickUpImporter);
@@ -1,6 +1,5 @@
"use client";
import type { FC } from "react";
import { Fragment, useEffect } from "react";
import { observer } from "mobx-react";
import useSWR from "swr";
@@ -14,14 +13,13 @@ import { useZipImporter } from "@/plane-web/hooks/store/importers/use-zip-import
import type { TZipImporterProps } from "@/plane-web/types/importers/zip-importer";
import { EZipDriverType } from "@/plane-web/types/importers/zip-importer";
const ConfluenceImporter: FC = observer(() => {
function ConfluenceImporter() {
const {
// Properties
workspace,
user,
externalApiToken,
dashboardView,
// Actions
fetchExternalApiToken,
verifyAndAddCredentials,
@@ -97,6 +95,6 @@ const ConfluenceImporter: FC = observer(() => {
};
return <Fragment>{dashboardView ? <ZipImporterDashboard {...props} /> : <StepsRoot {...props} />}</Fragment>;
});
}
export default ConfluenceImporter;
export default observer(ConfluenceImporter);
@@ -1,6 +1,5 @@
"use client";
import type { FC } from "react";
import { Fragment, useEffect } from "react";
import { observer } from "mobx-react";
import useSWR from "swr";
@@ -9,14 +8,13 @@ import { FlatfileDashboardRoot } from "@/plane-web/components/importers/flatfile
import { StepsRoot } from "@/plane-web/components/importers/flatfile/steps";
import { useFlatfileImporter } from "@/plane-web/hooks/store";
const FlatfileImporter: FC = observer(() => {
function FlatfileImporter() {
const {
// Properties
workspace,
user,
externalApiToken,
dashboardView,
// Actions
fetchProjects,
fetchExternalApiToken,
@@ -83,6 +81,6 @@ const FlatfileImporter: FC = observer(() => {
);
return <Fragment>{dashboardView ? <FlatfileDashboardRoot /> : <StepsRoot />}</Fragment>;
});
}
export default FlatfileImporter;
export default observer(FlatfileImporter);
@@ -1,6 +1,5 @@
"use client";
import type { FC } from "react";
import { Fragment, useEffect } from "react";
import { observer } from "mobx-react";
import useSWR from "swr";
@@ -10,7 +9,7 @@ import { AuthenticationRoot, JiraServerDashboardRoot, StepsRoot } from "@/plane-
// plane web hooks
import { useJiraServerImporter } from "@/plane-web/hooks/store";
const JiraServerImporter: FC = observer(() => {
function JiraServerImporter() {
const {
user,
workspace,
@@ -80,6 +79,6 @@ const JiraServerImporter: FC = observer(() => {
)}
</Fragment>
);
});
}
export default JiraServerImporter;
export default observer(JiraServerImporter);
@@ -1,6 +1,5 @@
"use client";
import type { FC } from "react";
import { Fragment, useEffect } from "react";
import { observer } from "mobx-react";
import useSWR from "swr";
@@ -10,7 +9,7 @@ import { AuthenticationRoot, StepsRoot, JiraDashboardRoot } from "@/plane-web/co
// plane web hooks
import { useJiraImporter } from "@/plane-web/hooks/store";
const JiraImporter: FC = observer(() => {
function JiraImporter() {
const {
user,
workspace,
@@ -80,6 +79,6 @@ const JiraImporter: FC = observer(() => {
)}
</Fragment>
);
});
}
export default JiraImporter;
export default observer(JiraImporter);
@@ -2,7 +2,6 @@
import { observer } from "mobx-react";
import Link from "next/link";
import { useParams } from "next/navigation";
import { Outlet } from "react-router";
import { SILO_BASE_URL, SILO_BASE_PATH } from "@plane/constants";
import { ChevronLeftIcon } from "@plane/propel/icons";
@@ -10,10 +9,11 @@ import { ChevronLeftIcon } from "@plane/propel/icons";
import { SettingsContentWrapper } from "@/components/settings/content-wrapper";
import { useWorkspace } from "@/hooks/store/use-workspace";
import { useUser } from "@/hooks/store/user";
import type { Route } from "./+types/layout";
const ImporterLayout = observer(() => {
function ImporterLayout({ params }: Route.ComponentProps) {
// router params
const { workspaceSlug: workspaceSlugParam } = useParams();
const { workspaceSlug } = params;
// hooks
const { currentWorkspace } = useWorkspace();
@@ -21,12 +21,11 @@ const ImporterLayout = observer(() => {
// derived values
const siloBaseUrl = encodeURI(SILO_BASE_URL + SILO_BASE_PATH) || undefined;
const workspaceSlug = workspaceSlugParam?.toString() || undefined;
const workspaceId = currentWorkspace?.id || undefined;
const userId = currentUser?.id || undefined;
// check if workspace exists
if (!workspaceSlug || !workspaceId || !userId || !siloBaseUrl) return null;
if (!workspaceId || !userId || !siloBaseUrl) return null;
return (
<SettingsContentWrapper size="lg">
@@ -40,6 +39,6 @@ const ImporterLayout = observer(() => {
<Outlet />
</SettingsContentWrapper>
);
});
}
export default ImporterLayout;
export default observer(ImporterLayout);
@@ -1,6 +1,5 @@
"use client";
import type { FC } from "react";
import { Fragment, useEffect } from "react";
import { observer } from "mobx-react";
import useSWR from "swr";
@@ -11,7 +10,7 @@ import { AuthenticationRoot, StepsRoot } from "@/plane-web/components/importers/
import { LinearDashboardRoot } from "@/plane-web/components/importers/linear/dashboard/root";
import { useLinearImporter } from "@/plane-web/hooks/store";
const LinearImporter: FC = observer(() => {
function LinearImporter() {
const {
user,
workspace,
@@ -81,6 +80,6 @@ const LinearImporter: FC = observer(() => {
)}
</Fragment>
);
});
}
export default LinearImporter;
export default observer(LinearImporter);
@@ -1,6 +1,5 @@
"use client";
import type { FC } from "react";
import { Fragment, useEffect } from "react";
import { observer } from "mobx-react";
import useSWR from "swr";
@@ -14,14 +13,13 @@ import { useZipImporter } from "@/plane-web/hooks/store/importers/use-zip-import
import type { TZipImporterProps } from "@/plane-web/types/importers/zip-importer";
import { EZipDriverType } from "@/plane-web/types/importers/zip-importer";
const NotionImporter: FC = observer(() => {
function NotionImporter() {
const {
// Properties
workspace,
user,
externalApiToken,
dashboardView,
// Actions
fetchProjects,
fetchExternalApiToken,
@@ -105,6 +103,6 @@ const NotionImporter: FC = observer(() => {
};
return <Fragment>{dashboardView ? <ZipImporterDashboard {...props} /> : <StepsRoot {...props} />}</Fragment>;
});
}
export default NotionImporter;
export default observer(NotionImporter);
@@ -1,7 +1,6 @@
"use client";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
// components
@@ -15,10 +14,11 @@ import { useWorkspace } from "@/hooks/store/use-workspace";
import { useUserPermissions } from "@/hooks/store/user";
// plane web components
import { ImportersList } from "@/plane-web/components/importers";
import type { Route } from "./+types/page";
function ImportsPage() {
function ImportsPage({ params }: Route.ComponentProps) {
// router
const { workspaceSlug } = useParams();
const { workspaceSlug } = params;
// store hooks
const { currentWorkspace } = useWorkspace();
const { allowPermissions } = useUserPermissions();
@@ -37,7 +37,7 @@ function ImportsPage() {
title={t("workspace_settings.settings.imports.heading")}
description={t("workspace_settings.settings.imports.description")}
/>
{workspaceSlug && <ImportersList workspaceSlug={workspaceSlug.toString()} />}
<ImportersList workspaceSlug={workspaceSlug} />
</section>
</SettingsContentWrapper>
);
@@ -1,7 +1,6 @@
"use client";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// plane imports
import { INITIATIVE_TRACKER_EVENTS, INITIATIVES_TRACKER_ELEMENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
@@ -25,10 +24,11 @@ import { InitiativeLabelList } from "@/plane-web/components/initiatives/componen
import { InitiativesUpgrade } from "@/plane-web/components/initiatives/upgrade";
import { useWorkspaceFeatures } from "@/plane-web/hooks/store";
import { EWorkspaceFeatures } from "@/plane-web/types/workspace-feature";
import type { Route } from "./+types/page";
const InitiativesSettingsPage = observer(() => {
function InitiativesSettingsPage({ params }: Route.ComponentProps) {
// router
const { workspaceSlug } = useParams();
const { workspaceSlug } = params;
// store hooks
const { getWorkspaceRoleByWorkspaceSlug } = useUserPermissions();
const { currentWorkspace } = useWorkspace();
@@ -36,12 +36,12 @@ const InitiativesSettingsPage = observer(() => {
const { t } = useTranslation();
// derived values
const currentWorkspaceRole = getWorkspaceRoleByWorkspaceSlug(workspaceSlug.toString());
const currentWorkspaceRole = getWorkspaceRoleByWorkspaceSlug(workspaceSlug);
const pageTitle = currentWorkspace?.name ? `${currentWorkspace.name} - Initiatives` : undefined;
const isAdmin = currentWorkspaceRole === EUserWorkspaceRoles.ADMIN;
const isInitiativesFeatureEnabled = isWorkspaceFeatureEnabled(EWorkspaceFeatures.IS_INITIATIVES_ENABLED);
if (!workspaceSlug || !currentWorkspace?.id) return <></>;
if (!currentWorkspace?.id) return <></>;
if (!isAdmin) return <NotAuthorizedView section="settings" className="h-auto" />;
@@ -53,7 +53,7 @@ const InitiativesSettingsPage = observer(() => {
const payload = {
[EWorkspaceFeatures.IS_INITIATIVES_ENABLED]: !isInitiativesFeatureEnabled,
};
const toggleInitiativesFeaturePromise = updateWorkspaceFeature(workspaceSlug.toString(), payload);
const toggleInitiativesFeaturePromise = updateWorkspaceFeature(workspaceSlug, payload);
setPromiseToast(toggleInitiativesFeaturePromise, {
loading: t("project_settings.initiatives.toast.updating"),
success: {
@@ -95,8 +95,8 @@ const InitiativesSettingsPage = observer(() => {
/>
<WithFeatureFlagHOC
flag="INITIATIVES"
fallback={<InitiativesUpgrade workspaceSlug={workspaceSlug?.toString()} redirect />}
workspaceSlug={workspaceSlug?.toString()}
fallback={<InitiativesUpgrade workspaceSlug={workspaceSlug} redirect />}
workspaceSlug={workspaceSlug}
>
<div className=" py-6 flex items-center justify-between gap-2 w-full">
<div className="flex items-center gap-4">
@@ -120,6 +120,6 @@ const InitiativesSettingsPage = observer(() => {
</div>
</SettingsContentWrapper>
);
});
}
export default InitiativesSettingsPage;
export default observer(InitiativesSettingsPage);
@@ -1,9 +1,9 @@
"use client";
import type { FC } from "react";
import { useEffect } from "react";
import { observer } from "mobx-react";
import Image from "next/image";
import { useSearchParams } from "next/navigation";
import { useTheme } from "next-themes";
import useSWR from "swr";
// plane web components components
@@ -23,8 +23,9 @@ import { SiloAppService } from "@/plane-web/services/integrations/silo.service";
const siloAppService = new SiloAppService();
const GitHubEnterpriseIntegration: FC<{ searchParams?: { error: string } }> = observer(({ searchParams }) => {
function GitHubEnterpriseIntegration() {
// hooks
const searchParams = useSearchParams();
const { resolvedTheme } = useTheme();
const {
workspace,
@@ -64,7 +65,7 @@ const GitHubEnterpriseIntegration: FC<{ searchParams?: { error: string } }> = ob
);
// error message
const errorCode = searchParams?.error;
const errorCode = searchParams?.get("error");
useEffect(() => {
if (!errorCode) {
return;
@@ -133,6 +134,6 @@ const GitHubEnterpriseIntegration: FC<{ searchParams?: { error: string } }> = ob
{organization && <IntegrationRoot isEnterprise />}
</div>
);
});
}
export default GitHubEnterpriseIntegration;
export default observer(GitHubEnterpriseIntegration);
@@ -1,8 +1,8 @@
"use client";
import type { FC } from "react";
import { useEffect } from "react";
import { observer } from "mobx-react";
import { useSearchParams } from "next/navigation";
import useSWR from "swr";
// plane web components components
import { Cloud } from "lucide-react";
@@ -20,7 +20,8 @@ import { SiloAppService } from "@/plane-web/services/integrations/silo.service";
const siloAppService = new SiloAppService();
const GitHubIntegration: FC<{ searchParams?: { error: string } }> = observer(({ searchParams }) => {
function GitHubIntegration() {
const searchParams = useSearchParams();
// hooks
const {
workspace,
@@ -58,7 +59,7 @@ const GitHubIntegration: FC<{ searchParams?: { error: string } }> = observer(({
);
// error message
const errorCode = searchParams?.error;
const errorCode = searchParams.get("error");
useEffect(() => {
if (!errorCode) {
return;
@@ -135,6 +136,6 @@ const GitHubIntegration: FC<{ searchParams?: { error: string } }> = observer(({
{organization && <IntegrationRoot isEnterprise={false} />}
</div>
);
});
}
export default GitHubIntegration;
export default observer(GitHubIntegration);
@@ -1,8 +1,8 @@
"use client";
import type { FC } from "react";
import { useEffect } from "react";
import { observer } from "mobx-react";
import { useSearchParams } from "next/navigation";
import useSWR from "swr";
// plane web components components
import { Cloud } from "lucide-react";
@@ -20,8 +20,9 @@ import { SiloAppService } from "@/plane-web/services/integrations/silo.service";
const siloAppService = new SiloAppService();
const GitlabEnterpriseIntegration: FC<{ searchParams?: { error: string } }> = observer(({ searchParams }) => {
function GitlabEnterpriseIntegration() {
// hooks
const searchParams = useSearchParams();
const {
workspace,
externalApiToken,
@@ -59,7 +60,7 @@ const GitlabEnterpriseIntegration: FC<{ searchParams?: { error: string } }> = ob
);
// error message
const errorCode = searchParams?.error;
const errorCode = searchParams.get("error");
useEffect(() => {
if (!errorCode) {
return;
@@ -137,6 +138,6 @@ const GitlabEnterpriseIntegration: FC<{ searchParams?: { error: string } }> = ob
{organization && <IntegrationRoot isEnterprise />}
</div>
);
});
}
export default GitlabEnterpriseIntegration;
export default observer(GitlabEnterpriseIntegration);
@@ -1,8 +1,8 @@
"use client";
import type { FC } from "react";
import { useEffect } from "react";
import { observer } from "mobx-react";
import { useSearchParams } from "next/navigation";
import useSWR from "swr";
// plane web components components
import { Cloud } from "lucide-react";
@@ -20,8 +20,9 @@ import { SiloAppService } from "@/plane-web/services/integrations/silo.service";
const siloAppService = new SiloAppService();
const GitlabIntegration: FC<{ searchParams?: { error: string } }> = observer(({ searchParams }) => {
function GitlabIntegration() {
// hooks
const searchParams = useSearchParams();
const {
workspace,
externalApiToken,
@@ -58,7 +59,7 @@ const GitlabIntegration: FC<{ searchParams?: { error: string } }> = observer(({
);
// error message
const errorCode = searchParams?.error;
const errorCode = searchParams.get("error");
useEffect(() => {
if (!errorCode) {
return;
@@ -136,6 +137,6 @@ const GitlabIntegration: FC<{ searchParams?: { error: string } }> = observer(({
{organization && <IntegrationRoot isEnterprise={false} />}
</div>
);
});
}
export default GitlabIntegration;
export default observer(GitlabIntegration);
@@ -2,7 +2,6 @@
import { observer } from "mobx-react";
import Link from "next/link";
import { useParams } from "next/navigation";
import { Outlet } from "react-router";
import { ChevronLeftIcon } from "lucide-react";
import { SILO_BASE_URL, SILO_BASE_PATH, E_FEATURE_FLAGS } from "@plane/constants";
@@ -12,10 +11,11 @@ import { useWorkspace } from "@/hooks/store/use-workspace";
import { useUser, useUserProfile } from "@/hooks/store/user";
import { WithFeatureFlagHOC } from "@/plane-web/components/feature-flags";
import { IntegrationsEmptyState } from "@/plane-web/components/integrations";
import type { Route } from "./+types/layout";
const IntegrationLayout = observer(() => {
function IntegrationLayout({ params }: Route.ComponentProps) {
// router params
const { workspaceSlug: workspaceSlugParam } = useParams();
const { workspaceSlug } = params;
// hooks
const { currentWorkspace } = useWorkspace();
@@ -24,12 +24,11 @@ const IntegrationLayout = observer(() => {
// derived values
const siloBaseUrl = encodeURI(SILO_BASE_URL + SILO_BASE_PATH) || undefined;
const workspaceSlug = workspaceSlugParam?.toString() || undefined;
const workspaceId = currentWorkspace?.id || undefined;
const userId = currentUser?.id || undefined;
// check if workspace exists
if (!workspaceSlug || !workspaceId || !userId || !siloBaseUrl) return null;
if (!workspaceId || !userId || !siloBaseUrl) return null;
return (
<WithFeatureFlagHOC
@@ -53,6 +52,6 @@ const IntegrationLayout = observer(() => {
</SettingsContentWrapper>
</WithFeatureFlagHOC>
);
});
}
export default IntegrationLayout;
export default observer(IntegrationLayout);
@@ -1,9 +1,8 @@
"use client";
import type { FC } from "react";
import { useEffect } from "react";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
import { useSearchParams } from "next/navigation";
import useSWR from "swr";
import { Cloud } from "lucide-react";
// plane web components
@@ -17,14 +16,16 @@ import { SentryIntegrationRoot } from "@/plane-web/components/integrations/sentr
import { useFlag, useWorkspaceSubscription } from "@/plane-web/hooks/store";
// plane web constants
import { SiloAppService } from "@/plane-web/services/integrations/silo.service";
import type { Route } from "./+types/page";
const siloAppService = new SiloAppService();
const SentryIntegration: FC<{ searchParams?: { error: string } }> = observer(({ searchParams }) => {
function SentryIntegration({ params }: Route.ComponentProps) {
// router
const { workspaceSlug } = useParams();
const { workspaceSlug } = params;
const searchParams = useSearchParams();
// derived values
const isFeatureEnabled = useFlag(workspaceSlug?.toString(), "SENTRY_INTEGRATION");
const isFeatureEnabled = useFlag(workspaceSlug, "SENTRY_INTEGRATION");
const { currentWorkspaceSubscribedPlanDetail: subscriptionDetail } = useWorkspaceSubscription();
// derived values
@@ -41,7 +42,7 @@ const SentryIntegration: FC<{ searchParams?: { error: string } }> = observer(({
const { t } = useTranslation();
// error message
const errorCode = searchParams?.error;
const errorCode = searchParams.get("error");
useEffect(() => {
if (!errorCode) {
return;
@@ -103,6 +104,6 @@ const SentryIntegration: FC<{ searchParams?: { error: string } }> = observer(({
)}
</div>
);
});
}
export default SentryIntegration;
export default observer(SentryIntegration);
@@ -1,9 +1,8 @@
"use client";
import type { FC } from "react";
import { useEffect } from "react";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
import { useSearchParams } from "next/navigation";
import useSWR from "swr";
import { Cloud } from "lucide-react";
// plane web components
@@ -19,16 +18,18 @@ import { useFlag, useWorkspaceSubscription } from "@/plane-web/hooks/store";
// plane web constants
import { useSlackIntegration } from "@/plane-web/hooks/store/integrations/use-slack";
import { SiloAppService } from "@/plane-web/services/integrations/silo.service";
import type { Route } from "./+types/page";
const siloAppService = new SiloAppService();
const SlackIntegration: FC<{ searchParams?: { error: string } }> = observer(({ searchParams }) => {
function SlackIntegration({ params }: Route.ComponentProps) {
// router
const { workspaceSlug } = useParams();
const { workspaceSlug } = params;
const searchParams = useSearchParams();
// store hooks
const { fetchExternalApiToken, externalApiToken } = useSlackIntegration();
// derived values
const isFeatureEnabled = useFlag(workspaceSlug?.toString(), E_FEATURE_FLAGS.SLACK_INTEGRATION) || false;
const isFeatureEnabled = useFlag(workspaceSlug, E_FEATURE_FLAGS.SLACK_INTEGRATION) || false;
const { currentWorkspaceSubscribedPlanDetail: subscriptionDetail } = useWorkspaceSubscription();
// derived values
@@ -46,13 +47,13 @@ const SlackIntegration: FC<{ searchParams?: { error: string } }> = observer(({ s
// fetching external api token
const { isLoading: externalApiTokenIsLoading } = useSWR(
workspaceSlug && !externalApiToken ? `IMPORTER_EXTERNAL_SERVICE_TOKEN` : null,
workspaceSlug && !externalApiToken ? async () => fetchExternalApiToken(workspaceSlug?.toString()) : null,
!externalApiToken ? `IMPORTER_EXTERNAL_SERVICE_TOKEN` : null,
!externalApiToken ? async () => fetchExternalApiToken(workspaceSlug) : null,
{ errorRetryCount: 0 }
);
// error message
const errorCode = searchParams?.error;
const errorCode = searchParams.get("error");
useEffect(() => {
if (!errorCode) {
return;
@@ -130,6 +131,6 @@ const SlackIntegration: FC<{ searchParams?: { error: string } }> = observer(({ s
)}
</div>
);
});
}
export default SlackIntegration;
export default observer(SlackIntegration);
@@ -3,7 +3,6 @@
import { observer } from "mobx-react";
// component
import { useParams } from "next/navigation";
import useSWR from "swr";
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import { setToast, TOAST_TYPE } from "@plane/propel/toast";
@@ -18,26 +17,24 @@ import { useUserPermissions } from "@/hooks/store/user";
// plane web components
import { CreateUpdateApplication } from "@/plane-web/components/marketplace";
import { useApplications } from "@/plane-web/hooks/store";
import type { Route } from "./+types/page";
const ApplicationEditPage = observer(() => {
function ApplicationEditPage({ params }: Route.ComponentProps) {
// store hooks
const { workspaceUserInfo, allowPermissions } = useUserPermissions();
const { currentWorkspace } = useWorkspace();
const { appSlug } = useParams();
const { appSlug } = params;
const { updateApplication, getApplicationBySlug, fetchApplication, fetchApplicationCategories } = useApplications();
// derived values
const canPerformWorkspaceAdminActions = allowPermissions([EUserPermissions.ADMIN], EUserPermissionsLevel.WORKSPACE);
const pageTitle = currentWorkspace?.name ? `${currentWorkspace.name} - Edit Application` : undefined;
const application = getApplicationBySlug(appSlug?.toString() || "");
const application = getApplicationBySlug(appSlug);
// state
const { data, isLoading } = useSWR(
appSlug ? APPLICATION_DETAILS(appSlug.toString()) : null,
appSlug ? async () => fetchApplication(appSlug.toString()) : null
);
const { data, isLoading } = useSWR(APPLICATION_DETAILS(appSlug), () => fetchApplication(appSlug));
useSWR(APPLICATION_CATEGORIES_LIST(), async () => fetchApplicationCategories());
useSWR(APPLICATION_CATEGORIES_LIST(), () => fetchApplicationCategories());
const handleFormSubmit = async (data: Partial<TApplication>): Promise<TApplication | undefined> => {
try {
@@ -74,6 +71,6 @@ const ApplicationEditPage = observer(() => {
<CreateUpdateApplication formData={application} handleFormSubmit={handleFormSubmit} />
</>
);
});
}
export default ApplicationEditPage;
export default observer(ApplicationEditPage);
@@ -3,7 +3,6 @@
import { observer } from "mobx-react";
// component
import { useParams } from "next/navigation";
import useSWR from "swr";
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import { NotAuthorizedView } from "@/components/auth-screens/not-authorized-view";
@@ -16,23 +15,21 @@ import { useUserPermissions } from "@/hooks/store/user";
// plane web components
import { ApplicationInstallationDetails } from "@/plane-web/components/marketplace/applications";
import { useApplications } from "@/plane-web/hooks/store";
import type { Route } from "./+types/page";
const ApplicationInstallPage: React.FC = observer(() => {
function ApplicationInstallPage({ params }: Route.ComponentProps) {
// store hooks
const { workspaceUserInfo, allowPermissions } = useUserPermissions();
const { currentWorkspace } = useWorkspace();
const { appSlug } = useParams();
const { appSlug } = params;
const { getApplicationBySlug, fetchApplication } = useApplications();
// derived values
const canPerformWorkspaceAdminActions = allowPermissions([EUserPermissions.ADMIN], EUserPermissionsLevel.WORKSPACE);
const pageTitle = currentWorkspace?.name ? `${currentWorkspace.name} - Install Application` : undefined;
const application = getApplicationBySlug(appSlug?.toString() || "");
const { data, isLoading } = useSWR(
appSlug ? APPLICATION_DETAILS(appSlug.toString()) : null,
appSlug ? async () => fetchApplication(appSlug.toString()) : null
);
const application = getApplicationBySlug(appSlug);
const { data, isLoading } = useSWR(APPLICATION_DETAILS(appSlug), () => fetchApplication(appSlug));
if (!data || !application || isLoading) {
return <EmailSettingsLoader />;
@@ -48,6 +45,6 @@ const ApplicationInstallPage: React.FC = observer(() => {
<ApplicationInstallationDetails app={application} />
</>
);
});
}
export default ApplicationInstallPage;
export default observer(ApplicationInstallPage);
@@ -1,12 +1,12 @@
"use client";
import Link from "next/link";
import { useParams } from "next/navigation";
import { Outlet } from "react-router";
import { ChevronLeftIcon } from "lucide-react";
import type { Route } from "./+types/layout";
const IntegrationLayout = () => {
const { workspaceSlug } = useParams();
function IntegrationLayout({ params }: Route.ComponentProps) {
const { workspaceSlug } = params;
return (
<div className="w-full h-full">
<Link
@@ -19,6 +19,6 @@ const IntegrationLayout = () => {
<Outlet />
</div>
);
};
}
export default IntegrationLayout;
@@ -4,7 +4,6 @@ import { observer } from "mobx-react";
// component
import Link from "next/link";
import { useParams } from "next/navigation";
import useSWR from "swr";
import { ChevronLeftIcon } from "lucide-react";
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
@@ -12,25 +11,26 @@ import { setToast, TOAST_TYPE } from "@plane/propel/toast";
import type { TUserApplication } from "@plane/types";
import { NotAuthorizedView } from "@/components/auth-screens/not-authorized-view";
import { PageHead } from "@/components/core/page-title";
import { APPLICATION_CATEGORIES_LIST } from "@/constants/fetch-keys";
// hooks
import { APPLICATION_CATEGORIES_LIST } from "@/constants/fetch-keys";
import { useWorkspace } from "@/hooks/store/use-workspace";
import { useUserPermissions } from "@/hooks/store/user";
// plane web components
import { CreateUpdateApplication } from "@/plane-web/components/marketplace";
import { useApplications } from "@/plane-web/hooks/store";
import type { Route } from "./+types/page";
const ApplicationCreatePage = observer(() => {
function ApplicationCreatePage({ params }: Route.ComponentProps) {
// store hooks
const { workspaceUserInfo, allowPermissions } = useUserPermissions();
const { currentWorkspace } = useWorkspace();
const { createApplication, fetchApplicationCategories } = useApplications();
const { workspaceSlug } = useParams();
const { workspaceSlug } = params;
// derived values
const canPerformWorkspaceAdminActions = allowPermissions([EUserPermissions.ADMIN], EUserPermissionsLevel.WORKSPACE);
const pageTitle = currentWorkspace?.name ? `${currentWorkspace.name} - Create Application` : undefined;
const { data: categories } = useSWR(APPLICATION_CATEGORIES_LIST(), async () => fetchApplicationCategories());
useSWR(APPLICATION_CATEGORIES_LIST(), async () => fetchApplicationCategories());
const handleFormSubmit = async (data: Partial<TUserApplication>) => {
try {
@@ -71,6 +71,6 @@ const ApplicationCreatePage = observer(() => {
</div>
</>
);
});
}
export default ApplicationCreatePage;
export default observer(ApplicationCreatePage);
@@ -1,8 +1,6 @@
"use client";
import React from "react";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// plane imports
import {
E_FEATURE_FLAGS,
@@ -28,10 +26,11 @@ import { WithFeatureFlagHOC } from "@/plane-web/components/feature-flags";
import { PiChatUpgrade } from "@/plane-web/components/pi-chat/upgrade";
import { useWorkspaceFeatures } from "@/plane-web/hooks/store";
import { EWorkspaceFeatures } from "@/plane-web/types/workspace-feature";
import type { Route } from "./+types/page";
const PlaneIntelligenceSettingsPage = observer(() => {
function PlaneIntelligenceSettingsPage({ params }: Route.ComponentProps) {
// router
const { workspaceSlug } = useParams();
const { workspaceSlug } = params;
// store hooks
const { getWorkspaceRoleByWorkspaceSlug } = useUserPermissions();
const { currentWorkspace } = useWorkspace();
@@ -39,12 +38,12 @@ const PlaneIntelligenceSettingsPage = observer(() => {
const { t } = useTranslation();
// derived values
const currentWorkspaceRole = getWorkspaceRoleByWorkspaceSlug(workspaceSlug.toString());
const currentWorkspaceRole = getWorkspaceRoleByWorkspaceSlug(workspaceSlug);
const pageTitle = currentWorkspace?.name ? `${currentWorkspace.name} - Plane Intelligence` : undefined;
const isAdmin = currentWorkspaceRole === EUserWorkspaceRoles.ADMIN;
const isPlaneIntelligenceFeatureEnabled = isWorkspaceFeatureEnabled(EWorkspaceFeatures.IS_PI_ENABLED);
if (!workspaceSlug || !currentWorkspace?.id) return <></>;
if (!currentWorkspace?.id) return <></>;
if (!isAdmin) return <NotAuthorizedView section="settings" className="h-auto" />;
@@ -56,7 +55,7 @@ const PlaneIntelligenceSettingsPage = observer(() => {
const payload = {
[EWorkspaceFeatures.IS_PI_ENABLED]: !isPlaneIntelligenceFeatureEnabled,
};
const toggleTeamsFeaturePromise = updateWorkspaceFeature(workspaceSlug.toString(), payload);
const toggleTeamsFeaturePromise = updateWorkspaceFeature(workspaceSlug, payload);
setPromiseToast(toggleTeamsFeaturePromise, {
loading: "Updating Plane Intelligence feature...",
success: {
@@ -72,7 +71,7 @@ const PlaneIntelligenceSettingsPage = observer(() => {
captureSuccess({
eventName: PLANE_INTELLIGENCE_TRACKER_EVENTS.TOGGLE,
payload: {
workspace_slug: workspaceSlug.toString(),
workspace_slug: workspaceSlug,
type: isPlaneIntelligenceFeatureEnabled ? "disable" : "enable",
},
});
@@ -81,7 +80,7 @@ const PlaneIntelligenceSettingsPage = observer(() => {
captureError({
eventName: PLANE_INTELLIGENCE_TRACKER_EVENTS.TOGGLE,
payload: {
workspace_slug: workspaceSlug.toString(),
workspace_slug: workspaceSlug,
type: isPlaneIntelligenceFeatureEnabled ? "disable" : "enable",
},
});
@@ -95,7 +94,7 @@ const PlaneIntelligenceSettingsPage = observer(() => {
<WithFeatureFlagHOC
flag={E_FEATURE_FLAGS.PI_CHAT || E_FEATURE_FLAGS.PI_DEDUPE || E_FEATURE_FLAGS.EDITOR_AI_OPS}
fallback={<PiChatUpgrade />}
workspaceSlug={workspaceSlug?.toString()}
workspaceSlug={workspaceSlug}
>
<div className="px-4 py-6 flex items-center justify-between gap-2 border-b border-custom-border-100 w-full">
<div className="flex items-center gap-4">
@@ -117,6 +116,6 @@ const PlaneIntelligenceSettingsPage = observer(() => {
</WithFeatureFlagHOC>
</SettingsContentWrapper>
);
});
}
export default PlaneIntelligenceSettingsPage;
export default observer(PlaneIntelligenceSettingsPage);
@@ -1,8 +1,6 @@
"use client";
import React from "react";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// plane imports
import { PROJECT_GROUPING_TRACKER_EVENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
@@ -27,23 +25,25 @@ import {
// plane web hooks
import { useFlag, useWorkspaceFeatures } from "@/plane-web/hooks/store";
import { EWorkspaceFeatures } from "@/plane-web/types/workspace-feature";
const WorklogsPage = observer(() => {
import type { Route } from "./+types/page";
function WorklogsPage({ params }: Route.ComponentProps) {
// router
const { workspaceSlug } = useParams();
const { workspaceSlug } = params;
// store hooks
const { getWorkspaceRoleByWorkspaceSlug } = useUserPermissions();
const { currentWorkspace } = useWorkspace();
const { isWorkspaceFeatureEnabled, updateWorkspaceFeature } = useWorkspaceFeatures();
const isFeatureEnabled = useFlag(workspaceSlug?.toString(), "PROJECT_GROUPING");
const isFeatureEnabled = useFlag(workspaceSlug, "PROJECT_GROUPING");
const { t } = useTranslation();
// derived values
const currentWorkspaceRole = getWorkspaceRoleByWorkspaceSlug(workspaceSlug.toString());
const currentWorkspaceRole = getWorkspaceRoleByWorkspaceSlug(workspaceSlug);
const pageTitle = currentWorkspace?.name ? `${currentWorkspace.name} - Project States` : undefined;
const isAdmin = currentWorkspaceRole === EUserWorkspaceRoles.ADMIN;
const isProjectGroupingEnabled = isWorkspaceFeatureEnabled(EWorkspaceFeatures.IS_PROJECT_GROUPING_ENABLED);
if (!workspaceSlug || !currentWorkspace?.id) return <></>;
if (!currentWorkspace?.id) return <></>;
if (!isAdmin) return <NotAuthorizedView section="settings" className="h-auto" />;
@@ -53,7 +53,7 @@ const WorklogsPage = observer(() => {
const payload = {
[EWorkspaceFeatures.IS_PROJECT_GROUPING_ENABLED]: willEnableProjectGrouping,
};
await updateWorkspaceFeature(workspaceSlug.toString(), payload);
await updateWorkspaceFeature(workspaceSlug, payload);
captureSuccess({
eventName: willEnableProjectGrouping
? PROJECT_GROUPING_TRACKER_EVENTS.ENABLE
@@ -87,12 +87,12 @@ const WorklogsPage = observer(() => {
<WithFeatureFlagHOC
flag="PROJECT_GROUPING"
fallback={<WorkspaceProjectStatesUpgrade />}
workspaceSlug={workspaceSlug?.toString()}
workspaceSlug={workspaceSlug}
>
<main className="container mx-auto space-y-4 w-full">
<WorkspaceProjectStatesRoot
isProjectGroupingEnabled={isProjectGroupingEnabled}
workspaceSlug={workspaceSlug.toString()}
workspaceSlug={workspaceSlug}
workspaceId={currentWorkspace?.id}
toggleProjectGroupingFeature={toggleProjectGroupingFeature}
/>
@@ -101,6 +101,6 @@ const WorklogsPage = observer(() => {
</div>
</SettingsContentWrapper>
);
});
}
export default WorklogsPage;
export default observer(WorklogsPage);
@@ -1,8 +1,6 @@
"use client";
import React from "react";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// plane imports
import { TEAMSPACE_TRACKER_ELEMENTS, TEAMSPACE_TRACKER_EVENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
@@ -24,10 +22,11 @@ import { WithFeatureFlagHOC } from "@/plane-web/components/feature-flags";
import { TeamspaceUpgrade } from "@/plane-web/components/teamspaces/upgrade";
import { useWorkspaceFeatures } from "@/plane-web/hooks/store";
import { EWorkspaceFeatures } from "@/plane-web/types/workspace-feature";
import type { Route } from "./+types/page";
const TeamspaceSettingsPage = observer(() => {
function TeamspaceSettingsPage({ params }: Route.ComponentProps) {
// router
const { workspaceSlug } = useParams();
const { workspaceSlug } = params;
// store hooks
const { getWorkspaceRoleByWorkspaceSlug } = useUserPermissions();
const { currentWorkspace } = useWorkspace();
@@ -35,12 +34,12 @@ const TeamspaceSettingsPage = observer(() => {
const { t } = useTranslation();
// derived values
const currentWorkspaceRole = getWorkspaceRoleByWorkspaceSlug(workspaceSlug.toString());
const currentWorkspaceRole = getWorkspaceRoleByWorkspaceSlug(workspaceSlug);
const pageTitle = currentWorkspace?.name ? `${currentWorkspace.name} - Teamspaces` : undefined;
const isAdmin = currentWorkspaceRole === EUserWorkspaceRoles.ADMIN;
const isTeamspacesFeatureEnabled = isWorkspaceFeatureEnabled(EWorkspaceFeatures.IS_TEAMSPACES_ENABLED);
if (!workspaceSlug || !currentWorkspace?.id) return <></>;
if (!currentWorkspace?.id) return <></>;
if (!isAdmin) return <NotAuthorizedView section="settings" className="h-auto" />;
@@ -52,7 +51,7 @@ const TeamspaceSettingsPage = observer(() => {
const payload = {
[EWorkspaceFeatures.IS_TEAMSPACES_ENABLED]: !isTeamspacesFeatureEnabled,
};
const toggleTeamsFeaturePromise = updateWorkspaceFeature(workspaceSlug.toString(), payload);
const toggleTeamsFeaturePromise = updateWorkspaceFeature(workspaceSlug, payload);
setPromiseToast(toggleTeamsFeaturePromise, {
loading: "Updating teamspaces feature...",
success: {
@@ -68,7 +67,7 @@ const TeamspaceSettingsPage = observer(() => {
captureSuccess({
eventName: isTeamspacesFeatureEnabled ? TEAMSPACE_TRACKER_EVENTS.DISABLE : TEAMSPACE_TRACKER_EVENTS.ENABLE,
payload: {
workspace_slug: workspaceSlug.toString(),
workspace_slug: workspaceSlug,
},
});
} catch (error) {
@@ -76,7 +75,7 @@ const TeamspaceSettingsPage = observer(() => {
captureError({
eventName: isTeamspacesFeatureEnabled ? TEAMSPACE_TRACKER_EVENTS.DISABLE : TEAMSPACE_TRACKER_EVENTS.ENABLE,
payload: {
workspace_slug: workspaceSlug.toString(),
workspace_slug: workspaceSlug,
},
});
}
@@ -89,7 +88,7 @@ const TeamspaceSettingsPage = observer(() => {
title={t("workspace_settings.settings.teamspaces.heading")}
description={t("workspace_settings.settings.teamspaces.description")}
/>
<WithFeatureFlagHOC flag="TEAMSPACES" fallback={<TeamspaceUpgrade />} workspaceSlug={workspaceSlug?.toString()}>
<WithFeatureFlagHOC flag="TEAMSPACES" fallback={<TeamspaceUpgrade />} workspaceSlug={workspaceSlug}>
<div className="px-4 py-6 flex items-center justify-between gap-2 border-b border-custom-border-100 w-full">
<div className="flex items-center gap-4">
<div className="size-10 bg-custom-background-90 rounded-md flex items-center justify-center">
@@ -120,6 +119,6 @@ const TeamspaceSettingsPage = observer(() => {
</WithFeatureFlagHOC>
</SettingsContentWrapper>
);
});
}
export default TeamspaceSettingsPage;
export default observer(TeamspaceSettingsPage);
@@ -2,14 +2,14 @@
import { observer } from "mobx-react";
import Link from "next/link";
import { useParams } from "next/navigation";
import { Outlet } from "react-router";
import { ChevronLeftIcon } from "lucide-react";
import { SettingsContentWrapper } from "@/components/settings/content-wrapper";
import type { Route } from "./+types/layout";
const TemplatesLayout = observer(() => {
function TemplatesLayout({ params }: Route.ComponentProps) {
// router params
const { workspaceSlug } = useParams();
const { workspaceSlug } = params;
return (
<SettingsContentWrapper>
@@ -25,6 +25,6 @@ const TemplatesLayout = observer(() => {
</div>
</SettingsContentWrapper>
);
});
}
export default TemplatesLayout;
export default observer(TemplatesLayout);
@@ -1,7 +1,7 @@
"use client";
import { observer } from "mobx-react";
import { useParams, useSearchParams } from "next/navigation";
import { useSearchParams } from "next/navigation";
// plane imports
import { E_FEATURE_FLAGS, ETemplateLevel } from "@plane/constants";
// plane web imports
@@ -9,10 +9,11 @@ import { useTranslation } from "@plane/i18n";
import { WithFeatureFlagHOC } from "@/plane-web/components/feature-flags";
import { TemplatesUpgrade } from "@/plane-web/components/templates/settings";
import { CreateUpdatePageTemplate } from "@/plane-web/components/templates/settings/page/create-update";
import type { Route } from "./+types/page";
const CreateWorkspaceLevelPageTemplatePage = observer(() => {
function CreateWorkspaceLevelPageTemplatePage({ params }: Route.ComponentProps) {
// router
const { workspaceSlug } = useParams();
const { workspaceSlug } = params;
const searchParams = useSearchParams();
// store hooks
const { t } = useTranslation();
@@ -21,7 +22,7 @@ const CreateWorkspaceLevelPageTemplatePage = observer(() => {
return (
<WithFeatureFlagHOC
workspaceSlug={workspaceSlug?.toString()}
workspaceSlug={workspaceSlug}
flag={E_FEATURE_FLAGS.PAGE_TEMPLATES}
fallback={<TemplatesUpgrade flag={E_FEATURE_FLAGS.PAGE_TEMPLATES} />}
>
@@ -31,12 +32,12 @@ const CreateWorkspaceLevelPageTemplatePage = observer(() => {
</div>
</div>
<CreateUpdatePageTemplate
workspaceSlug={workspaceSlug?.toString()}
workspaceSlug={workspaceSlug}
currentLevel={ETemplateLevel.WORKSPACE}
templateId={templateId ?? undefined}
/>
</WithFeatureFlagHOC>
);
});
}
export default CreateWorkspaceLevelPageTemplatePage;
export default observer(CreateWorkspaceLevelPageTemplatePage);
@@ -1,7 +1,6 @@
"use client";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// plane imports
import { E_FEATURE_FLAGS } from "@plane/constants";
// plane web imports
@@ -9,28 +8,29 @@ import { WithFeatureFlagHOC } from "@/plane-web/components/feature-flags";
import { TemplatesUpgrade } from "@/plane-web/components/templates/settings";
import { PublishTemplate } from "@/plane-web/components/templates/settings/publish";
import { useProjectTemplates } from "@/plane-web/hooks/store";
import type { Route } from "./+types/page";
const PublishProjectTemplatePage = observer(() => {
function PublishProjectTemplatePage({ params }: Route.ComponentProps) {
// router
const { workspaceSlug, templateId } = useParams();
const { workspaceSlug, templateId } = params;
// store hooks
const { isInitializingTemplates, getTemplateById } = useProjectTemplates();
// derived values
const templateInstance = getTemplateById(templateId?.toString());
const templateInstance = getTemplateById(templateId);
return (
<WithFeatureFlagHOC
workspaceSlug={workspaceSlug?.toString()}
workspaceSlug={workspaceSlug}
flag={E_FEATURE_FLAGS.PROJECT_TEMPLATES_PUBLISH}
fallback={<TemplatesUpgrade flag={E_FEATURE_FLAGS.PROJECT_TEMPLATES_PUBLISH} />}
>
<PublishTemplate
workspaceSlug={workspaceSlug?.toString()}
workspaceSlug={workspaceSlug}
templateInstance={templateInstance}
isInitializing={isInitializingTemplates}
/>
</WithFeatureFlagHOC>
);
});
}
export default PublishProjectTemplatePage;
export default observer(PublishProjectTemplatePage);
@@ -1,7 +1,7 @@
"use client";
import { observer } from "mobx-react";
import { useParams, useSearchParams } from "next/navigation";
import { useSearchParams } from "next/navigation";
// plane web imports
import { E_FEATURE_FLAGS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
@@ -9,10 +9,11 @@ import { WithFeatureFlagHOC } from "@/plane-web/components/feature-flags";
import { IssueModalProvider } from "@/plane-web/components/issues/issue-modal/provider";
import { TemplatesUpgrade } from "@/plane-web/components/templates/settings";
import { CreateUpdateProjectTemplate } from "@/plane-web/components/templates/settings/project";
import type { Route } from "./+types/page";
const CreateProjectTemplatePage = observer(() => {
function CreateProjectTemplatePage({ params }: Route.ComponentProps) {
// router
const { workspaceSlug } = useParams();
const { workspaceSlug } = params;
const searchParams = useSearchParams();
// store hooks
const { t } = useTranslation();
@@ -21,7 +22,7 @@ const CreateProjectTemplatePage = observer(() => {
return (
<WithFeatureFlagHOC
workspaceSlug={workspaceSlug?.toString()}
workspaceSlug={workspaceSlug}
flag={E_FEATURE_FLAGS.PROJECT_TEMPLATES}
fallback={<TemplatesUpgrade flag={E_FEATURE_FLAGS.PROJECT_TEMPLATES} />}
>
@@ -31,10 +32,10 @@ const CreateProjectTemplatePage = observer(() => {
</div>
</div>
<IssueModalProvider>
<CreateUpdateProjectTemplate workspaceSlug={workspaceSlug?.toString()} templateId={templateId ?? undefined} />
<CreateUpdateProjectTemplate workspaceSlug={workspaceSlug} templateId={templateId ?? undefined} />
</IssueModalProvider>
</WithFeatureFlagHOC>
);
});
}
export default CreateProjectTemplatePage;
export default observer(CreateProjectTemplatePage);
@@ -1,7 +1,7 @@
"use client";
import { observer } from "mobx-react";
import { useParams, useSearchParams } from "next/navigation";
import { useSearchParams } from "next/navigation";
// plane imports
import { E_FEATURE_FLAGS, ETemplateLevel } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
@@ -10,10 +10,11 @@ import { WithFeatureFlagHOC } from "@/plane-web/components/feature-flags";
import { IssueModalProvider } from "@/plane-web/components/issues/issue-modal/provider";
import { TemplatesUpgrade } from "@/plane-web/components/templates/settings";
import { CreateUpdateWorkItemTemplate } from "@/plane-web/components/templates/settings/work-item";
import type { Route } from "./+types/page";
const CreateWorkspaceLevelWorkItemTemplatePage = observer(() => {
function CreateWorkspaceLevelWorkItemTemplatePage({ params }: Route.ComponentProps) {
// router
const { workspaceSlug } = useParams();
const { workspaceSlug } = params;
const searchParams = useSearchParams();
// store hooks
const { t } = useTranslation();
@@ -22,7 +23,7 @@ const CreateWorkspaceLevelWorkItemTemplatePage = observer(() => {
return (
<WithFeatureFlagHOC
workspaceSlug={workspaceSlug?.toString()}
workspaceSlug={workspaceSlug}
flag={E_FEATURE_FLAGS.WORKITEM_TEMPLATES}
fallback={<TemplatesUpgrade flag={E_FEATURE_FLAGS.WORKITEM_TEMPLATES} />}
>
@@ -33,13 +34,13 @@ const CreateWorkspaceLevelWorkItemTemplatePage = observer(() => {
</div>
<IssueModalProvider>
<CreateUpdateWorkItemTemplate
workspaceSlug={workspaceSlug?.toString()}
workspaceSlug={workspaceSlug}
currentLevel={ETemplateLevel.WORKSPACE}
templateId={templateId ?? undefined}
/>
</IssueModalProvider>
</WithFeatureFlagHOC>
);
});
}
export default CreateWorkspaceLevelWorkItemTemplatePage;
export default observer(CreateWorkspaceLevelWorkItemTemplatePage);
@@ -1,8 +1,6 @@
"use client";
import React from "react";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// plane imports
import { E_FEATURE_FLAGS, ETemplateLevel, EUserPermissionsLevel } from "@plane/constants";
// component
@@ -23,9 +21,11 @@ import {
WorkspaceTemplatesSettingsRoot,
} from "@/plane-web/components/templates/settings";
import { useFlag, useProjectTemplates, useWorkItemTemplates, usePageTemplates } from "@/plane-web/hooks/store";
const TemplatesWorkspaceSettingsPage = observer(() => {
import type { Route } from "./+types/page";
function TemplatesWorkspaceSettingsPage({ params }: Route.ComponentProps) {
// router
const { workspaceSlug } = useParams();
const { workspaceSlug } = params;
// plane hooks
const { t } = useTranslation();
// store hooks
@@ -35,19 +35,19 @@ const TemplatesWorkspaceSettingsPage = observer(() => {
const { isAnyWorkItemTemplatesAvailable } = useWorkItemTemplates();
const { isAnyPageTemplatesAvailable } = usePageTemplates();
// derived values
const isProjectTemplatesEnabled = useFlag(workspaceSlug?.toString(), "PROJECT_TEMPLATES");
const isProjectTemplatesAvailable = isAnyProjectTemplatesAvailable(workspaceSlug?.toString());
const isWorkItemTemplatesEnabled = useFlag(workspaceSlug?.toString(), "WORKITEM_TEMPLATES");
const isWorkItemTemplatesAvailable = isAnyWorkItemTemplatesAvailable(workspaceSlug?.toString());
const isPageTemplatesEnabled = useFlag(workspaceSlug?.toString(), "PAGE_TEMPLATES");
const isPageTemplatesAvailable = isAnyPageTemplatesAvailable(workspaceSlug?.toString());
const isProjectTemplatesEnabled = useFlag(workspaceSlug, "PROJECT_TEMPLATES");
const isProjectTemplatesAvailable = isAnyProjectTemplatesAvailable(workspaceSlug);
const isWorkItemTemplatesEnabled = useFlag(workspaceSlug, "WORKITEM_TEMPLATES");
const isWorkItemTemplatesAvailable = isAnyWorkItemTemplatesAvailable(workspaceSlug);
const isPageTemplatesEnabled = useFlag(workspaceSlug, "PAGE_TEMPLATES");
const isPageTemplatesAvailable = isAnyPageTemplatesAvailable(workspaceSlug);
const isAnyTemplatesEnabled = isProjectTemplatesEnabled || isWorkItemTemplatesEnabled || isPageTemplatesEnabled;
const isAnyTemplatesAvailable =
isProjectTemplatesAvailable || isWorkItemTemplatesAvailable || isPageTemplatesAvailable;
const pageTitle = currentWorkspace?.name ? `${currentWorkspace.name} - ${t("common.templates")}` : undefined;
const hasAdminPermission = allowPermissions([EUserWorkspaceRoles.ADMIN], EUserPermissionsLevel.WORKSPACE);
if (!workspaceSlug || !currentWorkspace?.id) return <></>;
if (!currentWorkspace?.id) return <></>;
if (workspaceUserInfo && !hasAdminPermission) {
return <NotAuthorizedView section="settings" />;
@@ -63,7 +63,7 @@ const TemplatesWorkspaceSettingsPage = observer(() => {
<>
{isAnyTemplatesEnabled && isAnyTemplatesAvailable && hasAdminPermission && (
<CreateTemplatesButton
workspaceSlug={workspaceSlug?.toString()}
workspaceSlug={workspaceSlug}
currentLevel={ETemplateLevel.WORKSPACE}
buttonSize="sm"
variant="settings"
@@ -75,12 +75,12 @@ const TemplatesWorkspaceSettingsPage = observer(() => {
<WithFeatureFlagHOC
flag={E_FEATURE_FLAGS.WORKITEM_TEMPLATES}
fallback={<TemplatesUpgrade flag={E_FEATURE_FLAGS.WORKITEM_TEMPLATES} />}
workspaceSlug={workspaceSlug?.toString()}
workspaceSlug={workspaceSlug}
>
<WorkspaceTemplatesSettingsRoot workspaceSlug={workspaceSlug?.toString()} />
<WorkspaceTemplatesSettingsRoot workspaceSlug={workspaceSlug} />
</WithFeatureFlagHOC>
</SettingsContentWrapper>
);
});
}
export default TemplatesWorkspaceSettingsPage;
export default observer(TemplatesWorkspaceSettingsPage);
@@ -1,8 +1,6 @@
"use client";
import React from "react";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
import { EUserWorkspaceRoles } from "@plane/types";
// plane imports
// component
@@ -16,35 +14,33 @@ import { useUserPermissions } from "@/hooks/store/user";
import { WithFeatureFlagHOC } from "@/plane-web/components/feature-flags";
import { WorkspaceWorklogRoot, WorkspaceWorklogsUpgrade } from "@/plane-web/components/worklogs";
import { useFlag } from "@/plane-web/hooks/store";
const WorklogsPage = observer(() => {
import type { Route } from "./+types/page";
function WorklogsPage({ params }: Route.ComponentProps) {
// router
const { workspaceSlug } = useParams();
const { workspaceSlug } = params;
// store hooks
const { getWorkspaceRoleByWorkspaceSlug } = useUserPermissions();
const { currentWorkspace } = useWorkspace();
const isFeatureEnabled = useFlag(workspaceSlug.toString(), "ISSUE_WORKLOG");
const isFeatureEnabled = useFlag(workspaceSlug, "ISSUE_WORKLOG");
// derived values
const currentWorkspaceRole = getWorkspaceRoleByWorkspaceSlug(workspaceSlug.toString());
const currentWorkspaceRole = getWorkspaceRoleByWorkspaceSlug(workspaceSlug);
const pageTitle = currentWorkspace?.name ? `${currentWorkspace.name} - Worklogs` : undefined;
const isAdmin = currentWorkspaceRole === EUserWorkspaceRoles.ADMIN;
if (!workspaceSlug || !currentWorkspace) return <></>;
if (!currentWorkspace) return <></>;
if (!isAdmin) return <NotAuthorizedView section="settings" className="h-auto" />;
return (
<SettingsContentWrapper size={isFeatureEnabled ? "lg" : "md"}>
<PageHead title={pageTitle} />
<WithFeatureFlagHOC
workspaceSlug={workspaceSlug?.toString()}
flag="ISSUE_WORKLOG"
fallback={<WorkspaceWorklogsUpgrade />}
>
<WorkspaceWorklogRoot workspaceSlug={workspaceSlug.toString()} workspaceId={currentWorkspace.id} />
<WithFeatureFlagHOC workspaceSlug={workspaceSlug} flag="ISSUE_WORKLOG" fallback={<WorkspaceWorklogsUpgrade />}>
<WorkspaceWorklogRoot workspaceSlug={workspaceSlug} workspaceId={currentWorkspace.id} />
</WithFeatureFlagHOC>
</SettingsContentWrapper>
);
});
}
export default WorklogsPage;
export default observer(WorklogsPage);
@@ -1,7 +1,6 @@
"use client";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// plane imports
import { EUserPermissionsLevel } from "@plane/constants";
import { EUserProjectRoles } from "@plane/types";
@@ -16,10 +15,11 @@ import { useUserPermissions } from "@/hooks/store/user/user-permissions";
import { EpicsRoot } from "@/plane-web/components/epics/settings";
import { EpicsUpgrade } from "@/plane-web/components/epics/upgrade";
import { WithFeatureFlagHOC } from "@/plane-web/components/feature-flags";
import type { Route } from "./+types/page";
const EpicsSettingsPage = observer(() => {
function EpicsSettingsPage({ params }: Route.ComponentProps) {
// router
const { workspaceSlug } = useParams();
const { workspaceSlug } = params;
// store hooks
const { allowPermissions } = useUserPermissions();
const { currentProjectDetails } = useProject();
@@ -35,12 +35,12 @@ const EpicsSettingsPage = observer(() => {
<SettingsContentWrapper>
<PageHead title={pageTitle} />
<div className={`w-full h-full overflow-hidden `}>
<WithFeatureFlagHOC flag="EPICS" fallback={<EpicsUpgrade />} workspaceSlug={workspaceSlug?.toString()}>
<WithFeatureFlagHOC flag="EPICS" fallback={<EpicsUpgrade />} workspaceSlug={workspaceSlug}>
<EpicsRoot />
</WithFeatureFlagHOC>
</div>
</SettingsContentWrapper>
);
});
}
export default EpicsSettingsPage;
export default observer(EpicsSettingsPage);
@@ -2,7 +2,6 @@
import { observer } from "mobx-react";
import Link from "next/link";
import { useParams } from "next/navigation";
// plane imports
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import { ChevronLeftIcon } from "@plane/propel/icons";
@@ -19,17 +18,16 @@ import { useUserPermissions } from "@/hooks/store/user";
import { AutoScheduleCycles } from "@/plane-web/components/cycles/settings";
// plane web imports
import { PROJECT_BASE_FEATURES_LIST } from "@/plane-web/constants/project/settings";
import type { Route } from "./+types/page";
const CyclesFeatureSettingsPage = observer(() => {
const { workspaceSlug, projectId } = useParams();
function CyclesFeatureSettingsPage({ params }: Route.ComponentProps) {
const { workspaceSlug, projectId } = params;
// permissions
const { workspaceUserInfo, allowPermissions } = useUserPermissions();
const canPerformProjectAdminActions = allowPermissions([EUserPermissions.ADMIN], EUserPermissionsLevel.PROJECT);
// project store
const { getProjectById, updateProject } = useProject();
const currentProjectDetails = projectId ? getProjectById(projectId.toString()) : undefined;
if (!workspaceSlug || !projectId) return null;
const currentProjectDetails = getProjectById(projectId);
if (workspaceUserInfo && !canPerformProjectAdminActions) {
return <NotAuthorizedView section="settings" isProjectView className="h-auto" />;
@@ -39,8 +37,8 @@ const CyclesFeatureSettingsPage = observer(() => {
const handleToggle = async () => {
if (!currentProjectDetails) return;
const payload = { cycle_view: !Boolean(currentProjectDetails.cycle_view) };
const promise = updateProject(workspaceSlug.toString(), projectId.toString(), payload);
const payload = { cycle_view: !currentProjectDetails.cycle_view };
const promise = updateProject(workspaceSlug, projectId, payload);
setPromiseToast(promise, {
loading: "Updating project feature...",
success: { title: "Success!", message: () => "Project feature updated successfully." },
@@ -81,7 +79,7 @@ const CyclesFeatureSettingsPage = observer(() => {
</div>
<ToggleSwitch
value={Boolean(currentProjectDetails?.cycle_view)}
value={!!currentProjectDetails?.cycle_view}
onChange={handleToggle}
disabled={!canPerformProjectAdminActions}
size="sm"
@@ -93,6 +91,6 @@ const CyclesFeatureSettingsPage = observer(() => {
{currentProjectDetails?.cycle_view && <AutoScheduleCycles />}
</SettingsContentWrapper>
);
});
}
export default CyclesFeatureSettingsPage;
export default observer(CyclesFeatureSettingsPage);
@@ -1,7 +1,6 @@
"use client";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
import { useTheme } from "next-themes";
import useSWR from "swr";
// plane imports
@@ -20,27 +19,26 @@ import { PROJECT_DETAILS, WORKSPACE_INTEGRATIONS } from "@/constants/fetch-keys"
// services
import { IntegrationService } from "@/services/integrations";
import { ProjectService } from "@/services/project";
import type { Route } from "./+types/page";
// services
const integrationService = new IntegrationService();
const projectService = new ProjectService();
const ProjectIntegrationsPage = observer(() => {
function ProjectIntegrationsPage({ params }: Route.ComponentProps) {
// router
const { workspaceSlug, projectId } = useParams();
const { workspaceSlug, projectId } = params;
// plane hooks
const { t } = useTranslation();
// theme hook
const { resolvedTheme } = useTheme();
// fetch project details
const { data: projectDetails } = useSWR<IProject>(
workspaceSlug && projectId ? PROJECT_DETAILS(workspaceSlug?.toString(), projectId?.toString()) : null,
workspaceSlug && projectId ? () => projectService.getProject(workspaceSlug as string, projectId as string) : null
const { data: projectDetails } = useSWR<IProject>(PROJECT_DETAILS(workspaceSlug, projectId), () =>
projectService.getProject(workspaceSlug, projectId)
);
// fetch Integrations list
const { data: workspaceIntegrations } = useSWR(
workspaceSlug ? WORKSPACE_INTEGRATIONS(workspaceSlug as string) : null,
() => (workspaceSlug ? integrationService.getWorkspaceIntegrationsList(workspaceSlug as string) : null)
const { data: workspaceIntegrations } = useSWR(WORKSPACE_INTEGRATIONS(workspaceSlug), () =>
integrationService.getWorkspaceIntegrationsList(workspaceSlug)
);
// derived values
const isAdmin = projectDetails?.member_role === 20;
@@ -76,6 +74,6 @@ const ProjectIntegrationsPage = observer(() => {
</div>
</>
);
});
}
export default ProjectIntegrationsPage;
export default observer(ProjectIntegrationsPage);
@@ -1,8 +1,6 @@
"use client";
import React from "react";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// plane imports
import { EUserPermissionsLevel } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
@@ -20,16 +18,17 @@ import { WithFeatureFlagHOC } from "@/plane-web/components/feature-flags";
// plane web constants
import { ProjectUpdatesUpgrade } from "@/plane-web/components/project-overview/upgrade";
import { useProjectAdvanced } from "@/plane-web/hooks/store/projects/use-projects";
import type { Route } from "./+types/page";
const UpdatesSettingsPage = observer(() => {
function UpdatesSettingsPage({ params }: Route.ComponentProps) {
// router
const { workspaceSlug, projectId } = useParams();
const { workspaceSlug, projectId } = params;
// store hooks
const { allowPermissions } = useUserPermissions();
const { getProjectFeatures, toggleProjectFeatures } = useProjectAdvanced();
const { t } = useTranslation();
// derived values
const currentProjectDetails = getProjectFeatures(projectId?.toString());
const currentProjectDetails = getProjectFeatures(projectId);
const canPerformProjectAdminActions = allowPermissions([EUserProjectRoles.ADMIN], EUserPermissionsLevel.PROJECT);
if (!canPerformProjectAdminActions) {
@@ -51,7 +50,7 @@ const UpdatesSettingsPage = observer(() => {
const settingsPayload = {
is_project_updates_enabled: !currentProjectDetails?.["is_project_updates_enabled"],
};
const updateProjectPromise = toggleProjectFeatures(workspaceSlug.toString(), projectId.toString(), settingsPayload);
const updateProjectPromise = toggleProjectFeatures(workspaceSlug, projectId, settingsPayload);
setPromiseToast(updateProjectPromise, {
loading: "Updating project feature...",
success: {
@@ -72,11 +71,7 @@ const UpdatesSettingsPage = observer(() => {
title={t("project_settings.project_updates.heading")}
description={t("project_settings.project_updates.description")}
/>
<WithFeatureFlagHOC
flag="PROJECT_UPDATES"
fallback={<ProjectUpdatesUpgrade />}
workspaceSlug={workspaceSlug?.toString()}
>
<WithFeatureFlagHOC flag="PROJECT_UPDATES" fallback={<ProjectUpdatesUpgrade />} workspaceSlug={workspaceSlug}>
<>
<div className="px-4 py-6 flex items-center justify-between gap-2 border-b border-custom-border-100">
<div className="flex items-center gap-4">
@@ -104,6 +99,6 @@ const UpdatesSettingsPage = observer(() => {
</div>
</SettingsContentWrapper>
);
});
}
export default UpdatesSettingsPage;
export default observer(UpdatesSettingsPage);
@@ -1,7 +1,6 @@
"use client";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// plane imports
import { E_FEATURE_FLAGS } from "@plane/constants";
// plane web imports
@@ -10,17 +9,11 @@ import { WithFeatureFlagHOC } from "@/plane-web/components/feature-flags";
import { IssueModalProvider } from "@/plane-web/components/issues/issue-modal/provider";
import { CreateUpdateRecurringWorkItem } from "@/plane-web/components/recurring-work-items/settings/create-update/root";
import { RecurringWorkItemsUpgrade } from "@/plane-web/components/recurring-work-items/settings/upgrade";
import type { Route } from "./+types/page";
const UpdateRecurringWorkItemPage = observer(() => {
function UpdateRecurringWorkItemPage({ params }: Route.ComponentProps) {
// router
const {
workspaceSlug: routerWorkspaceSlug,
projectId: routerProjectId,
recurringWorkItemId: routerRecurringWorkItemId,
} = useParams();
const workspaceSlug = routerWorkspaceSlug?.toString();
const projectId = routerProjectId?.toString();
const recurringWorkItemId = routerRecurringWorkItemId?.toString();
const { workspaceSlug, projectId, recurringWorkItemId } = params;
// plane hooks
const { t } = useTranslation();
@@ -44,6 +37,6 @@ const UpdateRecurringWorkItemPage = observer(() => {
</IssueModalProvider>
</WithFeatureFlagHOC>
);
});
}
export default UpdateRecurringWorkItemPage;
export default observer(UpdateRecurringWorkItemPage);
@@ -1,7 +1,6 @@
"use client";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// plane imports
import { E_FEATURE_FLAGS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
@@ -10,12 +9,11 @@ import { WithFeatureFlagHOC } from "@/plane-web/components/feature-flags";
import { IssueModalProvider } from "@/plane-web/components/issues/issue-modal/provider";
import { CreateUpdateRecurringWorkItem } from "@/plane-web/components/recurring-work-items/settings/create-update/root";
import { RecurringWorkItemsUpgrade } from "@/plane-web/components/recurring-work-items/settings/upgrade";
import type { Route } from "./+types/page";
const CreateRecurringWorkItemPage = observer(() => {
function CreateRecurringWorkItemPage({ params }: Route.ComponentProps) {
// router
const { workspaceSlug: routerWorkspaceSlug, projectId: routerProjectId } = useParams();
const workspaceSlug = routerWorkspaceSlug?.toString();
const projectId = routerProjectId?.toString();
const { workspaceSlug, projectId } = params;
// plane hooks
const { t } = useTranslation();
@@ -35,6 +33,6 @@ const CreateRecurringWorkItemPage = observer(() => {
</IssueModalProvider>
</WithFeatureFlagHOC>
);
});
}
export default CreateRecurringWorkItemPage;
export default observer(CreateRecurringWorkItemPage);
@@ -2,7 +2,6 @@
import { observer } from "mobx-react";
import Link from "next/link";
import { useParams } from "next/navigation";
import { Outlet } from "react-router";
import { ChevronLeftIcon } from "lucide-react";
// plane imports
@@ -14,12 +13,11 @@ import { NotAuthorizedView } from "@/components/auth-screens/not-authorized-view
import { SettingsContentWrapper } from "@/components/settings/content-wrapper";
// hooks
import { useUserPermissions } from "@/hooks/store/user";
import type { Route } from "./+types/layout";
const RecurringWorkItemsDetailsLayout = observer(() => {
function RecurringWorkItemsDetailsLayout({ params }: Route.ComponentProps) {
// router params
const { workspaceSlug: routerWorkspaceSlug, projectId: routerProjectId } = useParams();
const workspaceSlug = routerWorkspaceSlug?.toString();
const projectId = routerProjectId?.toString();
const { workspaceSlug, projectId } = params;
// store hooks
const { workspaceUserInfo, allowPermissions } = useUserPermissions();
// derived values
@@ -45,6 +43,6 @@ const RecurringWorkItemsDetailsLayout = observer(() => {
</div>
</SettingsContentWrapper>
);
});
}
export default RecurringWorkItemsDetailsLayout;
export default observer(RecurringWorkItemsDetailsLayout);
@@ -1,7 +1,6 @@
"use client";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
import { Outlet } from "react-router";
import useSWR from "swr";
// plane imports
@@ -16,12 +15,11 @@ import { useUserPermissions } from "@/hooks/store/user";
// plane web components
import { useRecurringWorkItems } from "@/plane-web/hooks/store/recurring-work-items/use-recurring-work-items";
import { useFlag } from "@/plane-web/hooks/store/use-flag";
import type { Route } from "./+types/layout";
const RecurringWorkItemsProjectSettingsLayout = observer(() => {
function RecurringWorkItemsProjectSettingsLayout({ params }: Route.ComponentProps) {
// router
const { workspaceSlug: routerWorkspaceSlug, projectId: routerProjectId } = useParams();
const workspaceSlug = routerWorkspaceSlug?.toString();
const projectId = routerProjectId?.toString();
const { workspaceSlug, projectId } = params;
// store hooks
const { workspaceUserInfo, allowPermissions } = useUserPermissions();
const { getProjectById } = useProject();
@@ -36,16 +34,12 @@ const RecurringWorkItemsProjectSettingsLayout = observer(() => {
// fetching recurring work items
useSWR(
workspaceSlug && isRecurringWorkItemsEnabled
? ["recurringWorkItems", workspaceSlug, projectId, isRecurringWorkItemsEnabled]
: null,
workspaceSlug && projectId && isRecurringWorkItemsEnabled
? () => fetchRecurringWorkItems(workspaceSlug, projectId)
: null,
isRecurringWorkItemsEnabled ? ["recurringWorkItems", workspaceSlug, projectId, isRecurringWorkItemsEnabled] : null,
isRecurringWorkItemsEnabled ? () => fetchRecurringWorkItems(workspaceSlug, projectId) : null,
{ revalidateIfStale: false, revalidateOnFocus: false }
);
if (!workspaceSlug || !currentProjectDetails?.id) return <></>;
if (!currentProjectDetails?.id) return <></>;
if (workspaceUserInfo && !hasMemberLevelPermission) {
return <NotAuthorizedView section="settings" isProjectView />;
@@ -56,6 +50,6 @@ const RecurringWorkItemsProjectSettingsLayout = observer(() => {
<Outlet />
</SettingsContentWrapper>
);
});
}
export default RecurringWorkItemsProjectSettingsLayout;
export default observer(RecurringWorkItemsProjectSettingsLayout);
@@ -1,8 +1,6 @@
"use client";
import React from "react";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// plane imports
import { EUserPermissionsLevel } from "@plane/constants";
// component
@@ -20,12 +18,11 @@ import { RecurringWorkItemsSettingsRoot } from "@/plane-web/components/recurring
import { RecurringWorkItemsUpgrade } from "@/plane-web/components/recurring-work-items/settings/upgrade";
import { useRecurringWorkItems } from "@/plane-web/hooks/store/recurring-work-items/use-recurring-work-items";
import { useFlag } from "@/plane-web/hooks/store/use-flag";
import type { Route } from "./+types/page";
const RecurringWorkItemsProjectSettingsPage = observer(() => {
function RecurringWorkItemsProjectSettingsPage({ params }: Route.ComponentProps) {
// router
const { workspaceSlug: routerWorkspaceSlug, projectId: routerProjectId } = useParams();
const workspaceSlug = routerWorkspaceSlug?.toString();
const projectId = routerProjectId?.toString();
const { workspaceSlug, projectId } = params;
// plane hooks
const { t } = useTranslation();
// store hooks
@@ -63,6 +60,6 @@ const RecurringWorkItemsProjectSettingsPage = observer(() => {
</WithFeatureFlagHOC>
</>
);
});
}
export default RecurringWorkItemsProjectSettingsPage;
export default observer(RecurringWorkItemsProjectSettingsPage);
@@ -3,7 +3,6 @@
import { observer } from "mobx-react";
// plane imports
import Link from "next/link";
import { useParams } from "next/navigation";
import { Outlet } from "react-router";
import { ChevronLeftIcon } from "lucide-react";
import { EUserPermissionsLevel } from "@plane/constants";
@@ -13,10 +12,11 @@ import { NotAuthorizedView } from "@/components/auth-screens/not-authorized-view
// hooks
import { SettingsContentWrapper } from "@/components/settings/content-wrapper";
import { useUserPermissions } from "@/hooks/store/user";
import type { Route } from "./+types/layout";
const ProjectLevelTemplatesLayout = observer(() => {
function ProjectLevelTemplatesLayout({ params }: Route.ComponentProps) {
// router params
const { workspaceSlug, projectId } = useParams();
const { workspaceSlug, projectId } = params;
// store hooks
const { workspaceUserInfo, allowPermissions } = useUserPermissions();
// derived values
@@ -42,6 +42,6 @@ const ProjectLevelTemplatesLayout = observer(() => {
</div>
</SettingsContentWrapper>
);
});
}
export default ProjectLevelTemplatesLayout;
export default observer(ProjectLevelTemplatesLayout);
@@ -1,7 +1,7 @@
"use client";
import { observer } from "mobx-react";
import { useParams, useSearchParams } from "next/navigation";
import { useSearchParams } from "next/navigation";
// plane imports
import { E_FEATURE_FLAGS, ETemplateLevel } from "@plane/constants";
// plane web imports
@@ -9,9 +9,10 @@ import { useTranslation } from "@plane/i18n";
import { WithFeatureFlagHOC } from "@/plane-web/components/feature-flags";
import { TemplatesUpgrade } from "@/plane-web/components/templates/settings";
import { CreateUpdatePageTemplate } from "@/plane-web/components/templates/settings/page";
const CreateProjectLevelPageTemplatePage = observer(() => {
import type { Route } from "./+types/page";
function CreateProjectLevelPageTemplatePage({ params }: Route.ComponentProps) {
// router
const { workspaceSlug, projectId } = useParams();
const { workspaceSlug, projectId } = params;
const searchParams = useSearchParams();
// derived values
const templateId = searchParams.get("templateId");
@@ -19,7 +20,7 @@ const CreateProjectLevelPageTemplatePage = observer(() => {
return (
<WithFeatureFlagHOC
workspaceSlug={workspaceSlug?.toString()}
workspaceSlug={workspaceSlug}
flag={E_FEATURE_FLAGS.PAGE_TEMPLATES}
fallback={<TemplatesUpgrade flag={E_FEATURE_FLAGS.PAGE_TEMPLATES} />}
>
@@ -29,13 +30,13 @@ const CreateProjectLevelPageTemplatePage = observer(() => {
</div>
</div>
<CreateUpdatePageTemplate
workspaceSlug={workspaceSlug?.toString()}
workspaceSlug={workspaceSlug}
currentLevel={ETemplateLevel.PROJECT}
projectId={projectId?.toString()}
projectId={projectId}
templateId={templateId ?? undefined}
/>
</WithFeatureFlagHOC>
);
});
}
export default CreateProjectLevelPageTemplatePage;
export default observer(CreateProjectLevelPageTemplatePage);
@@ -1,7 +1,7 @@
"use client";
import { observer } from "mobx-react";
import { useParams, useSearchParams } from "next/navigation";
import { useSearchParams } from "next/navigation";
// plane imports
import { E_FEATURE_FLAGS, ETemplateLevel } from "@plane/constants";
// plane web imports
@@ -10,10 +10,11 @@ import { WithFeatureFlagHOC } from "@/plane-web/components/feature-flags";
import { IssueModalProvider } from "@/plane-web/components/issues/issue-modal/provider";
import { TemplatesUpgrade } from "@/plane-web/components/templates/settings";
import { CreateUpdateWorkItemTemplate } from "@/plane-web/components/templates/settings/work-item";
import type { Route } from "./+types/page";
const CreateProjectLevelWorkItemTemplatePage = observer(() => {
function CreateProjectLevelWorkItemTemplatePage({ params }: Route.ComponentProps) {
// router
const { workspaceSlug, projectId } = useParams();
const { workspaceSlug, projectId } = params;
const searchParams = useSearchParams();
// plane hooks
const { t } = useTranslation();
@@ -22,7 +23,7 @@ const CreateProjectLevelWorkItemTemplatePage = observer(() => {
return (
<WithFeatureFlagHOC
workspaceSlug={workspaceSlug?.toString()}
workspaceSlug={workspaceSlug}
flag={E_FEATURE_FLAGS.WORKITEM_TEMPLATES}
fallback={<TemplatesUpgrade flag={E_FEATURE_FLAGS.WORKITEM_TEMPLATES} />}
>
@@ -33,14 +34,14 @@ const CreateProjectLevelWorkItemTemplatePage = observer(() => {
</div>
<IssueModalProvider>
<CreateUpdateWorkItemTemplate
workspaceSlug={workspaceSlug?.toString()}
workspaceSlug={workspaceSlug}
templateId={templateId ?? undefined}
projectId={projectId?.toString()}
projectId={projectId}
currentLevel={ETemplateLevel.PROJECT}
/>
</IssueModalProvider>
</WithFeatureFlagHOC>
);
});
}
export default CreateProjectLevelWorkItemTemplatePage;
export default observer(CreateProjectLevelWorkItemTemplatePage);
@@ -23,8 +23,8 @@ import {
import { useFlag, usePageTemplates, useWorkItemTemplates } from "@/plane-web/hooks/store";
import type { Route } from "./+types/page";
const TemplatesProjectSettingsPage = observer((props: Route.ComponentProps) => {
const { params } = props;
function TemplatesProjectSettingsPage({ params }: Route.ComponentProps) {
// router
const { workspaceSlug, projectId } = params;
// plane hooks
const { t } = useTranslation();
@@ -51,7 +51,7 @@ const TemplatesProjectSettingsPage = observer((props: Route.ComponentProps) => {
EUserPermissionsLevel.PROJECT
);
if (!workspaceSlug || !currentProjectDetails?.id) return <></>;
if (!currentProjectDetails?.id) return <></>;
if (workspaceUserInfo && !hasMemberLevelPermission) {
return <NotAuthorizedView section="settings" isProjectView />;
@@ -83,6 +83,6 @@ const TemplatesProjectSettingsPage = observer((props: Route.ComponentProps) => {
</WithFeatureFlagHOC>
</SettingsContentWrapper>
);
});
}
export default TemplatesProjectSettingsPage;
export default observer(TemplatesProjectSettingsPage);
@@ -15,7 +15,7 @@ import { useUserPermissions } from "@/hooks/store/user";
// plane web imports
import { IssueTypesRoot } from "@/plane-web/components/issue-types";
const WorkItemTypesSettingsPage = observer(() => {
function WorkItemTypesSettingsPage() {
// plane hooks
const { t } = useTranslation();
// store hooks
@@ -39,6 +39,6 @@ const WorkItemTypesSettingsPage = observer(() => {
</div>
</SettingsContentWrapper>
);
});
}
export default WorkItemTypesSettingsPage;
export default observer(WorkItemTypesSettingsPage);
@@ -26,10 +26,11 @@ import { StateWorkflowRoot } from "@/plane-web/components/workflow/page/root";
import { WorkflowUpgrade } from "@/plane-web/components/workflow/page/upgrade";
import { useFlag } from "@/plane-web/hooks/store";
import { useProjectAdvanced } from "@/plane-web/hooks/store/projects/use-projects";
import type { Route } from "./+types/page";
const WorkflowsSettingsPage = observer(() => {
function WorkflowsSettingsPage({ params }: Route.ComponentProps) {
// router
const { workspaceSlug, projectId } = useParams();
const { workspaceSlug, projectId } = params;
// plane hooks
const { t } = useTranslation();
// store
@@ -41,24 +42,20 @@ const WorkflowsSettingsPage = observer(() => {
const pageTitle = currentProjectDetails?.name
? `${currentProjectDetails?.name} - ${t("common.workflows")}`
: undefined;
const isWorkflowFeatureFlagEnabled = useFlag(workspaceSlug?.toString(), "WORKFLOWS");
const isWorkflowEnabled = isProjectFeatureEnabled(projectId?.toString(), "is_workflow_enabled");
const isWorkflowFeatureFlagEnabled = useFlag(workspaceSlug, "WORKFLOWS");
const isWorkflowEnabled = isProjectFeatureEnabled(projectId, "is_workflow_enabled");
const hasAdminPermission = allowPermissions([EUserProjectRoles.ADMIN], EUserPermissionsLevel.PROJECT);
// fetch project states
const { isLoading } = useSWR(
workspaceSlug && projectId ? `PROJECT_STATES_${workspaceSlug}_${projectId}` : null,
workspaceSlug && projectId ? () => fetchProjectStates(workspaceSlug.toString(), projectId.toString()) : null,
`PROJECT_STATES_${workspaceSlug}_${projectId}`,
() => fetchProjectStates(workspaceSlug, projectId),
{ revalidateIfStale: false, revalidateOnFocus: false }
);
// fetch project workflows
useSWR(
workspaceSlug && projectId && isWorkflowFeatureFlagEnabled
? `PROJECT_WORKFLOWS_${workspaceSlug}_${projectId}`
: null,
workspaceSlug && projectId && isWorkflowFeatureFlagEnabled
? () => fetchWorkflowStates(workspaceSlug.toString(), projectId.toString())
: null,
isWorkflowFeatureFlagEnabled ? `PROJECT_WORKFLOWS_${workspaceSlug}_${projectId}` : null,
isWorkflowFeatureFlagEnabled ? () => fetchWorkflowStates(workspaceSlug, projectId) : null,
{ revalidateIfStale: false, revalidateOnFocus: false }
);
@@ -68,7 +65,7 @@ const WorkflowsSettingsPage = observer(() => {
const handleEnableDisableWorkflow = async () => {
const featureState = !isWorkflowEnabled;
const featureTogglePromise = toggleProjectFeatures(workspaceSlug?.toString(), projectId?.toString(), {
const featureTogglePromise = toggleProjectFeatures(workspaceSlug, projectId, {
is_workflow_enabled: featureState,
})
.then(() => {
@@ -130,10 +127,7 @@ const WorkflowsSettingsPage = observer(() => {
disabled={isLoading}
data-ph-element={WORKFLOW_TRACKER_ELEMENTS.WORK_FLOW_ENABLE_DISABLE_BUTTON}
/>
<WorkflowSettingsQuickActions
projectId={projectId?.toString()}
workspaceSlug={workspaceSlug?.toString()}
/>
<WorkflowSettingsQuickActions projectId={projectId} workspaceSlug={workspaceSlug} />
</div>
)}
</>
@@ -141,13 +135,13 @@ const WorkflowsSettingsPage = observer(() => {
/>
<div className="flex-1">
<WithFeatureFlagHOC flag="WORKFLOWS" fallback={<WorkflowUpgrade />} workspaceSlug={workspaceSlug?.toString()}>
<StateWorkflowRoot workspaceSlug={workspaceSlug?.toString()} projectId={projectId?.toString()} />
<WithFeatureFlagHOC flag="WORKFLOWS" fallback={<WorkflowUpgrade />} workspaceSlug={workspaceSlug}>
<StateWorkflowRoot workspaceSlug={workspaceSlug} projectId={projectId} />
</WithFeatureFlagHOC>
</div>
</div>
</SettingsContentWrapper>
);
});
}
export default WorkflowsSettingsPage;
export default observer(WorkflowsSettingsPage);
@@ -1,21 +1,17 @@
"use client";
import { useParams } from "next/navigation";
// plane web components
import { WithFeatureFlagHOC } from "@/plane-web/components/feature-flags";
import { WikiPagesListLayoutRoot } from "@/plane-web/components/pages";
// local components
import type { Route } from "./+types/layout";
import { SharedPagesFallback } from "./empty-shared-pages";
export default function SharedPagesList() {
const { workspaceSlug } = useParams();
export default function SharedPagesList({ params }: Route.ComponentProps) {
const { workspaceSlug } = params;
return (
<WithFeatureFlagHOC
workspaceSlug={workspaceSlug?.toString()}
flag="SHARED_PAGES"
fallback={<SharedPagesFallback />}
>
<WithFeatureFlagHOC workspaceSlug={workspaceSlug} flag="SHARED_PAGES" fallback={<SharedPagesFallback />}>
<WikiPagesListLayoutRoot pageType="shared" />
</WithFeatureFlagHOC>
);
@@ -3,7 +3,6 @@
import { useCallback, useEffect, useMemo } from "react";
import { observer } from "mobx-react";
import Link from "next/link";
import { useParams } from "next/navigation";
import useSWR from "swr";
// plane imports
import { getButtonStyling } from "@plane/propel/button";
@@ -26,6 +25,7 @@ import { EpicPeekOverview } from "@/plane-web/components/epics/peek-overview";
import { EPageStoreType, usePage, usePageStore } from "@/plane-web/hooks/store";
import { WorkspaceService } from "@/plane-web/services";
import { WorkspacePageService, WorkspacePageVersionService } from "@/plane-web/services/page";
import type { Route } from "./+types/page";
// services
const workspaceService = new WorkspaceService();
const workspacePageService = new WorkspacePageService();
@@ -33,29 +33,25 @@ const workspacePageVersionService = new WorkspacePageVersionService();
const storeType = EPageStoreType.WORKSPACE;
const PageDetailsPage = observer(() => {
function PageDetailsPage({ params }: Route.ComponentProps) {
// router
const router = useAppRouter();
const { workspaceSlug, pageId } = useParams();
const { workspaceSlug, pageId } = params;
// flag
// store hooks
const { getWorkspaceBySlug } = useWorkspace();
const { createPage, fetchPageDetails, isNestedPagesEnabled } = usePageStore(storeType);
const page = usePage({
pageId: pageId?.toString() ?? "",
pageId,
storeType,
});
const { uploadEditorAsset } = useEditorAsset();
// derived values
const workspaceId = useMemo(
() => (workspaceSlug ? (getWorkspaceBySlug(workspaceSlug?.toString())?.id ?? "") : ""),
[getWorkspaceBySlug, workspaceSlug]
);
const workspaceId = useMemo(() => getWorkspaceBySlug(workspaceSlug)?.id ?? "", [getWorkspaceBySlug, workspaceSlug]);
const { canCurrentUserAccessPage, id, name, updateDescription } = page ?? {};
// entity search handler
const fetchEntityCallback = useCallback(
async (payload: TSearchEntityRequestPayload) =>
await workspaceService.searchEntity(workspaceSlug?.toString() ?? "", payload),
async (payload: TSearchEntityRequestPayload) => await workspaceService.searchEntity(workspaceSlug ?? "", payload),
[workspaceSlug]
);
// editor config
@@ -74,22 +70,16 @@ const PageDetailsPage = observer(() => {
const pageRootHandlers: TPageRootHandlers = useMemo(
() => ({
create: createPage,
fetchAllVersions: async (pageId) => {
if (!workspaceSlug) return;
return await workspacePageVersionService.fetchAllVersions(workspaceSlug.toString(), pageId);
},
fetchAllVersions: async (pageId) => await workspacePageVersionService.fetchAllVersions(workspaceSlug, pageId),
fetchDescriptionBinary: async () => {
if (!workspaceSlug || !id) return;
return await workspacePageService.fetchDescriptionBinary(workspaceSlug.toString(), id);
if (!id) return;
return await workspacePageService.fetchDescriptionBinary(workspaceSlug, id);
},
fetchEntity: fetchEntityCallback,
fetchVersionDetails: async (pageId, versionId) => {
if (!workspaceSlug) return;
return await workspacePageVersionService.fetchVersionById(workspaceSlug.toString(), pageId, versionId);
},
fetchVersionDetails: async (pageId, versionId) =>
await workspacePageVersionService.fetchVersionById(workspaceSlug, pageId, versionId),
restoreVersion: async (pageId, versionId) => {
if (!workspaceSlug) return;
await workspacePageVersionService.restoreVersion(workspaceSlug.toString(), pageId, versionId);
await workspacePageVersionService.restoreVersion(workspaceSlug, pageId, versionId);
},
getRedirectionLink: (pageId) => {
if (pageId) {
@@ -114,12 +104,12 @@ const PageDetailsPage = observer(() => {
entity_identifier: id ?? "",
entity_type: EFileAssetType.PAGE_DESCRIPTION,
},
workspaceSlug: workspaceSlug?.toString() ?? "",
workspaceSlug,
});
return asset_id;
},
workspaceId,
workspaceSlug: workspaceSlug?.toString() ?? "",
workspaceSlug,
}),
}),
[getEditorFileHandlers, id, uploadEditorAsset, workspaceId, workspaceSlug]
@@ -128,7 +118,7 @@ const PageDetailsPage = observer(() => {
const webhookConnectionParams: TWebhookConnectionQueryParams = useMemo(
() => ({
documentType: "workspace_page",
workspaceSlug: workspaceSlug?.toString() ?? "",
workspaceSlug,
}),
[workspaceSlug]
);
@@ -146,7 +136,7 @@ const PageDetailsPage = observer(() => {
</div>
);
if (!isNestedPagesEnabled(workspaceSlug?.toString()) && page?.parent_id)
if (!isNestedPagesEnabled(workspaceSlug) && page?.parent_id)
return (
<div className="size-full flex flex-col items-center justify-center">
<h3 className="text-lg font-semibold text-center">Please upgrade your plan to view this nested page</h3>
@@ -185,7 +175,7 @@ const PageDetailsPage = observer(() => {
page={page}
storeType={storeType}
webhookConnectionParams={webhookConnectionParams}
workspaceSlug={workspaceSlug.toString()}
workspaceSlug={workspaceSlug}
/>
<IssuePeekOverview />
<EpicPeekOverview />
@@ -193,6 +183,6 @@ const PageDetailsPage = observer(() => {
</div>
</>
);
});
}
export default PageDetailsPage;
export default observer(PageDetailsPage);
@@ -1,6 +1,6 @@
"use client";
import { useParams } from "next/navigation";
// layouts
import { Outlet } from "react-router";
// components
import { EUserPermissions } from "@plane/constants";
@@ -12,21 +12,22 @@ import { WikiAppPowerKProvider } from "@/plane-web/components/command-palette/wi
import { WithFeatureFlagHOC } from "@/plane-web/components/feature-flags/with-feature-flag-hoc";
import { WikiUpgradeScreen } from "@/plane-web/components/wiki/upgrade-screen";
import { WorkspaceAuthWrapper } from "@/plane-web/layouts/workspace-wrapper";
// local imports
// local components
import type { Route } from "./+types/layout";
import { PagesAppSidebar } from "./_sidebar";
export default function WikiLayout() {
export default function WikiLayout({ params }: Route.ComponentProps) {
// router
const { workspaceSlug } = useParams();
const { workspaceSlug } = params;
return (
<AuthenticationWrapper>
<WikiAppPowerKProvider />
<WorkspaceAuthWrapper>
<WithFeatureFlagHOC
workspaceSlug={workspaceSlug?.toString()}
workspaceSlug={workspaceSlug}
flag="WORKSPACE_PAGES"
fallback={<WikiUpgradeScreen workspaceSlug={workspaceSlug?.toString()} />}
fallback={<WikiUpgradeScreen workspaceSlug={workspaceSlug} />}
>
<WorkspaceAccessWrapper
pageKey="pages"
@@ -11,11 +11,12 @@ import { UserGreetingsView } from "@/components/user";
// hooks
import { useUser } from "@/hooks/store/user/user-user";
// plane web components
import type { Route } from "./+types/page";
import { PagesAppDashboardHeader } from "./header";
export default function WorkspacePagesPage() {
export default function WorkspacePagesPage({ params }: Route.ComponentProps) {
// navigation
const { workspaceSlug } = useParams();
const { workspaceSlug } = params;
// store hooks
const { data: currentUser } = useUser();
@@ -26,20 +27,18 @@ export default function WorkspacePagesPage() {
className={cn("gap-6 bg-custom-background-100 max-w-[800px] mx-auto scrollbar-hide px-page-x lg:px-0")}
>
{currentUser && <UserGreetingsView user={currentUser} />}
{workspaceSlug && (
<div className="size-full divide-y-[1px] divide-custom-border-100">
<div className="py-4">
<RecentActivityWidget
workspaceSlug={workspaceSlug.toString()}
presetFilter="workspace_page"
showFilterSelect={false}
/>
</div>
<div className="py-4">
<StickiesWidget />
</div>
<div className="size-full divide-y-[1px] divide-custom-border-100">
<div className="py-4">
<RecentActivityWidget
workspaceSlug={workspaceSlug}
presetFilter="workspace_page"
showFilterSelect={false}
/>
</div>
)}
<div className="py-4">
<StickiesWidget />
</div>
</div>
</ContentWrapper>
</>
);
+3 -4
View File
@@ -1,6 +1,5 @@
"use client";
import React from "react";
import { observer } from "mobx-react";
import type { TInstanceConfig } from "@plane/types";
// hooks
@@ -13,7 +12,7 @@ export const meta: Route.MetaFunction = () => [
{ name: "viewport", content: "width=device-width, initial-scale=1, maximum-scale=1" },
];
const MobileAuth = observer(() => {
function MobileAuth() {
// hooks
const { config } = useInstance();
@@ -26,6 +25,6 @@ const MobileAuth = observer(() => {
</div>
</div>
);
});
}
export default MobileAuth;
export default observer(MobileAuth);
+4 -5
View File
@@ -1,6 +1,5 @@
"use client";
import React from "react";
import { observer } from "mobx-react";
import Link from "next/link";
import { useSearchParams } from "next/navigation";
@@ -21,7 +20,7 @@ import { AppConsent } from "@/plane-web/components/marketplace";
import { ApplicationService } from "@/plane-web/services/marketplace";
const applicationService = new ApplicationService();
const OAuthPage = observer(() => {
function OAuthPage() {
const searchParams = useSearchParams();
const {
workspace_slug,
@@ -45,7 +44,7 @@ const OAuthPage = observer(() => {
});
const application = data?.application;
const applicationPermissions = data?.applicationPermissions?.reduce((acc: any, curr: any) => {
const applicationPermissions = data?.applicationPermissions?.reduce((acc, curr) => {
acc[curr.workspace_id] = curr.state;
return acc;
}, {} as any);
@@ -103,6 +102,6 @@ const OAuthPage = observer(() => {
</AuthenticationWrapper>
</DefaultLayout>
);
});
}
export default OAuthPage;
export default observer(OAuthPage);
@@ -1,29 +1,32 @@
"use client";
import React, { useCallback } from "react";
import { useMemo } from "react";
import { observer } from "mobx-react";
import Link from "next/link";
import { useParams } from "next/navigation";
import { PlaneLockup } from "@plane/propel/icons";
// hooks
import { useUser } from "@/hooks/store/user";
// services
import { AuthenticationWrapper } from "@/lib/wrappers/authentication-wrapper";
// local imports
import type { Route } from "./+types/page";
import { ESupportedFeatures, WorkspaceSelector } from "./workspace-selector";
const NOT_FOUND_CLASSNAME = "flex items-center justify-center h-full text-custom-text-100 text-lg font-medium";
const WorkspacePickerPage = observer(() => {
function isValidFeature(feature: string): feature is ESupportedFeatures {
return Object.values(ESupportedFeatures).includes(feature as ESupportedFeatures);
}
function WorkspacePickerPage({ params }: Route.ComponentProps) {
// router
const { feature: featureFromRoute, identifier } = useParams();
const feature = featureFromRoute as ESupportedFeatures;
const { feature, identifier } = params;
// hooks
const { data: currentUser } = useUser();
// derived values
const isFeatureSupported = Object.values(ESupportedFeatures).includes(feature);
const isFeatureSupported = isValidFeature(feature);
const renderContent = useCallback(() => {
const content = useMemo(() => {
if (!isFeatureSupported) {
return <div className={NOT_FOUND_CLASSNAME}>Invalid feature</div>;
}
@@ -42,10 +45,10 @@ const WorkspacePickerPage = observer(() => {
</Link>
<div className="text-sm text-custom-text-100">{currentUser?.email}</div>
</div>
{renderContent()}
{content}
</div>
</AuthenticationWrapper>
);
});
}
export default WorkspacePickerPage;
export default observer(WorkspacePickerPage);
@@ -2,11 +2,11 @@ import React from "react";
import { observer } from "mobx-react";
import Image from "next/image";
// assets
import { cn } from "@plane/utils";
import ProjectNotAuthorizedImg from "@/app/assets/auth/project-not-authorized.svg?url";
import Unauthorized from "@/app/assets/auth/unauthorized.svg?url";
import WorkspaceNotAuthorizedImg from "@/app/assets/auth/workspace-not-authorized.svg?url";
// layouts
import { cn } from "@plane/utils";
import DefaultLayout from "@/layouts/default-layout";
type Props = {
@@ -11,10 +11,10 @@ import type { TContextMenuItem } from "@plane/ui";
import { ContextMenu, CustomMenu } from "@plane/ui";
import { copyUrlToClipboard, cn } from "@plane/utils";
// helpers
import { useViewMenuItems } from "@/components/common/quick-actions-helper";
import { captureClick } from "@/helpers/event-tracker.helper";
// hooks
import { useUser, useUserPermissions } from "@/hooks/store/user";
import { useViewMenuItems } from "@/components/common/quick-actions-helper";
import { PublishViewModal, useViewPublish } from "@/plane-web/components/views/publish";
// local imports
import { DeleteProjectViewModal } from "./delete-view-modal";
@@ -9,10 +9,10 @@ import type { IWorkspaceView } from "@plane/types";
import { CustomMenu } from "@plane/ui";
import { copyUrlToClipboard, cn } from "@plane/utils";
// helpers
import { useViewMenuItems } from "@/components/common/quick-actions-helper";
import { captureClick } from "@/helpers/event-tracker.helper";
// hooks
import { useUser, useUserPermissions } from "@/hooks/store/user";
import { useViewMenuItems } from "@/components/common/quick-actions-helper";
// local imports
import { DeleteGlobalViewModal } from "./delete-view-modal";
import { CreateUpdateWorkspaceViewModal } from "./modal";

Some files were not shown because too many files have changed in this diff Show More