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