mirror of
https://github.com/makeplane/plane.git
synced 2025-12-16 20:07:56 +01:00
chore: run fixes (#8257)
* chore: run fixes * fix: type, just use hocuspocusservercontext * fix: codemod --------- Co-authored-by: Palanikannan M <akashmalinimurugu@gmail.com>
This commit is contained in:
12
.npmrc
12
.npmrc
@@ -45,15 +45,3 @@ prefer-frozen-lockfile = true
|
||||
|
||||
# Use isolated linker (best compatibility with Node ecosystem tools)
|
||||
node-linker = isolated
|
||||
|
||||
|
||||
# ------------------------------
|
||||
# Hoisting Strategy
|
||||
# ------------------------------
|
||||
|
||||
# Hoist commonly used tools to the root to prevent duplicates and speed up resolution
|
||||
public-hoist-pattern[] = typescript
|
||||
public-hoist-pattern[] = eslint
|
||||
public-hoist-pattern[] = *@plane/*
|
||||
public-hoist-pattern[] = vite
|
||||
public-hoist-pattern[] = turbo
|
||||
|
||||
@@ -11,7 +11,7 @@ import { cn } from "@plane/utils";
|
||||
// hooks
|
||||
import { useTheme } from "@/hooks/store";
|
||||
// assets
|
||||
// eslint-disable-next-line import/order
|
||||
|
||||
import packageJson from "package.json";
|
||||
|
||||
const helpOptions = [
|
||||
|
||||
@@ -26,7 +26,7 @@ export enum EErrorAlertType {
|
||||
}
|
||||
|
||||
const errorCodeMessages: {
|
||||
[key in EAdminAuthErrorCodes]: { title: string; message: (email?: string | undefined) => React.ReactNode };
|
||||
[key in EAdminAuthErrorCodes]: { title: string; message: (email?: string) => React.ReactNode };
|
||||
} = {
|
||||
// admin
|
||||
[EAdminAuthErrorCodes.ADMIN_ALREADY_EXIST]: {
|
||||
@@ -79,14 +79,11 @@ const errorCodeMessages: {
|
||||
},
|
||||
[EAdminAuthErrorCodes.ADMIN_USER_DEACTIVATED]: {
|
||||
title: `User account deactivated`,
|
||||
message: () => `User account deactivated. Please contact ${!!SUPPORT_EMAIL ? SUPPORT_EMAIL : "administrator"}.`,
|
||||
message: () => `User account deactivated. Please contact ${SUPPORT_EMAIL ? SUPPORT_EMAIL : "administrator"}.`,
|
||||
},
|
||||
};
|
||||
|
||||
export const authErrorHandler = (
|
||||
errorCode: EAdminAuthErrorCodes,
|
||||
email?: string | undefined
|
||||
): TAdminAuthErrorInfo | undefined => {
|
||||
export const authErrorHandler = (errorCode: EAdminAuthErrorCodes, email?: string): TAdminAuthErrorInfo | undefined => {
|
||||
const bannerAlertErrorCodes = [
|
||||
EAdminAuthErrorCodes.ADMIN_ALREADY_EXIST,
|
||||
EAdminAuthErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD_FIRST_NAME,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable import/order */
|
||||
import * as Sentry from "@sentry/react-router";
|
||||
import { startTransition, StrictMode } from "react";
|
||||
import { hydrateRoot } from "react-dom/client";
|
||||
|
||||
@@ -11,6 +11,7 @@ export function UpgradeButton() {
|
||||
href="https://plane.so/pricing?mode=self-hosted"
|
||||
target="_blank"
|
||||
className={cn(getButtonStyling("primary", "sm"))}
|
||||
rel="noreferrer"
|
||||
>
|
||||
Upgrade
|
||||
<SquareArrowOutUpRight className="h-3.5 w-3.5 p-0.5" />
|
||||
|
||||
@@ -24,6 +24,7 @@ export const WorkspaceListItem = observer(function WorkspaceListItem({ workspace
|
||||
href={`${WEB_BASE_URL}/${encodeURIComponent(workspace.slug)}`}
|
||||
target="_blank"
|
||||
className="group flex items-center justify-between p-4 gap-2.5 truncate border border-custom-border-200/70 hover:border-custom-border-200 hover:bg-custom-background-90 rounded-md"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<div className="flex items-start gap-4">
|
||||
<span
|
||||
|
||||
@@ -12,7 +12,7 @@ export class ForceCloseHandler implements Extension {
|
||||
priority = 999;
|
||||
|
||||
async onConfigure({ instance }: onConfigurePayload) {
|
||||
const redisExt = instance.configuration.extensions.find((ext) => ext instanceof Redis) as Redis | undefined;
|
||||
const redisExt = instance.configuration.extensions.find((ext) => ext instanceof Redis);
|
||||
|
||||
if (!redisExt) {
|
||||
logger.warn("[FORCE_CLOSE_HANDLER] Redis extension not found");
|
||||
@@ -149,7 +149,7 @@ export const forceCloseDocumentAcrossServers = async (
|
||||
logger.info(`[FORCE_CLOSE] Closed ${closedCount}/${connectionsBefore} local connections`);
|
||||
|
||||
// STEP 4: BROADCAST TO OTHER SERVERS
|
||||
const redisExt = instance.configuration.extensions.find((ext) => ext instanceof Redis) as Redis | undefined;
|
||||
const redisExt = instance.configuration.extensions.find((ext) => ext instanceof Redis);
|
||||
|
||||
if (redisExt) {
|
||||
const commandData: ForceCloseCommandData = {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// eslint-disable-next-line import/order
|
||||
import { setupSentry } from "./instrument";
|
||||
setupSentry();
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Hocuspocus } from "@hocuspocus/server";
|
||||
import { createRealtimeEvent } from "@plane/editor";
|
||||
import { logger } from "@plane/logger";
|
||||
import type { FetchPayloadWithContext, StorePayloadWithContext } from "@/types";
|
||||
import type { HocusPocusServerContext } from "@/types";
|
||||
import { broadcastMessageToPage } from "./broadcast-message";
|
||||
|
||||
// Helper to broadcast error to frontend
|
||||
@@ -10,7 +10,7 @@ export const broadcastError = async (
|
||||
pageId: string,
|
||||
errorMessage: string,
|
||||
errorType: "fetch" | "store",
|
||||
context: FetchPayloadWithContext["context"] | StorePayloadWithContext["context"],
|
||||
context: HocusPocusServerContext,
|
||||
errorCode?: "content_too_large" | "page_locked" | "page_archived",
|
||||
shouldDisconnect?: boolean
|
||||
) => {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable import/order */
|
||||
import * as Sentry from "@sentry/react-router";
|
||||
import { startTransition, StrictMode } from "react";
|
||||
import { hydrateRoot } from "react-dom/client";
|
||||
|
||||
@@ -11,7 +11,7 @@ interface Props {
|
||||
subGroupId: string | undefined,
|
||||
isSubGroupCumulative: boolean
|
||||
) => number | undefined;
|
||||
getIssueLoader: (groupId?: string | undefined, subGroupId?: string | undefined) => TLoader;
|
||||
getIssueLoader: (groupId?: string, subGroupId?: string) => TLoader;
|
||||
}
|
||||
|
||||
export const IssueLayoutHOC = observer(function IssueLayoutHOC(props: Props) {
|
||||
|
||||
@@ -37,7 +37,7 @@ export interface IKanBan {
|
||||
isSubGroupCumulative: boolean
|
||||
) => number | undefined;
|
||||
getPaginationData: (groupId: string | undefined, subGroupId: string | undefined) => TPaginationData | undefined;
|
||||
getIssueLoader: (groupId?: string | undefined, subGroupId?: string | undefined) => TLoader;
|
||||
getIssueLoader: (groupId?: string, subGroupId?: string) => TLoader;
|
||||
scrollableContainerRef?: MutableRefObject<HTMLDivElement | null>;
|
||||
showEmptyGroup?: boolean;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ interface IKanbanGroup {
|
||||
isSubGroupCumulative: boolean
|
||||
) => number | undefined;
|
||||
getPaginationData: (groupId: string | undefined, subGroupId: string | undefined) => TPaginationData | undefined;
|
||||
getIssueLoader: (groupId?: string | undefined, subGroupId?: string | undefined) => TLoader;
|
||||
getIssueLoader: (groupId?: string, subGroupId?: string) => TLoader;
|
||||
scrollableContainerRef?: MutableRefObject<HTMLDivElement | null>;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ export interface IKanBanSwimLanes {
|
||||
isSubGroupCumulative: boolean
|
||||
) => number | undefined;
|
||||
getPaginationData: (groupId: string | undefined, subGroupId: string | undefined) => TPaginationData | undefined;
|
||||
getIssueLoader: (groupId?: string | undefined, subGroupId?: string | undefined) => TLoader;
|
||||
getIssueLoader: (groupId?: string, subGroupId?: string) => TLoader;
|
||||
showEmptyGroup: boolean;
|
||||
scrollableContainerRef?: MutableRefObject<HTMLDivElement | null>;
|
||||
orderBy: TIssueOrderByOptions | undefined;
|
||||
@@ -163,7 +163,7 @@ interface ISubGroupSwimlane extends ISubGroupSwimlaneHeader {
|
||||
isSubGroupCumulative: boolean
|
||||
) => number | undefined;
|
||||
getPaginationData: (groupId: string | undefined, subGroupId: string | undefined) => TPaginationData | undefined;
|
||||
getIssueLoader: (groupId?: string | undefined, subGroupId?: string | undefined) => TLoader;
|
||||
getIssueLoader: (groupId?: string, subGroupId?: string) => TLoader;
|
||||
scrollableContainerRef?: MutableRefObject<HTMLDivElement | null>;
|
||||
loadMoreIssues: (groupId?: string, subGroupId?: string) => void;
|
||||
}
|
||||
@@ -220,7 +220,7 @@ interface ISubGroup {
|
||||
isSubGroupCumulative: boolean
|
||||
) => number | undefined;
|
||||
getPaginationData: (groupId: string | undefined, subGroupId: string | undefined) => TPaginationData | undefined;
|
||||
getIssueLoader: (groupId?: string | undefined, subGroupId?: string | undefined) => TLoader;
|
||||
getIssueLoader: (groupId?: string, subGroupId?: string) => TLoader;
|
||||
scrollableContainerRef?: MutableRefObject<HTMLDivElement | null>;
|
||||
loadMoreIssues: (groupId?: string, subGroupId?: string) => void;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ export interface IList {
|
||||
isSubGroupCumulative: boolean
|
||||
) => number | undefined;
|
||||
getPaginationData: (groupId: string | undefined, subGroupId: string | undefined) => TPaginationData | undefined;
|
||||
getIssueLoader: (groupId?: string | undefined, subGroupId?: string | undefined) => TLoader;
|
||||
getIssueLoader: (groupId?: string, subGroupId?: string) => TLoader;
|
||||
}
|
||||
|
||||
export const List = observer(function List(props: IList) {
|
||||
|
||||
@@ -32,7 +32,7 @@ interface Props {
|
||||
isSubGroupCumulative: boolean
|
||||
) => number | undefined;
|
||||
getPaginationData: (groupId: string | undefined, subGroupId: string | undefined) => TPaginationData | undefined;
|
||||
getIssueLoader: (groupId?: string | undefined, subGroupId?: string | undefined) => TLoader;
|
||||
getIssueLoader: (groupId?: string, subGroupId?: string) => TLoader;
|
||||
}
|
||||
|
||||
// List loader component
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
"use client";
|
||||
|
||||
import { observer } from "mobx-react";
|
||||
// plane ui
|
||||
import { StateGroupIcon } from "@plane/propel/icons";
|
||||
@@ -24,7 +22,7 @@ type Props = {
|
||||
}
|
||||
);
|
||||
|
||||
export const IssueBlockState: React.FC<Props> = observer((props) => {
|
||||
export const IssueBlockState = observer(function IssueBlockState(props: Props) {
|
||||
const { shouldShowBorder = true } = props;
|
||||
// store hooks
|
||||
const { getStateById } = useStates();
|
||||
|
||||
@@ -44,7 +44,7 @@ export const getGroupByColumns = (
|
||||
case "labels":
|
||||
return getLabelsColumns(label) as any;
|
||||
case "assignees":
|
||||
return getAssigneeColumns(member) as any;
|
||||
return getAssigneeColumns(member);
|
||||
case "created_by":
|
||||
return getCreatedByColumns(member) as any;
|
||||
default:
|
||||
@@ -65,7 +65,7 @@ const getCycleColumns = (cycleStore: ICycleStore): IGroupByColumn[] | undefined
|
||||
cycleGroups.push({
|
||||
id: cycle.id,
|
||||
name: cycle.name,
|
||||
icon: <CycleGroupIcon cycleGroup={cycleStatus as TCycleGroups} className="h-3.5 w-3.5" />,
|
||||
icon: <CycleGroupIcon cycleGroup={cycleStatus} className="h-3.5 w-3.5" />,
|
||||
payload: { cycle_id: cycle.id },
|
||||
});
|
||||
}
|
||||
@@ -196,11 +196,8 @@ export const getDisplayPropertiesCount = (
|
||||
return count;
|
||||
};
|
||||
|
||||
export const getIssueBlockId = (
|
||||
issueId: string | undefined,
|
||||
groupId: string | undefined,
|
||||
subGroupId?: string | undefined
|
||||
) => `issue_${issueId}_${groupId}_${subGroupId}`;
|
||||
export const getIssueBlockId = (issueId: string | undefined, groupId: string | undefined, subGroupId?: string) =>
|
||||
`issue_${issueId}_${groupId}_${subGroupId}`;
|
||||
|
||||
/**
|
||||
* returns empty Array if groupId is None
|
||||
|
||||
@@ -6,7 +6,7 @@ const useClipboardWritePermission = () => {
|
||||
useEffect(() => {
|
||||
const checkClipboardWriteAccess = () => {
|
||||
navigator.permissions
|
||||
//eslint-disable-next-line no-undef
|
||||
|
||||
.query({ name: "clipboard-write" as PermissionName })
|
||||
.then((result) => {
|
||||
if (result.state === "granted") {
|
||||
|
||||
@@ -32,7 +32,6 @@ export const useIntersectionObserver = (
|
||||
observer.observe(elementRef);
|
||||
return () => {
|
||||
if (elementRef) {
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
observer.unobserve(elementRef);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -103,15 +103,15 @@ export abstract class BaseIssuesStore implements IBaseIssuesStore {
|
||||
|
||||
const allIssues = groupedIssueIds[ALL_ISSUES] ?? [];
|
||||
if (allIssues && Array.isArray(allIssues)) {
|
||||
return allIssues as string[];
|
||||
return allIssues;
|
||||
}
|
||||
|
||||
if (groupId && groupedIssueIds?.[groupId] && Array.isArray(groupedIssueIds[groupId])) {
|
||||
return (groupedIssueIds[groupId] ?? []) as string[];
|
||||
return groupedIssueIds[groupId] ?? [];
|
||||
}
|
||||
|
||||
if (groupId && subGroupId) {
|
||||
return ((groupedIssueIds as TSubGroupedIssues)[groupId]?.[subGroupId] ?? []) as string[];
|
||||
return (groupedIssueIds as TSubGroupedIssues)[groupId]?.[subGroupId] ?? [];
|
||||
}
|
||||
|
||||
return undefined;
|
||||
@@ -443,7 +443,7 @@ export abstract class BaseIssuesStore implements IBaseIssuesStore {
|
||||
// if groupedIssueIds is an array, update the `groupedIssueIds` store at the issuePath
|
||||
if (groupedIssueIds && Array.isArray(groupedIssueIds)) {
|
||||
update(this, ["groupedIssueIds", ...issuePath], (issueIds: string[] = []) =>
|
||||
uniq(concat(issueIds, groupedIssueIds as string[]))
|
||||
uniq(concat(issueIds, groupedIssueIds))
|
||||
);
|
||||
// return true to indicate the store has been updated
|
||||
return true;
|
||||
|
||||
@@ -86,7 +86,7 @@ export type TAuthErrorInfo = {
|
||||
};
|
||||
|
||||
const errorCodeMessages: {
|
||||
[key in EAuthenticationErrorCodes]: { title: string; message: (email?: string | undefined) => React.ReactNode };
|
||||
[key in EAuthenticationErrorCodes]: { title: string; message: (email?: string) => React.ReactNode };
|
||||
} = {
|
||||
// global
|
||||
[EAuthenticationErrorCodes.INSTANCE_NOT_CONFIGURED]: {
|
||||
@@ -156,7 +156,7 @@ const errorCodeMessages: {
|
||||
// sign in
|
||||
[EAuthenticationErrorCodes.USER_ACCOUNT_DEACTIVATED]: {
|
||||
title: `User account deactivated`,
|
||||
message: () => `User account deactivated. Please contact ${!!SUPPORT_EMAIL ? SUPPORT_EMAIL : "administrator"}.`,
|
||||
message: () => `User account deactivated. Please contact ${SUPPORT_EMAIL ? SUPPORT_EMAIL : "administrator"}.`,
|
||||
},
|
||||
|
||||
[EAuthenticationErrorCodes.USER_DOES_NOT_EXIST]: {
|
||||
@@ -332,10 +332,7 @@ const errorCodeMessages: {
|
||||
},
|
||||
};
|
||||
|
||||
export const authErrorHandler = (
|
||||
errorCode: EAuthenticationErrorCodes,
|
||||
email?: string | undefined
|
||||
): TAuthErrorInfo | undefined => {
|
||||
export const authErrorHandler = (errorCode: EAuthenticationErrorCodes, email?: string): TAuthErrorInfo | undefined => {
|
||||
const bannerAlertErrorCodes = [
|
||||
EAuthenticationErrorCodes.INSTANCE_NOT_CONFIGURED,
|
||||
EAuthenticationErrorCodes.INVALID_EMAIL,
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { useParams } from "next/navigation";
|
||||
@@ -16,7 +14,7 @@ import { useAppRouter } from "@/hooks/use-app-router";
|
||||
// plane web imports
|
||||
import { CommonProjectBreadcrumbs } from "@/plane-web/components/breadcrumbs/common";
|
||||
|
||||
export const WorkItemDetailsHeader = observer(() => {
|
||||
export const WorkItemDetailsHeader = observer(function WorkItemDetailsHeader() {
|
||||
// router
|
||||
const router = useAppRouter();
|
||||
const { workspaceSlug, workItem } = useParams();
|
||||
|
||||
@@ -50,11 +50,7 @@ export const CycleIssuesHeader = observer(function CycleIssuesHeader() {
|
||||
const [analyticsModal, setAnalyticsModal] = useState(false);
|
||||
// router
|
||||
const router = useAppRouter();
|
||||
const { workspaceSlug, projectId, cycleId } = useParams() as {
|
||||
workspaceSlug: string;
|
||||
projectId: string;
|
||||
cycleId: string;
|
||||
};
|
||||
const { workspaceSlug, projectId, cycleId } = useParams();
|
||||
// i18n
|
||||
const { t } = useTranslation();
|
||||
// store hooks
|
||||
|
||||
@@ -22,10 +22,7 @@ export const ProjectIssuesMobileHeader = observer(function ProjectIssuesMobileHe
|
||||
// i18n
|
||||
const { t } = useTranslation();
|
||||
const [analyticsModal, setAnalyticsModal] = useState(false);
|
||||
const { workspaceSlug, projectId } = useParams() as {
|
||||
workspaceSlug: string;
|
||||
projectId: string;
|
||||
};
|
||||
const { workspaceSlug, projectId } = useParams();
|
||||
const { currentProjectDetails } = useProject();
|
||||
|
||||
// store hooks
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
"use client";
|
||||
|
||||
import { observer } from "mobx-react";
|
||||
import { Outlet } from "react-router";
|
||||
// plane imports
|
||||
|
||||
@@ -25,11 +25,7 @@ const SUPPORTED_LAYOUTS = [
|
||||
|
||||
export const ModuleIssuesMobileHeader = observer(function ModuleIssuesMobileHeader() {
|
||||
// router
|
||||
const { workspaceSlug, projectId, moduleId } = useParams() as {
|
||||
workspaceSlug: string;
|
||||
projectId: string;
|
||||
moduleId: string;
|
||||
};
|
||||
const { workspaceSlug, projectId, moduleId } = useParams();
|
||||
// states
|
||||
const [analyticsModal, setAnalyticsModal] = useState(false);
|
||||
// plane hooks
|
||||
|
||||
@@ -21,7 +21,7 @@ import { CommonProjectBreadcrumbs } from "@/plane-web/components/breadcrumbs/com
|
||||
export const ModulesListHeader = observer(function ModulesListHeader() {
|
||||
// router
|
||||
const router = useAppRouter();
|
||||
const { workspaceSlug, projectId } = useParams() as { workspaceSlug: string; projectId: string };
|
||||
const { workspaceSlug, projectId } = useParams();
|
||||
// store hooks
|
||||
const { toggleCreateModuleModal } = useCommandPalette();
|
||||
const { allowPermissions } = useUserPermissions();
|
||||
|
||||
@@ -15,7 +15,7 @@ import { useProject } from "@/hooks/store/use-project";
|
||||
import { CommonProjectBreadcrumbs } from "@/plane-web/components/breadcrumbs/common";
|
||||
|
||||
export const ProjectViewsHeader = observer(function ProjectViewsHeader() {
|
||||
const { workspaceSlug, projectId } = useParams() as { workspaceSlug: string; projectId: string };
|
||||
const { workspaceSlug, projectId } = useParams();
|
||||
// store hooks
|
||||
const { toggleCreateViewModal } = useCommandPalette();
|
||||
const { loader } = useProject();
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable import/order */
|
||||
import * as Sentry from "@sentry/react-router";
|
||||
import { startTransition, StrictMode } from "react";
|
||||
import { hydrateRoot } from "react-dom/client";
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
// hoc/withDockItems.tsx
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { useParams } from "next/navigation";
|
||||
@@ -13,7 +11,7 @@ type WithDockItemsProps = {
|
||||
};
|
||||
|
||||
export function withDockItems<P extends WithDockItemsProps>(WrappedComponent: React.ComponentType<P>) {
|
||||
const ComponentWithDockItems = observer((props: Omit<P, keyof WithDockItemsProps>) => {
|
||||
const ComponentWithDockItems = observer(function ComponentWithDockItems(props: Omit<P, keyof WithDockItemsProps>) {
|
||||
const { workspaceSlug } = useParams();
|
||||
const { isProjectsPath, isNotificationsPath } = useWorkspacePaths();
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ import { CommonProjectBreadcrumbs } from "@/plane-web/components/breadcrumbs/com
|
||||
export const IssuesHeader = observer(function IssuesHeader() {
|
||||
// router
|
||||
const router = useAppRouter();
|
||||
const { workspaceSlug, projectId } = useParams() as { workspaceSlug: string; projectId: string };
|
||||
const { workspaceSlug, projectId } = useParams();
|
||||
// store hooks
|
||||
const {
|
||||
issues: { getGroupIssueCount },
|
||||
|
||||
@@ -69,7 +69,7 @@ export const PaidPlanUpgradeModal = observer(function PaidPlanUpgradeModal(props
|
||||
verticalFeatureList
|
||||
extraFeatures={
|
||||
<p className={COMMON_EXTRA_FEATURES_CLASSNAME}>
|
||||
<a href={SUBSCRIPTION_WEBPAGE_URLS[EProductSubscriptionEnum.PRO]} target="_blank">
|
||||
<a href={SUBSCRIPTION_WEBPAGE_URLS[EProductSubscriptionEnum.PRO]} target="_blank" rel="noreferrer">
|
||||
See full features list
|
||||
</a>
|
||||
</p>
|
||||
@@ -87,7 +87,11 @@ export const PaidPlanUpgradeModal = observer(function PaidPlanUpgradeModal(props
|
||||
verticalFeatureList
|
||||
extraFeatures={
|
||||
<p className={COMMON_EXTRA_FEATURES_CLASSNAME}>
|
||||
<a href={SUBSCRIPTION_WEBPAGE_URLS[EProductSubscriptionEnum.BUSINESS]} target="_blank">
|
||||
<a
|
||||
href={SUBSCRIPTION_WEBPAGE_URLS[EProductSubscriptionEnum.BUSINESS]}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
See full features list
|
||||
</a>
|
||||
</p>
|
||||
@@ -105,7 +109,11 @@ export const PaidPlanUpgradeModal = observer(function PaidPlanUpgradeModal(props
|
||||
verticalFeatureList
|
||||
extraFeatures={
|
||||
<p className={COMMON_EXTRA_FEATURES_CLASSNAME}>
|
||||
<a href={SUBSCRIPTION_WEBPAGE_URLS[EProductSubscriptionEnum.ENTERPRISE]} target="_blank">
|
||||
<a
|
||||
href={SUBSCRIPTION_WEBPAGE_URLS[EProductSubscriptionEnum.ENTERPRISE]}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
See full features list
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -13,7 +13,7 @@ import { InboxIcon } from "@plane/propel/icons";
|
||||
import useSWR from "swr";
|
||||
import { useWorkspaceNotifications } from "@/hooks/store/notifications";
|
||||
|
||||
export const TopNavigationRoot = observer(() => {
|
||||
export const TopNavigationRoot = observer(function TopNavigationRoot() {
|
||||
// router
|
||||
const { workspaceSlug, projectId, workItem } = useParams();
|
||||
const pathname = usePathname();
|
||||
|
||||
@@ -65,7 +65,7 @@ export const useProjectColumns = (props: TUseProjectColumnsProps) => {
|
||||
tdRender: (rowData: RowData) => (
|
||||
<NameColumn
|
||||
rowData={rowData}
|
||||
workspaceSlug={workspaceSlug as string}
|
||||
workspaceSlug={workspaceSlug}
|
||||
isAdmin={isAdmin}
|
||||
currentUser={currentUser}
|
||||
setRemoveMemberModal={setRemoveMemberModal}
|
||||
@@ -110,8 +110,8 @@ export const useProjectColumns = (props: TUseProjectColumnsProps) => {
|
||||
<AccountTypeColumn
|
||||
rowData={rowData}
|
||||
currentProjectRole={currentProjectRole}
|
||||
projectId={projectId as string}
|
||||
workspaceSlug={workspaceSlug as string}
|
||||
projectId={projectId}
|
||||
workspaceSlug={workspaceSlug}
|
||||
/>
|
||||
),
|
||||
},
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { AppRailVisibilityProvider as CoreProvider } from "@/lib/app-rail";
|
||||
@@ -12,6 +10,8 @@ interface AppRailVisibilityProviderProps {
|
||||
* CE AppRailVisibilityProvider
|
||||
* Wraps core provider with isEnabled hardcoded to false
|
||||
*/
|
||||
export const AppRailVisibilityProvider = observer(({ children }: AppRailVisibilityProviderProps) => (
|
||||
<CoreProvider isEnabled={false}>{children}</CoreProvider>
|
||||
));
|
||||
export const AppRailVisibilityProvider = observer(function AppRailVisibilityProvider({
|
||||
children,
|
||||
}: AppRailVisibilityProviderProps) {
|
||||
return <CoreProvider isEnabled={false}>{children}</CoreProvider>;
|
||||
});
|
||||
|
||||
@@ -17,10 +17,10 @@ export const getTimelineStore = (
|
||||
return timelineStore.modulesTimeLineStore as IBaseTimelineStore;
|
||||
}
|
||||
if (timelineType === GANTT_TIMELINE_TYPE.PROJECT) {
|
||||
return timelineStore.projectTimeLineStore as IBaseTimelineStore;
|
||||
return timelineStore.projectTimeLineStore;
|
||||
}
|
||||
if (timelineType === GANTT_TIMELINE_TYPE.GROUPED) {
|
||||
return timelineStore.groupedTimeLineStore as IBaseTimelineStore;
|
||||
return timelineStore.groupedTimeLineStore;
|
||||
}
|
||||
throw new Error(`Unknown timeline type: ${timelineType}`);
|
||||
};
|
||||
|
||||
@@ -49,7 +49,7 @@ export function GeneratedTokenDetails(props: Props) {
|
||||
<div className="mt-6 flex items-center justify-between">
|
||||
<p className="text-xs text-custom-text-400">
|
||||
{tokenDetails.expired_at
|
||||
? `Expires ${renderFormattedDate(tokenDetails.expired_at!)} at ${renderFormattedTime(tokenDetails.expired_at!)}`
|
||||
? `Expires ${renderFormattedDate(tokenDetails.expired_at)} at ${renderFormattedTime(tokenDetails.expired_at)}`
|
||||
: "Never expires"}
|
||||
</p>
|
||||
<Button variant="neutral-primary" size="sm" onClick={handleClose}>
|
||||
|
||||
@@ -51,7 +51,7 @@ export function ApiTokenListItem(props: Props) {
|
||||
<p className="mb-1 text-xs leading-6 text-custom-text-400">
|
||||
{token.is_active
|
||||
? token.expired_at
|
||||
? `Expires ${renderFormattedDate(token.expired_at!)} at ${renderFormattedTime(token.expired_at!)}`
|
||||
? `Expires ${renderFormattedDate(token.expired_at)} at ${renderFormattedTime(token.expired_at)}`
|
||||
: "Never expires"
|
||||
: `Expired ${calculateTimeAgo(token.expired_at)}`}
|
||||
</p>
|
||||
|
||||
@@ -42,7 +42,7 @@ export const CommentCreate = observer(function CommentCreate(props: TCommentCrea
|
||||
// store hooks
|
||||
const workspaceStore = useWorkspace();
|
||||
// derived values
|
||||
const workspaceId = workspaceStore.getWorkspaceBySlug(workspaceSlug as string)?.id as string;
|
||||
const workspaceId = workspaceStore.getWorkspaceBySlug(workspaceSlug)?.id as string;
|
||||
// form info
|
||||
const {
|
||||
handleSubmit,
|
||||
|
||||
@@ -65,7 +65,7 @@ export const CommentsWrapper = observer(function CommentsWrapper(props: TComment
|
||||
<CommentCard
|
||||
key={comment.id}
|
||||
workspaceSlug={workspaceSlug}
|
||||
comment={comment as TIssueComment}
|
||||
comment={comment}
|
||||
activityOperations={activityOperations}
|
||||
disabled={!isEditingAllowed}
|
||||
ends={index === 0 ? "top" : index === comments.length - 1 ? "bottom" : undefined}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import type { FC } from "react";
|
||||
import { useMemo } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { Globe2, Link, Lock, Pencil, Trash2 } from "lucide-react";
|
||||
@@ -31,8 +30,9 @@ export const CommentQuickActions = observer(function CommentQuickActions(props:
|
||||
// translation
|
||||
const { t } = useTranslation();
|
||||
|
||||
const MENU_ITEMS = useMemo<TContextMenuItem[]>(
|
||||
() => [
|
||||
const MENU_ITEMS = useMemo(
|
||||
function MENU_ITEMS(): TContextMenuItem[] {
|
||||
return [
|
||||
{
|
||||
key: "edit",
|
||||
action: setEditMode,
|
||||
@@ -70,7 +70,8 @@ export const CommentQuickActions = observer(function CommentQuickActions(props:
|
||||
icon: Trash2,
|
||||
shouldRender: canDelete,
|
||||
},
|
||||
],
|
||||
];
|
||||
},
|
||||
[t, setEditMode, canEdit, showCopyLinkOption, activityOperations, comment, showAccessSpecifier, canDelete]
|
||||
);
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import type { ReactNode, FC } from "react";
|
||||
import React, { useMemo } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import Link from "next/link";
|
||||
@@ -19,7 +18,7 @@ const IconWrapper = React.memo(function IconWrapper({ icon }: { icon: React.Reac
|
||||
|
||||
IconWrapper.displayName = "IconWrapper";
|
||||
|
||||
const LabelWrapper = React.memo(function LabelWrapper({ label }: { label: ReactNode }) {
|
||||
const LabelWrapper = React.memo(function LabelWrapper({ label }: { label: React.ReactNode }) {
|
||||
return <div className="relative line-clamp-1 block max-w-[150px] overflow-hidden truncate">{label}</div>;
|
||||
});
|
||||
|
||||
@@ -30,7 +29,7 @@ const BreadcrumbContent = React.memo(function BreadcrumbContent({
|
||||
label,
|
||||
}: {
|
||||
icon?: React.ReactNode;
|
||||
label?: ReactNode;
|
||||
label?: React.ReactNode;
|
||||
}) {
|
||||
if (!icon && !label) return null;
|
||||
|
||||
@@ -58,10 +57,10 @@ export const BreadcrumbLink = observer(function BreadcrumbLink(props: Props) {
|
||||
const { isMobile } = usePlatformOS();
|
||||
|
||||
const itemWrapperProps = useMemo(
|
||||
() => ({
|
||||
(): Omit<React.ComponentProps<typeof ItemWrapper>, "children"> => ({
|
||||
label: label?.toString(),
|
||||
disableTooltip: isMobile || disableTooltip,
|
||||
type: (href && href !== "" ? "link" : "text") as "link" | "text",
|
||||
type: href && href !== "" ? "link" : "text",
|
||||
isLast,
|
||||
}),
|
||||
[href, label, isMobile, disableTooltip, isLast]
|
||||
|
||||
@@ -105,7 +105,7 @@ export const BulkDeleteIssuesModal = observer(function BulkDeleteIssuesModal(pro
|
||||
|
||||
if (!Array.isArray(data.delete_issue_ids)) data.delete_issue_ids = [data.delete_issue_ids];
|
||||
|
||||
await removeBulkIssues(workspaceSlug as string, projectId as string, data.delete_issue_ids)
|
||||
await removeBulkIssues(workspaceSlug, projectId, data.delete_issue_ids)
|
||||
.then(() => {
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
@@ -29,7 +27,7 @@ const defaultValues: TUniqueCodeValuesForm = { email: "", code: "" };
|
||||
// service initialization
|
||||
const authService = new AuthService();
|
||||
|
||||
export const ChangeEmailModal: React.FC<Props> = observer((props) => {
|
||||
export const ChangeEmailModal = observer(function ChangeEmailModal(props: Props) {
|
||||
const { isOpen, onClose } = props;
|
||||
// states
|
||||
const [currentStep, setCurrentStep] = useState<TModalStep>("EMAIL");
|
||||
|
||||
@@ -106,7 +106,7 @@ export const CycleSidebarHeader = observer(function CycleSidebarHeader(props: Pr
|
||||
|
||||
const dateChecker = async (payload: any) => {
|
||||
try {
|
||||
const res = await cycleService.cycleDateCheck(workspaceSlug as string, projectId as string, payload);
|
||||
const res = await cycleService.cycleDateCheck(workspaceSlug, projectId, payload);
|
||||
return res.status;
|
||||
} catch (err) {
|
||||
return false;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
"use client";
|
||||
|
||||
import type { ReactNode } from "react";
|
||||
import { useRef, useState } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
@@ -41,7 +39,9 @@ export type TWorkItemStateDropdownBaseProps = TDropdownProps & {
|
||||
value: string | undefined | null;
|
||||
};
|
||||
|
||||
export const WorkItemStateDropdownBase: React.FC<TWorkItemStateDropdownBaseProps> = observer((props) => {
|
||||
export const WorkItemStateDropdownBase = observer(function WorkItemStateDropdownBase(
|
||||
props: TWorkItemStateDropdownBaseProps
|
||||
) {
|
||||
const {
|
||||
button,
|
||||
buttonClassName,
|
||||
@@ -79,7 +79,7 @@ export const WorkItemStateDropdownBase: React.FC<TWorkItemStateDropdownBaseProps
|
||||
const { t } = useTranslation();
|
||||
const statesList = stateIds.map((stateId) => getStateById(stateId)).filter((state) => !!state);
|
||||
const defaultState = statesList?.find((state) => state?.default) || statesList[0];
|
||||
const stateValue = !!value ? value : showDefaultState ? defaultState?.id : undefined;
|
||||
const stateValue = value ? value : showDefaultState ? defaultState?.id : undefined;
|
||||
// popper-js init
|
||||
const { styles, attributes } = usePopper(referenceElement, popperElement, {
|
||||
placement: placement ?? "bottom-start",
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { useParams } from "next/navigation";
|
||||
@@ -16,7 +14,7 @@ type TWorkItemStateDropdownProps = Omit<
|
||||
stateIds?: string[];
|
||||
};
|
||||
|
||||
export const IntakeStateDropdown: React.FC<TWorkItemStateDropdownProps> = observer((props) => {
|
||||
export const IntakeStateDropdown = observer(function IntakeStateDropdown(props: TWorkItemStateDropdownProps) {
|
||||
const { projectId, stateIds: propsStateIds } = props;
|
||||
// router params
|
||||
const { workspaceSlug } = useParams();
|
||||
|
||||
@@ -79,7 +79,7 @@ export const WorkItemStateDropdownBase = observer(function WorkItemStateDropdown
|
||||
const { t } = useTranslation();
|
||||
const statesList = stateIds.map((stateId) => getStateById(stateId)).filter((state) => !!state);
|
||||
const defaultState = statesList?.find((state) => state?.default);
|
||||
const stateValue = !!value ? value : showDefaultState ? defaultState?.id : undefined;
|
||||
const stateValue = value ? value : showDefaultState ? defaultState?.id : undefined;
|
||||
// popper-js init
|
||||
const { styles, attributes } = usePopper(referenceElement, popperElement, {
|
||||
placement: placement ?? "bottom-start",
|
||||
|
||||
@@ -82,7 +82,7 @@ export const EstimatePointCreate = observer(function EstimatePointCreate(props:
|
||||
|
||||
const currentEstimatePointValues = estimatePoints
|
||||
.map((point) => point?.value || undefined)
|
||||
.filter((value) => value != undefined) as string[];
|
||||
.filter((value) => value != undefined);
|
||||
const isRepeated =
|
||||
(estimateType && isEstimatePointValuesRepeated(currentEstimatePointValues, estimateType, estimateInputValue)) ||
|
||||
false;
|
||||
|
||||
@@ -87,7 +87,7 @@ export const EstimatePointUpdate = observer(function EstimatePointUpdate(props:
|
||||
|
||||
const currentEstimatePointValues = estimatePoints
|
||||
.map((point) => (point?.key != estimatePoint?.key ? point?.value : undefined))
|
||||
.filter((value) => value != undefined) as string[];
|
||||
.filter((value) => value != undefined);
|
||||
const isRepeated =
|
||||
(estimateType && isEstimatePointValuesRepeated(currentEstimatePointValues, estimateType, estimateInputValue)) ||
|
||||
false;
|
||||
|
||||
@@ -104,6 +104,7 @@ export const EstimateRoot = observer(function EstimateRoot(props: TEstimateRoot)
|
||||
href={"https://docs.plane.so/core-concepts/projects/run-project#estimate"}
|
||||
target="_blank"
|
||||
className="text-custom-primary-100/80 hover:text-custom-primary-100"
|
||||
rel="noreferrer"
|
||||
>
|
||||
here.
|
||||
</a>
|
||||
|
||||
@@ -102,7 +102,7 @@ export const ExportForm = observer(function ExportForm(props: Props) {
|
||||
rich_filters: formData.filters,
|
||||
};
|
||||
await projectExportService
|
||||
.csvExport(workspaceSlug as string, payload)
|
||||
.csvExport(workspaceSlug, payload)
|
||||
.then(() => {
|
||||
mutateServices();
|
||||
setExportLoading(false);
|
||||
|
||||
@@ -74,7 +74,7 @@ export const Exporter = observer(function Exporter(props: Props) {
|
||||
multiple: multiple,
|
||||
};
|
||||
await projectExportService
|
||||
.csvExport(workspaceSlug as string, payload)
|
||||
.csvExport(workspaceSlug, payload)
|
||||
.then(() => {
|
||||
mutateServices();
|
||||
router.push(`/${workspaceSlug}/settings/exports`);
|
||||
|
||||
@@ -20,16 +20,11 @@ const IntegrationGuide = observer(function IntegrationGuide() {
|
||||
<div className="h-full w-full">
|
||||
<>
|
||||
<ExportForm
|
||||
workspaceSlug={workspaceSlug as string}
|
||||
workspaceSlug={workspaceSlug}
|
||||
provider={provider}
|
||||
mutateServices={() => mutate(EXPORT_SERVICES_LIST(workspaceSlug as string, `${cursor}`, `${per_page}`))}
|
||||
/>
|
||||
<PrevExports
|
||||
workspaceSlug={workspaceSlug as string}
|
||||
cursor={cursor}
|
||||
per_page={per_page}
|
||||
setCursor={setCursor}
|
||||
mutateServices={() => mutate(EXPORT_SERVICES_LIST(workspaceSlug, `${cursor}`, `${per_page}`))}
|
||||
/>
|
||||
<PrevExports workspaceSlug={workspaceSlug} cursor={cursor} per_page={per_page} setCursor={setCursor} />
|
||||
</>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -35,15 +35,13 @@ export const PrevExports = observer(function PrevExports(props: Props) {
|
||||
const columns = useExportColumns();
|
||||
|
||||
const { data: exporterServices } = useSWR(
|
||||
workspaceSlug && cursor ? EXPORT_SERVICES_LIST(workspaceSlug as string, cursor, `${per_page}`) : null,
|
||||
workspaceSlug && cursor
|
||||
? () => integrationService.getExportsServicesList(workspaceSlug as string, cursor, per_page)
|
||||
: null
|
||||
workspaceSlug && cursor ? EXPORT_SERVICES_LIST(workspaceSlug, cursor, `${per_page}`) : null,
|
||||
workspaceSlug && cursor ? () => integrationService.getExportsServicesList(workspaceSlug, cursor, per_page) : null
|
||||
);
|
||||
|
||||
const handleRefresh = () => {
|
||||
setRefreshing(true);
|
||||
mutate(EXPORT_SERVICES_LIST(workspaceSlug as string, `${cursor}`, `${per_page}`)).then(() => setRefreshing(false));
|
||||
mutate(EXPORT_SERVICES_LIST(workspaceSlug, `${cursor}`, `${per_page}`)).then(() => setRefreshing(false));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -14,7 +14,7 @@ type Props = {
|
||||
|
||||
export function SingleExport({ service, refreshing }: Props) {
|
||||
const provider = service.provider;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
|
||||
const [isLoading] = useState(false);
|
||||
|
||||
const checkExpiry = (inputDateString: string) => {
|
||||
|
||||
@@ -59,7 +59,7 @@ export const timePreview = (date: Date) => {
|
||||
export const datePreview = (date: Date, includeTime: boolean = false) => {
|
||||
const day = date.getDate();
|
||||
let month: number | WeekMonthDataType = date.getMonth();
|
||||
month = months[month as number] as WeekMonthDataType;
|
||||
month = months[month];
|
||||
const year = date.getFullYear();
|
||||
|
||||
return `${charCapitalize(month?.shortTitle)} ${day}, ${year}${includeTime ? `, ${timePreview(date)}` : ``}`;
|
||||
|
||||
@@ -5,7 +5,7 @@ export const handleOrderChange = (
|
||||
droppedBlockId: string | undefined,
|
||||
dropAtEndOfList: boolean,
|
||||
blockIds: string[] | null,
|
||||
getBlockById: (id: string, currentViewData?: ChartDataType | undefined) => IGanttBlock,
|
||||
getBlockById: (id: string, currentViewData?: ChartDataType) => IGanttBlock,
|
||||
blockUpdateHandler: (block: any, payload: IBlockUpdateData) => void
|
||||
) => {
|
||||
if (!blockIds || !draggingBlockId || !droppedBlockId) return;
|
||||
|
||||
@@ -15,6 +15,7 @@ export function ProductUpdatesFooter() {
|
||||
href="https://go.plane.so/p-docs"
|
||||
target="_blank"
|
||||
className="text-sm text-custom-text-200 hover:text-custom-text-100 hover:underline underline-offset-1 outline-none"
|
||||
rel="noreferrer"
|
||||
>
|
||||
{t("docs")}
|
||||
</a>
|
||||
@@ -26,6 +27,7 @@ export function ProductUpdatesFooter() {
|
||||
href="https://go.plane.so/p-changelog"
|
||||
target="_blank"
|
||||
className="text-sm text-custom-text-200 hover:text-custom-text-100 hover:underline underline-offset-1 outline-none"
|
||||
rel="noreferrer"
|
||||
>
|
||||
{t("full_changelog")}
|
||||
</a>
|
||||
@@ -36,6 +38,7 @@ export function ProductUpdatesFooter() {
|
||||
href="mailto:support@plane.so"
|
||||
target="_blank"
|
||||
className="text-sm text-custom-text-200 hover:text-custom-text-100 hover:underline underline-offset-1 outline-none"
|
||||
rel="noreferrer"
|
||||
>
|
||||
{t("support")}
|
||||
</a>
|
||||
@@ -46,6 +49,7 @@ export function ProductUpdatesFooter() {
|
||||
href="https://go.plane.so/p-discord"
|
||||
target="_blank"
|
||||
className="text-sm text-custom-text-200 hover:text-custom-text-100 hover:underline underline-offset-1 outline-none"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Discord
|
||||
</a>
|
||||
@@ -57,6 +61,7 @@ export function ProductUpdatesFooter() {
|
||||
getButtonStyling("accent-primary", "sm"),
|
||||
"flex gap-1.5 items-center text-center font-medium hover:underline underline-offset-2 outline-none"
|
||||
)}
|
||||
rel="noreferrer"
|
||||
>
|
||||
<PlaneLogo className="h-4 w-auto text-custom-text-100" />
|
||||
{t("powered_by_plane_pages")}
|
||||
|
||||
@@ -46,7 +46,7 @@ export const WidgetItem = observer(function WidgetItem(props: Props) {
|
||||
const { widgetsMap } = useHome();
|
||||
const { t } = useTranslation();
|
||||
// derived values
|
||||
const widget = widgetsMap[widgetId] as TWidgetEntityData;
|
||||
const widget = widgetsMap[widgetId];
|
||||
const widgetTitle = HOME_WIDGETS_LIST[widget.key]?.title;
|
||||
|
||||
// drag and drop
|
||||
|
||||
@@ -90,11 +90,10 @@ export const InboxIssueMainContent = observer(function InboxIssueMainContent(pro
|
||||
|
||||
const issueOperations: TIssueOperations = useMemo(
|
||||
() => ({
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars, arrow-body-style
|
||||
fetch: async (_workspaceSlug: string, _projectId: string, _issueId: string) => {
|
||||
return;
|
||||
},
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars, arrow-body-style
|
||||
|
||||
remove: async (_workspaceSlug: string, _projectId: string, _issueId: string) => {
|
||||
try {
|
||||
await removeIssue(workspaceSlug, projectId, _issueId);
|
||||
|
||||
@@ -43,8 +43,8 @@ export const DeleteInboxIssueModal = observer(function DeleteInboxIssueModal({
|
||||
.then(() => {
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: `${t("success")!}`,
|
||||
message: `${t("inbox_issue.modals.delete.success")!}`,
|
||||
title: `${t("success")}`,
|
||||
message: `${t("inbox_issue.modals.delete.success")}`,
|
||||
});
|
||||
})
|
||||
.catch((errors) => {
|
||||
|
||||
@@ -41,13 +41,13 @@ export function DeleteImportModal({ isOpen, handleClose, data }: Props) {
|
||||
setDeleteLoading(true);
|
||||
|
||||
mutate<IImporterService[]>(
|
||||
IMPORTER_SERVICES_LIST(workspaceSlug as string),
|
||||
IMPORTER_SERVICES_LIST(workspaceSlug),
|
||||
(prevData) => (prevData ?? []).filter((i) => i.id !== data.id),
|
||||
false
|
||||
);
|
||||
|
||||
integrationService
|
||||
.deleteImporterService(workspaceSlug as string, data.service, data.id)
|
||||
.deleteImporterService(workspaceSlug, data.service, data.id)
|
||||
.catch(() =>
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
|
||||
@@ -30,10 +30,10 @@ export function GithubRepoDetails({ selectedRepo, handleStepChange, setUsers, se
|
||||
const { workspaceSlug } = useParams();
|
||||
|
||||
const { data: repoInfo } = useSWR(
|
||||
workspaceSlug && selectedRepo ? GITHUB_REPOSITORY_INFO(workspaceSlug as string, selectedRepo.name) : null,
|
||||
workspaceSlug && selectedRepo ? GITHUB_REPOSITORY_INFO(workspaceSlug, selectedRepo.name) : null,
|
||||
workspaceSlug && selectedRepo
|
||||
? () =>
|
||||
githubIntegrationService.getGithubRepoInfo(workspaceSlug as string, {
|
||||
githubIntegrationService.getGithubRepoInfo(workspaceSlug, {
|
||||
owner: selectedRepo.owner.login,
|
||||
repo: selectedRepo.name,
|
||||
})
|
||||
|
||||
@@ -96,8 +96,8 @@ export function GithubImporterRoot() {
|
||||
const { data: appIntegrations } = useSWR(APP_INTEGRATIONS, () => integrationService.getAppIntegrationsList());
|
||||
|
||||
const { data: workspaceIntegrations } = useSWR(
|
||||
workspaceSlug ? WORKSPACE_INTEGRATIONS(workspaceSlug as string) : null,
|
||||
workspaceSlug ? () => integrationService.getWorkspaceIntegrationsList(workspaceSlug as string) : null
|
||||
workspaceSlug ? WORKSPACE_INTEGRATIONS(workspaceSlug) : null,
|
||||
workspaceSlug ? () => integrationService.getWorkspaceIntegrationsList(workspaceSlug) : null
|
||||
);
|
||||
|
||||
const activeIntegrationState = () => {
|
||||
@@ -138,10 +138,10 @@ export function GithubImporterRoot() {
|
||||
};
|
||||
|
||||
await githubIntegrationService
|
||||
.createGithubServiceImport(workspaceSlug as string, payload)
|
||||
.createGithubServiceImport(workspaceSlug, payload)
|
||||
.then(() => {
|
||||
router.push(`/${workspaceSlug}/settings/imports`);
|
||||
mutate(IMPORTER_SERVICES_LIST(workspaceSlug as string));
|
||||
mutate(IMPORTER_SERVICES_LIST(workspaceSlug));
|
||||
})
|
||||
.catch(() =>
|
||||
setToast({
|
||||
|
||||
@@ -54,8 +54,8 @@ const IntegrationGuide = observer(function IntegrationGuide() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { data: importerServices } = useSWR(
|
||||
workspaceSlug ? IMPORTER_SERVICES_LIST(workspaceSlug as string) : null,
|
||||
workspaceSlug ? () => integrationService.getImporterServicesList(workspaceSlug as string) : null
|
||||
workspaceSlug ? IMPORTER_SERVICES_LIST(workspaceSlug) : null,
|
||||
workspaceSlug ? () => integrationService.getImporterServicesList(workspaceSlug) : null
|
||||
);
|
||||
|
||||
const handleDeleteImport = (importService: IImporterService) => {
|
||||
@@ -129,7 +129,7 @@ const IntegrationGuide = observer(function IntegrationGuide() {
|
||||
className="flex flex-shrink-0 items-center gap-1 rounded bg-custom-background-80 px-1.5 py-1 text-xs outline-none"
|
||||
onClick={() => {
|
||||
setRefreshing(true);
|
||||
mutate(IMPORTER_SERVICES_LIST(workspaceSlug as string)).then(() => setRefreshing(false));
|
||||
mutate(IMPORTER_SERVICES_LIST(workspaceSlug)).then(() => setRefreshing(false));
|
||||
}}
|
||||
>
|
||||
<RefreshCw className={`h-3 w-3 ${refreshing ? "animate-spin" : ""}`} />{" "}
|
||||
|
||||
@@ -94,7 +94,7 @@ export function JiraImportUsers() {
|
||||
input
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
label={<span className="capitalize">{Boolean(value) ? value : ("Ignore" as any)}</span>}
|
||||
label={<span className="capitalize">{value ? value : ("Ignore" as any)}</span>}
|
||||
>
|
||||
<CustomSelect.Option value="invite">Invite by email</CustomSelect.Option>
|
||||
<CustomSelect.Option value="map">Map to existing</CustomSelect.Option>
|
||||
|
||||
@@ -60,9 +60,8 @@ export const SingleIntegrationCard = observer(function SingleIntegrationCard({ i
|
||||
slack_client_id: config?.slack_client_id || "",
|
||||
});
|
||||
|
||||
const { data: workspaceIntegrations } = useSWR(
|
||||
workspaceSlug ? WORKSPACE_INTEGRATIONS(workspaceSlug as string) : null,
|
||||
() => (workspaceSlug ? integrationService.getWorkspaceIntegrationsList(workspaceSlug as string) : null)
|
||||
const { data: workspaceIntegrations } = useSWR(workspaceSlug ? WORKSPACE_INTEGRATIONS(workspaceSlug) : null, () =>
|
||||
workspaceSlug ? integrationService.getWorkspaceIntegrationsList(workspaceSlug) : null
|
||||
);
|
||||
|
||||
const handleRemoveIntegration = async () => {
|
||||
@@ -73,10 +72,10 @@ export const SingleIntegrationCard = observer(function SingleIntegrationCard({ i
|
||||
setDeletingIntegration(true);
|
||||
|
||||
await integrationService
|
||||
.deleteWorkspaceIntegration(workspaceSlug as string, workspaceIntegrationId ?? "")
|
||||
.deleteWorkspaceIntegration(workspaceSlug, workspaceIntegrationId ?? "")
|
||||
.then(() => {
|
||||
mutate<IWorkspaceIntegration[]>(
|
||||
WORKSPACE_INTEGRATIONS(workspaceSlug as string),
|
||||
WORKSPACE_INTEGRATIONS(workspaceSlug),
|
||||
(prevData) => prevData?.filter((i) => i.id !== workspaceIntegrationId),
|
||||
false
|
||||
);
|
||||
|
||||
@@ -38,16 +38,10 @@ export const SelectChannel = observer(function SelectChannel({ integration }: Pr
|
||||
});
|
||||
|
||||
const { data: projectIntegration } = useSWR(
|
||||
workspaceSlug && projectId && integration.id
|
||||
? SLACK_CHANNEL_INFO(workspaceSlug as string, projectId as string)
|
||||
: null,
|
||||
workspaceSlug && projectId && integration.id ? SLACK_CHANNEL_INFO(workspaceSlug, projectId) : null,
|
||||
() =>
|
||||
workspaceSlug && projectId && integration.id
|
||||
? appInstallationService.getSlackChannelDetail(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
integration.id as string
|
||||
)
|
||||
? appInstallationService.getSlackChannelDetail(workspaceSlug, projectId, integration.id)
|
||||
: null
|
||||
);
|
||||
|
||||
@@ -74,7 +68,7 @@ export const SelectChannel = observer(function SelectChannel({ integration }: Pr
|
||||
setSlackChannel(null);
|
||||
});
|
||||
appInstallationService
|
||||
.removeSlackChannel(workspaceSlug as string, projectId as string, integration.id as string, slackChannel?.id)
|
||||
.removeSlackChannel(workspaceSlug, projectId, integration.id, slackChannel?.id)
|
||||
.catch((err) => console.error(err));
|
||||
};
|
||||
|
||||
|
||||
@@ -186,7 +186,7 @@ export const RelationsCollapsibleContent = observer(function RelationsCollapsibl
|
||||
issueCrudState.delete.issue.id &&
|
||||
issueCrudState.delete.issue.project_id
|
||||
) {
|
||||
const deleteOperation = !!issueCrudState.delete.issue?.is_epic
|
||||
const deleteOperation = issueCrudState.delete.issue?.is_epic
|
||||
? epicOperations.remove
|
||||
: issueOperations.remove;
|
||||
await deleteOperation(
|
||||
@@ -202,7 +202,7 @@ export const RelationsCollapsibleContent = observer(function RelationsCollapsibl
|
||||
|
||||
{shouldRenderIssueUpdateModal && (
|
||||
<>
|
||||
{!!issueCrudState?.update?.issue?.is_epic ? (
|
||||
{issueCrudState?.update?.issue?.is_epic ? (
|
||||
<CreateUpdateEpicModal
|
||||
isOpen={issueCrudState?.update?.toggle}
|
||||
onClose={() => {
|
||||
|
||||
@@ -51,7 +51,7 @@ export const RelationActionButton = observer(function RelationActionButton(props
|
||||
<CustomMenu.MenuItem
|
||||
key={index}
|
||||
onClick={() => {
|
||||
handleOnClick(item.key as TIssueRelationTypes);
|
||||
handleOnClick(item.key);
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
|
||||
@@ -13,7 +13,6 @@ import { useProjectInbox } from "@/hooks/store/use-project-inbox";
|
||||
// types
|
||||
import { LabelList, IssueLabelSelectRoot } from "./";
|
||||
// TODO: Fix this import statement, as core should not import from ee
|
||||
// eslint-disable-next-line import/order
|
||||
|
||||
export type TIssueLabel = {
|
||||
workspaceSlug: string;
|
||||
|
||||
@@ -39,12 +39,7 @@ import { CalendarWeekDays } from "./week-days";
|
||||
import { CalendarWeekHeader } from "./week-header";
|
||||
|
||||
type Props = {
|
||||
issuesFilterStore:
|
||||
| IProjectIssuesFilter
|
||||
| IModuleIssuesFilter
|
||||
| ICycleIssuesFilter
|
||||
| IProjectViewIssuesFilter
|
||||
| IProjectEpicsFilter;
|
||||
issuesFilterStore: IProjectIssuesFilter | IModuleIssuesFilter | ICycleIssuesFilter | IProjectViewIssuesFilter;
|
||||
issues: TIssueMap | undefined;
|
||||
groupedIssueIds: TGroupedIssues;
|
||||
layout: "month" | "week" | undefined;
|
||||
|
||||
@@ -23,12 +23,7 @@ import type { TRenderQuickActions } from "../list/list-view-types";
|
||||
import { CalendarIssueBlocks } from "./issue-blocks";
|
||||
|
||||
type Props = {
|
||||
issuesFilterStore:
|
||||
| IProjectIssuesFilter
|
||||
| IModuleIssuesFilter
|
||||
| ICycleIssuesFilter
|
||||
| IProjectViewIssuesFilter
|
||||
| IProjectEpicsFilter;
|
||||
issuesFilterStore: IProjectIssuesFilter | IModuleIssuesFilter | ICycleIssuesFilter | IProjectViewIssuesFilter;
|
||||
date: ICalendarDate;
|
||||
issues: TIssueMap | undefined;
|
||||
groupedIssueIds: TGroupedIssues;
|
||||
|
||||
@@ -17,12 +17,7 @@ import type { IProjectViewIssuesFilter } from "@/store/issue/project-views";
|
||||
// helpers
|
||||
|
||||
interface Props {
|
||||
issuesFilterStore:
|
||||
| IProjectIssuesFilter
|
||||
| IModuleIssuesFilter
|
||||
| ICycleIssuesFilter
|
||||
| IProjectViewIssuesFilter
|
||||
| IProjectEpicsFilter;
|
||||
issuesFilterStore: IProjectIssuesFilter | IModuleIssuesFilter | ICycleIssuesFilter | IProjectViewIssuesFilter;
|
||||
}
|
||||
export const CalendarMonthsDropdown = observer(function CalendarMonthsDropdown(props: Props) {
|
||||
const { issuesFilterStore } = props;
|
||||
|
||||
@@ -25,12 +25,7 @@ import type { IProjectIssuesFilter } from "@/store/issue/project";
|
||||
import type { IProjectViewIssuesFilter } from "@/store/issue/project-views";
|
||||
|
||||
interface ICalendarHeader {
|
||||
issuesFilterStore:
|
||||
| IProjectIssuesFilter
|
||||
| IModuleIssuesFilter
|
||||
| ICycleIssuesFilter
|
||||
| IProjectViewIssuesFilter
|
||||
| IProjectEpicsFilter;
|
||||
issuesFilterStore: IProjectIssuesFilter | IModuleIssuesFilter | ICycleIssuesFilter | IProjectViewIssuesFilter;
|
||||
updateFilters?: (
|
||||
projectId: string,
|
||||
filterType: TSupportedFilterTypeForUpdate,
|
||||
|
||||
@@ -16,12 +16,7 @@ import type { IProjectViewIssuesFilter } from "@/store/issue/project-views";
|
||||
import { CalendarMonthsDropdown, CalendarOptionsDropdown } from "./dropdowns";
|
||||
|
||||
interface ICalendarHeader {
|
||||
issuesFilterStore:
|
||||
| IProjectIssuesFilter
|
||||
| IModuleIssuesFilter
|
||||
| ICycleIssuesFilter
|
||||
| IProjectViewIssuesFilter
|
||||
| IProjectEpicsFilter;
|
||||
issuesFilterStore: IProjectIssuesFilter | IModuleIssuesFilter | ICycleIssuesFilter | IProjectViewIssuesFilter;
|
||||
updateFilters?: (
|
||||
projectId: string,
|
||||
filterType: TSupportedFilterTypeForUpdate,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable react/display-name */
|
||||
import { useState, useRef, forwardRef } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { useParams } from "next/navigation";
|
||||
|
||||
@@ -14,12 +14,7 @@ import type { TRenderQuickActions } from "../list/list-view-types";
|
||||
import { CalendarDayTile } from "./day-tile";
|
||||
|
||||
type Props = {
|
||||
issuesFilterStore:
|
||||
| IProjectIssuesFilter
|
||||
| IModuleIssuesFilter
|
||||
| ICycleIssuesFilter
|
||||
| IProjectViewIssuesFilter
|
||||
| IProjectEpicsFilter;
|
||||
issuesFilterStore: IProjectIssuesFilter | IModuleIssuesFilter | ICycleIssuesFilter | IProjectViewIssuesFilter;
|
||||
issues: TIssueMap | undefined;
|
||||
groupedIssueIds: TGroupedIssues;
|
||||
week: ICalendarWeek | undefined;
|
||||
|
||||
@@ -37,7 +37,7 @@ export const FilterDisplayProperties = observer(function FilterDisplayProperties
|
||||
// states
|
||||
const [previewEnabled, setPreviewEnabled] = React.useState(true);
|
||||
// derived values
|
||||
const projectId = !!routerProjectId ? routerProjectId?.toString() : undefined;
|
||||
const projectId = routerProjectId ? routerProjectId?.toString() : undefined;
|
||||
|
||||
// Filter out "cycle" and "module" keys if cycleViewDisabled or moduleViewDisabled is true
|
||||
// Also filter out display properties that should not be rendered
|
||||
|
||||
@@ -152,7 +152,7 @@ export const KanBan = observer(function KanBan(props: IKanBan) {
|
||||
const issueIds = isSubGroup
|
||||
? ((groupedIssueIds as TSubGroupedIssues)?.[subList.id]?.[sub_group_id] ?? [])
|
||||
: ((groupedIssueIds as TGroupedIssues)?.[subList.id] ?? []);
|
||||
const issueLength = issueIds?.length as number;
|
||||
const issueLength = issueIds?.length;
|
||||
const groupHeight = issueLength * approximateCardHeight;
|
||||
|
||||
return (
|
||||
|
||||
@@ -268,7 +268,7 @@ export const KanbanGroup = observer(function KanbanGroup(props: IKanbanGroup) {
|
||||
const canDragIssuesInCurrentGrouping =
|
||||
!!group_by &&
|
||||
DRAG_ALLOWED_GROUPS.includes(group_by) &&
|
||||
(!!sub_group_by ? DRAG_ALLOWED_GROUPS.includes(sub_group_by) : true);
|
||||
(sub_group_by ? DRAG_ALLOWED_GROUPS.includes(sub_group_by) : true);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@@ -160,7 +160,7 @@ const getCycleColumns = (): IGroupByColumn[] | undefined => {
|
||||
cycles.push({
|
||||
id: cycle.id,
|
||||
name: cycle.name,
|
||||
icon: <CycleGroupIcon cycleGroup={cycleStatus as TCycleGroups} className="h-3.5 w-3.5" />,
|
||||
icon: <CycleGroupIcon cycleGroup={cycleStatus} className="h-3.5 w-3.5" />,
|
||||
payload: { cycle_id: cycle.id },
|
||||
isDropDisabled,
|
||||
dropErrorMessage: isDropDisabled ? "Work item cannot be moved to completed cycles" : undefined,
|
||||
@@ -486,11 +486,8 @@ const handleSortOrder = (
|
||||
return currentIssueState;
|
||||
};
|
||||
|
||||
export const getIssueBlockId = (
|
||||
issueId: string | undefined,
|
||||
groupId: string | undefined,
|
||||
subGroupId?: string | undefined
|
||||
) => `issue_${issueId}_${groupId}_${subGroupId}`;
|
||||
export const getIssueBlockId = (issueId: string | undefined, groupId: string | undefined, subGroupId?: string) =>
|
||||
`issue_${issueId}_${groupId}_${subGroupId}`;
|
||||
|
||||
/**
|
||||
* returns empty Array if groupId is None
|
||||
|
||||
@@ -180,7 +180,7 @@ export const IssueDescriptionEditor = observer(function IssueDescriptionEditor(p
|
||||
id="issue-modal-editor"
|
||||
initialValue={value ?? ""}
|
||||
value={descriptionHtmlData}
|
||||
workspaceSlug={workspaceSlug?.toString() as string}
|
||||
workspaceSlug={workspaceSlug?.toString()}
|
||||
workspaceId={workspaceId}
|
||||
projectId={projectId}
|
||||
onChange={(_description: object, description_html: string) => {
|
||||
|
||||
@@ -70,7 +70,7 @@ export function ParentIssuesListModal({
|
||||
setIsLoading(true);
|
||||
|
||||
projectService
|
||||
.projectIssuesSearch(workspaceSlug as string, projectId as string, {
|
||||
.projectIssuesSearch(workspaceSlug, projectId, {
|
||||
search: debouncedSearchTerm,
|
||||
parent: searchEpic ? undefined : true,
|
||||
issue_id: issueId,
|
||||
|
||||
@@ -63,7 +63,7 @@ export const RelationIssueListItem = observer(function RelationIssueListItem(pro
|
||||
// derived values
|
||||
const issue = getIssueById(relationIssueId);
|
||||
const { handleRedirection } = useIssuePeekOverviewRedirection(!!issue?.is_epic);
|
||||
const issueOperations = useRelationOperations(!!issue?.is_epic ? EIssueServiceType.EPICS : EIssueServiceType.ISSUES);
|
||||
const issueOperations = useRelationOperations(issue?.is_epic ? EIssueServiceType.EPICS : EIssueServiceType.ISSUES);
|
||||
const projectDetail = (issue && issue.project_id && project.getProjectById(issue.project_id)) || undefined;
|
||||
const projectId = issue?.project_id;
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ export const LabelDndHOC = observer(function LabelDndHOC(props: Props) {
|
||||
if (instruction === "reorder-below") dropAtEndOfList = true;
|
||||
|
||||
const sourceData = source.data as TargetData;
|
||||
if (sourceData.id) onDrop(sourceData.id as string, parentId, droppedLabelId, dropAtEndOfList);
|
||||
if (sourceData.id) onDrop(sourceData.id, parentId, droppedLabelId, dropAtEndOfList);
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
@@ -78,6 +78,7 @@ export const TalkToSalesCard = observer(function TalkToSalesCard(props: TalkToSa
|
||||
upgradeButtonStyle,
|
||||
"relative inline-flex items-center justify-center w-56 px-4 py-2 text-sm font-medium rounded-lg focus:outline-none"
|
||||
)}
|
||||
rel="noreferrer"
|
||||
>
|
||||
Talk to Sales
|
||||
</a>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
"use client";
|
||||
import { observer } from "mobx-react";
|
||||
import { useParams, usePathname } from "next/navigation";
|
||||
import { Check, SettingsIcon } from "lucide-react";
|
||||
@@ -14,7 +13,7 @@ import { DesktopSidebarWorkspaceMenu } from "@/plane-web/components/desktop";
|
||||
// local imports
|
||||
import { AppSidebarItemsRoot } from "./items-root";
|
||||
|
||||
export const AppRailRoot = observer(() => {
|
||||
export const AppRailRoot = observer(function AppRailRoot() {
|
||||
// router
|
||||
const { workspaceSlug } = useParams();
|
||||
const pathname = usePathname();
|
||||
|
||||
@@ -38,7 +38,9 @@ const PERSONAL_ITEMS: Array<{ key: TPersonalNavigationItemKey; labelTranslationK
|
||||
{ key: "drafts", labelTranslationKey: "drafts" },
|
||||
];
|
||||
|
||||
export const CustomizeNavigationDialog: FC<TCustomizeNavigationDialogProps> = observer((props) => {
|
||||
export const CustomizeNavigationDialog = observer(function CustomizeNavigationDialog(
|
||||
props: TCustomizeNavigationDialogProps
|
||||
) {
|
||||
const { isOpen, onClose } = props;
|
||||
const { t } = useTranslation();
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// components/AppSidebarItemsRoot.tsx
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import type { AppSidebarItemData } from "@/components/sidebar/sidebar-item";
|
||||
@@ -11,7 +10,8 @@ type Props = {
|
||||
showLabel?: boolean;
|
||||
};
|
||||
|
||||
const Component = ({ dockItems, showLabel = true }: Props) => (
|
||||
function Component({ dockItems, showLabel = true }: Props) {
|
||||
return (
|
||||
<>
|
||||
{dockItems
|
||||
.filter((item) => item.shouldRender)
|
||||
@@ -19,6 +19,7 @@ const Component = ({ dockItems, showLabel = true }: Props) => (
|
||||
<AppSidebarItem key={item.label} item={{ ...item, showLabel }} variant="link" />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
export const AppSidebarItemsRoot = withDockItems(Component);
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
"use client";
|
||||
|
||||
import type { FC } from "react";
|
||||
import { useState, useRef } from "react";
|
||||
import { useNavigate } from "react-router";
|
||||
@@ -21,7 +19,7 @@ type Props = {
|
||||
onPublishModal: () => void;
|
||||
};
|
||||
|
||||
export const ProjectActionsMenu: FC<Props> = ({
|
||||
export function ProjectActionsMenu({
|
||||
workspaceSlug,
|
||||
project,
|
||||
isAdmin,
|
||||
@@ -29,7 +27,7 @@ export const ProjectActionsMenu: FC<Props> = ({
|
||||
onCopyText,
|
||||
onLeaveProject,
|
||||
onPublishModal,
|
||||
}) => {
|
||||
}: Props) {
|
||||
// states
|
||||
const [isMenuActive, setIsMenuActive] = useState(false);
|
||||
// translation
|
||||
@@ -111,4 +109,4 @@ export const ProjectActionsMenu: FC<Props> = ({
|
||||
)}
|
||||
</CustomMenu>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ type TProjectHeaderProps = {
|
||||
projectId: string;
|
||||
};
|
||||
|
||||
export const ProjectHeader = observer((props: TProjectHeaderProps) => {
|
||||
export const ProjectHeader = observer(function ProjectHeader(props: TProjectHeaderProps) {
|
||||
const { workspaceSlug, projectId } = props;
|
||||
// router
|
||||
const router = useAppRouter();
|
||||
|
||||
@@ -24,13 +24,7 @@ type Props = {
|
||||
* Displays items that don't fit in the visible area, with action icons
|
||||
* Shows "Eye" icon for user-hidden items, "Set as default" icon for all items
|
||||
*/
|
||||
export const TabNavigationOverflowMenu: React.FC<Props> = ({
|
||||
overflowItems,
|
||||
isActive,
|
||||
tabPreferences,
|
||||
onToggleDefault,
|
||||
onShow,
|
||||
}) => {
|
||||
export function TabNavigationOverflowMenu({ overflowItems, isActive, tabPreferences, onToggleDefault, onShow }: Props) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
@@ -97,4 +91,4 @@ export const TabNavigationOverflowMenu: React.FC<Props> = ({
|
||||
})}
|
||||
</Menu>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
"use client";
|
||||
|
||||
import type { FC } from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
@@ -44,7 +42,7 @@ type TTabNavigationRootProps = {
|
||||
projectId: string;
|
||||
};
|
||||
|
||||
export const TabNavigationRoot: FC<TTabNavigationRootProps> = observer((props) => {
|
||||
export const TabNavigationRoot = observer(function TabNavigationRoot(props: TTabNavigationRootProps) {
|
||||
const { workspaceSlug, projectId } = props;
|
||||
const { workItem: workItemIdentifierFromRoute } = useParams();
|
||||
const location = useLocation();
|
||||
|
||||
@@ -23,14 +23,14 @@ export type TTabNavigationVisibleItemProps = {
|
||||
* Individual visible tab navigation item with context menu
|
||||
* Handles right-click actions for setting default and hiding tabs
|
||||
*/
|
||||
export const TabNavigationVisibleItem: React.FC<TTabNavigationVisibleItemProps> = ({
|
||||
export function TabNavigationVisibleItem({
|
||||
item,
|
||||
isActive,
|
||||
tabPreferences,
|
||||
onToggleDefault,
|
||||
onHide,
|
||||
itemRef,
|
||||
}) => {
|
||||
}: TTabNavigationVisibleItemProps) {
|
||||
const { t } = useTranslation();
|
||||
const isDefault = item.key === tabPreferences.defaultTab;
|
||||
|
||||
@@ -76,4 +76,4 @@ export const TabNavigationVisibleItem: React.FC<TTabNavigationVisibleItemProps>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import { useUser } from "@/hooks/store/user";
|
||||
import { useAppRouter } from "@/hooks/use-app-router";
|
||||
import { useExpandableSearch } from "@/hooks/use-expandable-search";
|
||||
|
||||
export const TopNavPowerK = observer(() => {
|
||||
export const TopNavPowerK = observer(function TopNavPowerK() {
|
||||
// router
|
||||
const router = useAppRouter();
|
||||
const params = useParams();
|
||||
|
||||
@@ -87,7 +87,8 @@ export const PageActions = observer(function PageActions(props: Props) {
|
||||
canCurrentUserMovePage,
|
||||
} = page;
|
||||
// menu items
|
||||
const MENU_ITEMS = useMemo(() => {
|
||||
const MENU_ITEMS = useMemo(
|
||||
function MENU_ITEMS() {
|
||||
const menuItems: (TContextMenuItem & { key: TPageActions })[] = [
|
||||
{
|
||||
key: "toggle-lock",
|
||||
@@ -175,7 +176,8 @@ export const PageActions = observer(function PageActions(props: Props) {
|
||||
menuItems.push(...extraOptions);
|
||||
}
|
||||
return menuItems;
|
||||
}, [
|
||||
},
|
||||
[
|
||||
extraOptions,
|
||||
is_locked,
|
||||
canCurrentUserLockPage,
|
||||
@@ -188,7 +190,8 @@ export const PageActions = observer(function PageActions(props: Props) {
|
||||
canCurrentUserMovePage,
|
||||
isMovePageEnabled,
|
||||
pageOperations,
|
||||
]);
|
||||
]
|
||||
);
|
||||
// arrange options
|
||||
const arrangedOptions = useMemo<(TContextMenuItem & { key: TPageActions })[]>(
|
||||
() =>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user