chore: run fixes (#4993)

* chore: run fixes

* fix: type, just use hocuspocusservercontext

* fix: codemod

* chore: run ee fixes

---------

Co-authored-by: Palanikannan M <[email protected]>
This commit is contained in:
Aaron
2025-12-08 22:26:20 +05:30
committed by GitHub
co-authored by Palanikannan M
parent 3b68bc8f55
commit f464acbf97
2187 changed files with 17562 additions and 18425 deletions
@@ -27,6 +27,7 @@ jobs:
env:
TURBO_SCM_BASE: ${{ github.event.pull_request.base.sha }}
TURBO_SCM_HEAD: ${{ github.sha }}
NODE_OPTIONS: --max-old-space-size=4096
steps:
- name: Checkout code
uses: actions/checkout@v4
-12
View File
@@ -45,15 +45,3 @@ prefer-frozen-lockfile = true
# Use isolated linker (best compatibility with Node ecosystem tools)
node-linker = isolated
# ------------------------------
# Hoisting Strategy
# ------------------------------
# Hoist commonly used tools to the root to prevent duplicates and speed up resolution
public-hoist-pattern[] = typescript
public-hoist-pattern[] = eslint
public-hoist-pattern[] = *@plane/*
public-hoist-pattern[] = vite
public-hoist-pattern[] = turbo
@@ -1,5 +1,3 @@
"use client";
import type { FC } from "react";
import { isEmpty } from "lodash-es";
import { Smartphone } from "lucide-react";
@@ -10,7 +8,7 @@ import { CodeBlock } from "@/components/common/code-block";
import type { TCopyField } from "@/components/common/copy-field";
import { CopyField } from "@/components/common/copy-field";
export const GithubMobileForm: FC = () => {
export function GithubMobileForm() {
const originURL = !isEmpty(API_BASE_URL) ? API_BASE_URL : typeof window !== "undefined" ? window.location.origin : "";
const GITHUB_MOBILE_SERVICE_DETAILS: TCopyField[] = [
@@ -48,4 +46,4 @@ export const GithubMobileForm: FC = () => {
</div>
</div>
);
};
}
@@ -1,5 +1,3 @@
"use client";
import type { FC } from "react";
import { isEmpty } from "lodash-es";
import { Smartphone } from "lucide-react";
@@ -10,7 +8,7 @@ import { CodeBlock } from "@/components/common/code-block";
import type { TCopyField } from "@/components/common/copy-field";
import { CopyField } from "@/components/common/copy-field";
export const GoogleMobileForm: FC = () => {
export function GoogleMobileForm() {
const originURL = !isEmpty(API_BASE_URL) ? API_BASE_URL : typeof window !== "undefined" ? window.location.origin : "";
const GOOGLE_MOBILE_SERVICE_DETAILS: TCopyField[] = [
@@ -48,4 +46,4 @@ export const GoogleMobileForm: FC = () => {
</div>
</div>
);
};
}
@@ -24,7 +24,7 @@ type Props = {
type OIDCConfigFormValues = Record<TInstanceOIDCAuthenticationConfigurationKeys, string>;
export const InstanceOIDCConfigForm: FC<Props> = (props) => {
export function InstanceOIDCConfigForm(props: Props) {
const { config } = props;
// states
const [isDiscardChangesModalOpen, setIsDiscardChangesModalOpen] = useState(false);
@@ -293,4 +293,4 @@ export const InstanceOIDCConfigForm: FC<Props> = (props) => {
</div>
</>
);
};
}
@@ -1,5 +1,3 @@
"use client";
import { useState } from "react";
import { observer } from "mobx-react";
import useSWR from "swr";
@@ -19,7 +17,7 @@ import { useInstanceFlag } from "@/plane-admin/hooks/store/use-instance-flag";
import type { Route } from "./+types/page";
import { InstanceOIDCConfigForm } from "./form";
const InstanceOIDCAuthenticationPage = observer<React.FC<Route.ComponentProps>>(() => {
const InstanceOIDCAuthenticationPage = observer(function InstanceOIDCAuthenticationPage(_props: Route.ComponentProps) {
// state
const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
// store
@@ -26,7 +26,7 @@ type Props = {
type SAMLConfigFormValues = Record<TInstanceSAMLAuthenticationConfigurationKeys, string>;
export const InstanceSAMLConfigForm: FC<Props> = (props) => {
export function InstanceSAMLConfigForm(props: Props) {
const { config } = props;
// states
const [isDiscardChangesModalOpen, setIsDiscardChangesModalOpen] = useState(false);
@@ -301,4 +301,4 @@ export const InstanceSAMLConfigForm: FC<Props> = (props) => {
</div>
</>
);
};
}
@@ -1,5 +1,3 @@
"use client";
import { useState } from "react";
import { observer } from "mobx-react";
import useSWR from "swr";
@@ -19,7 +17,7 @@ import { useInstanceFlag } from "@/plane-admin/hooks/store/use-instance-flag";
import type { Route } from "./+types/page";
import { InstanceSAMLConfigForm } from "./form";
const InstanceSAMLAuthenticationPage = observer<React.FC<Route.ComponentProps>>(() => {
const InstanceSAMLAuthenticationPage = observer(function InstanceSAMLAuthenticationPage(_props: Route.ComponentProps) {
// state
const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
// store
@@ -11,7 +11,7 @@ import { cn } from "@plane/utils";
// hooks
import { useInstance, useTheme } from "@/hooks/store";
// assets
// eslint-disable-next-line import/order
import packageJson from "package.json";
const helpOptions = [
+3 -6
View File
@@ -26,7 +26,7 @@ export enum EErrorAlertType {
}
const errorCodeMessages: {
[key in EAdminAuthErrorCodes]: { title: string; message: (email?: string | undefined) => React.ReactNode };
[key in EAdminAuthErrorCodes]: { title: string; message: (email?: string) => React.ReactNode };
} = {
// admin
[EAdminAuthErrorCodes.ADMIN_ALREADY_EXIST]: {
@@ -79,14 +79,11 @@ const errorCodeMessages: {
},
[EAdminAuthErrorCodes.ADMIN_USER_DEACTIVATED]: {
title: `User account deactivated`,
message: () => `User account deactivated. Please contact ${!!SUPPORT_EMAIL ? SUPPORT_EMAIL : "administrator"}.`,
message: () => `User account deactivated. Please contact ${SUPPORT_EMAIL ? SUPPORT_EMAIL : "administrator"}.`,
},
};
export const authErrorHandler = (
errorCode: EAdminAuthErrorCodes,
email?: string | undefined
): TAdminAuthErrorInfo | undefined => {
export const authErrorHandler = (errorCode: EAdminAuthErrorCodes, email?: string): TAdminAuthErrorInfo | undefined => {
const bannerAlertErrorCodes = [
EAdminAuthErrorCodes.ADMIN_ALREADY_EXIST,
EAdminAuthErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD_FIRST_NAME,
-1
View File
@@ -1,4 +1,3 @@
/* eslint-disable import/order */
import * as Sentry from "@sentry/react-router";
import { startTransition, StrictMode } from "react";
import { hydrateRoot } from "react-dom/client";
@@ -11,6 +11,7 @@ export function UpgradeButton() {
href="https://plane.so/pricing?mode=self-hosted"
target="_blank"
className={cn(getButtonStyling("primary", "sm"))}
rel="noreferrer"
>
Upgrade
<SquareArrowOutUpRight className="h-3.5 w-3.5 p-0.5" />
@@ -24,6 +24,7 @@ export const WorkspaceListItem = observer(function WorkspaceListItem({ workspace
href={`${WEB_BASE_URL}/${encodeURIComponent(workspace.slug)}`}
target="_blank"
className="group flex items-center justify-between p-4 gap-2.5 truncate border border-custom-border-200/70 hover:border-custom-border-200 hover:bg-custom-background-90 rounded-md"
rel="noreferrer"
>
<div className="flex items-start gap-4">
<span
@@ -114,7 +114,7 @@ export const getAuthenticationModes: (props: TGetAuthenticationModeProps) => TIn
},
];
export const AuthenticationModes: React.FC<TAuthenticationModeProps> = observer((props) => {
export const AuthenticationModes = observer(function AuthenticationModes(props: TAuthenticationModeProps) {
const { disabled, updateConfig } = props;
// next-themes
const { resolvedTheme } = useTheme();
@@ -1,5 +1,3 @@
"use client";
import React from "react";
import { observer } from "mobx-react";
import Link from "next/link";
@@ -18,7 +16,7 @@ type Props = {
updateConfig: (key: TInstanceEnterpriseAuthenticationMethodKeys, value: string) => void;
};
export const OIDCConfiguration: React.FC<Props> = observer((props) => {
export const OIDCConfiguration = observer(function OIDCConfiguration(props: Props) {
const { disabled, updateConfig } = props;
// store
const { formattedConfig } = useInstance();
@@ -1,28 +1,30 @@
export const SAMLAttributeMappingTable = () => (
<table className="table-auto border-collapse text-custom-text-200 text-sm w-full">
<thead>
<tr className="text-left border-b border-custom-border-200">
<th className="py-2">IdP</th>
<th className="py-2">Plane</th>
</tr>
</thead>
<tbody>
<tr className="border-b border-custom-border-200">
<td className="py-2">Name ID format</td>
<td className="py-2">emailAddress</td>
</tr>
<tr className="border-b border-custom-border-200">
<td className="py-2">first_name</td>
<td className="py-2">user.firstName</td>
</tr>
<tr className="border-b border-custom-border-200">
<td className="py-2">last_name</td>
<td className="py-2">user.lastName</td>
</tr>
<tr className="border-b border-custom-border-200">
<td className="py-2">email</td>
<td className="py-2">user.email</td>
</tr>
</tbody>
</table>
);
export function SAMLAttributeMappingTable() {
return (
<table className="table-auto border-collapse text-custom-text-200 text-sm w-full">
<thead>
<tr className="text-left border-b border-custom-border-200">
<th className="py-2">IdP</th>
<th className="py-2">Plane</th>
</tr>
</thead>
<tbody>
<tr className="border-b border-custom-border-200">
<td className="py-2">Name ID format</td>
<td className="py-2">emailAddress</td>
</tr>
<tr className="border-b border-custom-border-200">
<td className="py-2">first_name</td>
<td className="py-2">user.firstName</td>
</tr>
<tr className="border-b border-custom-border-200">
<td className="py-2">last_name</td>
<td className="py-2">user.lastName</td>
</tr>
<tr className="border-b border-custom-border-200">
<td className="py-2">email</td>
<td className="py-2">user.email</td>
</tr>
</tbody>
</table>
);
}
@@ -1,5 +1,3 @@
"use client";
import React from "react";
import { observer } from "mobx-react";
import Link from "next/link";
@@ -18,7 +16,7 @@ type Props = {
updateConfig: (key: TInstanceEnterpriseAuthenticationMethodKeys, value: string) => void;
};
export const SAMLConfiguration: React.FC<Props> = observer((props) => {
export const SAMLConfiguration = observer(function SAMLConfiguration(props: Props) {
const { disabled, updateConfig } = props;
// store
const { formattedConfig } = useInstance();
@@ -1,12 +1,10 @@
"use client";
import React from "react";
// plane internal packages
import { WEB_BASE_URL } from "@plane/constants";
import { Button } from "@plane/propel/button";
import { AlertModalCore } from "@plane/ui";
export const UpgradeButton: React.FC = () => {
export function UpgradeButton() {
// states
const [isActivationModalOpen, setIsActivationModalOpen] = React.useState(false);
// derived values
@@ -36,4 +34,4 @@ export const UpgradeButton: React.FC = () => {
</Button>
</>
);
};
}
@@ -88,7 +88,7 @@ export class AdminController {
// Validate and map error code to ForceCloseReason
let reason: ForceCloseReason;
if (isValidForceCloseReason(errorCode)) {
reason = errorCode as ForceCloseReason;
reason = errorCode;
} else {
logger.warn(`[ADMIN] Invalid error code "${errorCode}", defaulting to ADMIN_REQUEST`);
reason = ForceCloseReason.ADMIN_REQUEST;
@@ -168,7 +168,7 @@ export class BroadcastController {
if (matchingEmbeds.length > 0) {
matchingEmbeds.forEach(({ parent, indexInParent }) => {
const newPageEmbedNode = new Y.XmlElement("pageEmbedComponent");
newPageEmbedNode.setAttribute("entity_identifier", data.new_page_id as string);
newPageEmbedNode.setAttribute("entity_identifier", data.new_page_id);
newPageEmbedNode.setAttribute("entity_name", "sub_page");
newPageEmbedNode.setAttribute("id", uuidv4());
newPageEmbedNode.setAttribute("workspace_identifier", workspace_slug || "");
@@ -12,7 +12,7 @@ export class ForceCloseHandler implements Extension {
priority = 999;
async onConfigure({ instance }: onConfigurePayload) {
const redisExt = instance.configuration.extensions.find((ext) => ext instanceof Redis) as Redis | undefined;
const redisExt = instance.configuration.extensions.find((ext) => ext instanceof Redis);
if (!redisExt) {
logger.warn("[FORCE_CLOSE_HANDLER] Redis extension not found");
@@ -149,7 +149,7 @@ export const forceCloseDocumentAcrossServers = async (
logger.info(`[FORCE_CLOSE] Closed ${closedCount}/${connectionsBefore} local connections`);
// STEP 4: BROADCAST TO OTHER SERVERS
const redisExt = instance.configuration.extensions.find((ext) => ext instanceof Redis) as Redis | undefined;
const redisExt = instance.configuration.extensions.find((ext) => ext instanceof Redis);
if (redisExt) {
const commandData: ForceCloseCommandData = {
+11 -14
View File
@@ -34,24 +34,21 @@ function addSpacesToCheckboxes() {
child.properties &&
child.properties["data-type"] === "taskItem"
) {
const liElement = child as HASTElement;
const liElement = child;
// Find the label and div elements
const label = liElement.children?.find(
(c) => c.type === "element" && (c as HASTElement).tagName === "label"
) as HASTElement | undefined;
const label = liElement.children?.find((c) => c.type === "element" && c.tagName === "label") as
| HASTElement
| undefined;
const contentDiv = liElement.children?.find(
(c) => c.type === "element" && (c as HASTElement).tagName === "div"
) as HASTElement | undefined;
const contentDiv = liElement.children?.find((c) => c.type === "element" && c.tagName === "div") as
| HASTElement
| undefined;
if (label && contentDiv) {
// Find the checkbox input
const checkbox = label.children?.find(
(c) =>
c.type === "element" &&
(c as HASTElement).tagName === "input" &&
(c as HASTElement).properties?.type === "checkbox"
(c) => c.type === "element" && c.tagName === "input" && c.properties?.type === "checkbox"
) as HASTElement | undefined;
if (checkbox) {
@@ -59,9 +56,9 @@ function addSpacesToCheckboxes() {
const textContent: ElementContent[] = [];
if (contentDiv.children) {
for (const child of contentDiv.children) {
if (child.type === "element" && (child as HASTElement).tagName === "p") {
if (child.type === "element" && child.tagName === "p") {
// Unwrap paragraph - add its children directly
const pElement = child as HASTElement;
const pElement = child;
if (pElement.children) {
textContent.push(...pElement.children);
}
@@ -81,7 +78,7 @@ function addSpacesToCheckboxes() {
}
}
} else if (child && child.type === "element") {
helper(child as HASTElement);
helper(child);
}
}
};
+2 -2
View File
@@ -11,7 +11,7 @@ import { serverAgentManager } from "@/agents/server-agent";
* @param param0
*/
export const onStateless = async ({ payload, document, connection }: onStatelessPayload) => {
const payloadStr = payload as string;
const payloadStr = payload;
// Function to safely parse JSON without throwing exceptions
const safeJsonParse = (str: string) => {
@@ -26,7 +26,7 @@ export const onStateless = async ({ payload, document, connection }: onStateless
const documentEvent = DocumentCollaborativeEvents[payload as TDocumentEventsServer]?.client;
if (documentEvent) {
const eventType = documentEvent as keyof EventToPayloadMap;
const eventType = documentEvent;
let eventData: Partial<EventToPayloadMap[typeof eventType]> = {
user_id: connection.context.userId,
-1
View File
@@ -1,4 +1,3 @@
// eslint-disable-next-line import/order
import { setupSentry } from "./instrument";
setupSentry();
+2 -2
View File
@@ -1,7 +1,7 @@
import type { Hocuspocus } from "@hocuspocus/server";
import { createRealtimeEvent } from "@plane/editor";
import { logger } from "@plane/logger";
import type { FetchPayloadWithContext, StorePayloadWithContext } from "@/types";
import type { HocusPocusServerContext } from "@/types";
import { broadcastMessageToPage } from "./broadcast-message";
// Helper to broadcast error to frontend
@@ -10,7 +10,7 @@ export const broadcastError = async (
pageId: string,
errorMessage: string,
errorType: "fetch" | "store",
context: FetchPayloadWithContext["context"] | StorePayloadWithContext["context"],
context: HocusPocusServerContext,
errorCode?: "content_too_large" | "page_locked" | "page_archived",
shouldDisconnect?: boolean
) => {
@@ -130,5 +130,5 @@ export const getTransformedCustomFieldValues = (
export const getTransformedComments = (entities: AsanaEntity): Partial<ExIssueComment>[] => {
const issueComments = entities.comments.map((comment) => transformComments(comment, entities.users));
return issueComments.filter(Boolean) as Partial<ExIssueComment>[];
return issueComments.filter(Boolean);
};
@@ -131,7 +131,7 @@ export class ClickUpAdditionalDataMigrator extends TaskHandler {
* Sometimes, we're getting multiple messages being injected for the same page.
* We should lock the page to prevent same page being pulled multiple times.
*/
const lock = new Lock(this.store!, {
const lock = new Lock(this.store, {
type: "custom",
lockKey: `clickup_pull_${job.id}_${job.config.team.id}_${job.config.folder.id}_${page}`,
ttl: 15 * 60, // 15 minutes TTL
@@ -57,7 +57,7 @@ export class AppController {
const { workspaceId } = req.params;
try {
const allConnections = await integrationConnectionHelper.getWorkspaceConnections({
workspace_id: workspaceId as string,
workspace_id: workspaceId,
});
// Extract unique connection types
@@ -403,7 +403,7 @@ export default class GithubController {
const { github_code, encoded_github_state } = githubState;
const authState: GithubUserAuthState = JSON.parse(Buffer.from(encoded_github_state as string, "base64").toString());
const authState: GithubUserAuthState = JSON.parse(Buffer.from(encoded_github_state, "base64").toString());
let redirectUri = `${env.APP_BASE_URL}/${authState.workspace_slug}/settings/integrations/github/`;
if (authState.profile_redirect) {
@@ -412,7 +412,7 @@ export default class GithubController {
try {
const { response, state } = await githubAuthService.getUserAccessToken({
code: github_code as string,
code: github_code,
state: authState,
});
+5 -5
View File
@@ -21,7 +21,7 @@ export const getConnDetailsForGithubToPlaneSync = async (props: {
const { wsAdminCredentials: credentials, isEnterprise, type, repositoryId, planeProjectId } = props;
// Get the workspace connection for the installation
const workspaceConnection = await apiClient.workspaceConnection.listWorkspaceConnections({
workspace_id: credentials.workspace_id!,
workspace_id: credentials.workspace_id,
credential_id: credentials.id,
});
@@ -30,7 +30,7 @@ export const getConnDetailsForGithubToPlaneSync = async (props: {
}
const entityConnections = await apiClient.workspaceEntityConnection.listWorkspaceEntityConnections({
workspace_id: credentials.workspace_id!,
workspace_id: credentials.workspace_id,
entity_type: isEnterprise ? E_INTEGRATION_KEYS.GITHUB_ENTERPRISE : E_INTEGRATION_KEYS.GITHUB,
type: type,
});
@@ -87,9 +87,9 @@ export const getConnDetailsForPlaneToGithubSync = async (
const credentials = await apiClient.workspaceCredential.getWorkspaceCredential(workspaceConnection.credential_id);
return {
credentials: credentials as TWorkspaceCredential,
entityConnection: entityConnection as TGithubEntityConnection,
workspaceConnection: workspaceConnection as TGithubWorkspaceConnection,
credentials: credentials,
entityConnection: entityConnection,
workspaceConnection: workspaceConnection,
};
};
@@ -245,7 +245,7 @@ export const transformGitHubComment = async (
githubService,
});
comment_html = replaceIssueNumber(comment_html!, repository);
comment_html = replaceIssueNumber(comment_html, repository);
comment_html = replaceMentionedGhUsers(comment_html, workspaceSlug, userMap, planeUsers);
return {
@@ -15,7 +15,7 @@ type GithubWebhookInstallationDeleted = GithubWebhookPayload["webhook-installati
export const handleInstallationEvents = async (action: string, data: unknown): Promise<boolean> => {
switch (action) {
case "deleted": {
await handleInstallationDeletion(data as unknown as GithubWebhookInstallationDeleted);
await handleInstallationDeletion(data as GithubWebhookInstallationDeleted);
return true;
}
default: {
@@ -71,7 +71,7 @@ export const syncCommentWithPlane = async (
const { workspaceConnection, entityConnectionForRepository: entityConnection } =
await getConnDetailsForGithubToPlaneSync({
wsAdminCredentials: wsAdminCredentials as TWorkspaceCredential,
wsAdminCredentials: wsAdminCredentials,
type: EGithubEntityConnectionType.PROJECT_ISSUE_SYNC,
repositoryId: data.repository.id.toString(),
isEnterprise: data.isEnterprise,
@@ -91,11 +91,7 @@ export const syncCommentWithPlane = async (
let planeClient: PlaneClient = await getPlaneAPIClient(wsAdminCredentials, ghIntegrationKey);
const ghService = getGithubService(
workspaceConnection as TGithubWorkspaceConnection,
data.installation?.id.toString(),
data.isEnterprise
);
const ghService = getGithubService(workspaceConnection, data.installation?.id.toString(), data.isEnterprise);
const commentHtml = await ghService.getCommentHtml(
data.repository.owner.login,
data.repository.name,
@@ -62,7 +62,7 @@ export const syncIssueWithPlane = async (store: Store, action: IssueWebhookActio
const { workspaceConnection, entityConnectionForRepository: entityConnection } =
await getConnDetailsForGithubToPlaneSync({
wsAdminCredentials: wsAdminCredentials as TWorkspaceCredential,
wsAdminCredentials: wsAdminCredentials,
isEnterprise: data.isEnterprise,
type: EGithubEntityConnectionType.PROJECT_ISSUE_SYNC,
repositoryId: data.repositoryId.toString(),
@@ -77,11 +77,7 @@ export const syncIssueWithPlane = async (store: Store, action: IssueWebhookActio
let issue: ExIssue | null = null;
const ghService = getGithubService(
workspaceConnection as TGithubWorkspaceConnection,
data.installationId.toString(),
data.isEnterprise
);
const ghService = getGithubService(workspaceConnection, data.installationId.toString(), data.isEnterprise);
const ghIssue = await ghService.getIssue(data.owner, data.repositoryName, Number(data.issueNumber));
const bodyHtml = await ghService.getBodyHtml(data.owner, data.repositoryName, Number(data.issueNumber));
// replace the issue body with the html body
@@ -181,7 +177,7 @@ export const syncIssueWithPlane = async (store: Store, action: IssueWebhookActio
return l.id;
}
})
.filter((l) => l !== undefined) as string[];
.filter((l) => l !== undefined);
}
if (planeIssue.created_by) {
@@ -12,7 +12,7 @@ import { getPlaneAPIClient } from "@/helpers/plane-api-client";
import { PullRequestBehaviour } from "@/lib/behaviours";
export const handlePullRequestEvents = async (action: PullRequestWebhookActions, data: unknown) => {
await handlePullRequestOpened(data as unknown as GithubPullRequestDedupPayload);
await handlePullRequestOpened(data as GithubPullRequestDedupPayload);
return true;
};
@@ -44,7 +44,7 @@ const handlePullRequestOpened = async (data: GithubPullRequestDedupPayload) => {
// Get the workspace connection for the installation
// get all entity connections for the installation and do pr automation on them
const { workspaceConnection, allEntityConnections } = await getConnDetailsForGithubToPlaneSync({
wsAdminCredentials: wsAdminCredentials as TWorkspaceCredential,
wsAdminCredentials: wsAdminCredentials,
type: EGithubEntityConnectionType.PROJECT_PR_AUTOMATION,
isEnterprise: data.isEnterprise,
});
@@ -55,7 +55,7 @@ const handlePullRequestOpened = async (data: GithubPullRequestDedupPayload) => {
// Create the pull request service based on the type of integration
let pullRequestService: GithubIntegrationService;
if (data.isEnterprise) {
const appConfig = (workspaceConnection as TGithubWorkspaceConnection)?.connection_data?.appConfig;
const appConfig = workspaceConnection?.connection_data?.appConfig;
if (!appConfig) {
logger.error("[PULL-REQUEST] GitHub Enterprise app config not found", {
installationId: data.installationId,
@@ -107,11 +107,7 @@ const handleCommentSync = async (store: Store, payload: PlaneWebhookPayload) =>
return;
}
const githubService = getGithubService(
workspaceConnection as TGithubWorkspaceConnection,
credentials.source_access_token,
payload.isEnterprise
);
const githubService = getGithubService(workspaceConnection, credentials.source_access_token, payload.isEnterprise);
const comment = await planeClient.issueComment.getComment(
entityConnection.workspace_slug,
@@ -188,11 +184,7 @@ const createOrUpdateGitHubComment = async (
let userGithubService = githubService;
if (userCredential?.source_access_token) {
userGithubService = getGithubUserService(
workspaceConnection as TGithubWorkspaceConnection,
userCredential.source_access_token,
isEnterprise
);
userGithubService = getGithubUserService(workspaceConnection, userCredential.source_access_token, isEnterprise);
}
if (comment.external_id && comment.external_source && comment.external_source === ghIntegrationKey) {
@@ -77,11 +77,7 @@ const handleIssueSync = async (store: Store, payload: PlaneWebhookPayload) => {
const planeClient = await getPlaneAPIClient(credentials, ghIntegrationKey);
// Create or update issue in GitHub
const githubService = getGithubService(
workspaceConnection as TGithubWorkspaceConnection,
credentials.source_access_token,
payload.isEnterprise
);
const githubService = getGithubService(workspaceConnection, credentials.source_access_token, payload.isEnterprise);
const issue = await planeClient.issue.getIssue(entityConnection.workspace_slug, payload.project, payload.id);
@@ -185,11 +181,7 @@ const createOrUpdateGitHubIssue = async (
// If the user has a credential, create a new github service for the user
if (userCredential?.source_access_token) {
githubUserService = getGithubUserService(
workspaceConnection as TGithubWorkspaceConnection,
userCredential.source_access_token,
isEnterprise
);
githubUserService = getGithubUserService(workspaceConnection, userCredential.source_access_token, isEnterprise);
}
// If the issue has already been created with the external source as GITHUB, update the issue
@@ -217,7 +217,7 @@ export default class GitlabEnterpriseController {
});
}
const appConfig = wsConnection.connection_data.appConfig as TGitlabAppConfig;
const appConfig = wsConnection.connection_data.appConfig;
const gitlabClientService = await getGitlabClientService(
entityConnection.workspace_id,
@@ -146,9 +146,7 @@ export default class GitlabController {
const { gitlab_code, encoded_gitlab_state } = gitlabState;
const gitlabAuthState: GitLabAuthorizeState = JSON.parse(
Buffer.from(encoded_gitlab_state as string, "base64").toString()
);
const gitlabAuthState: GitLabAuthorizeState = JSON.parse(Buffer.from(encoded_gitlab_state, "base64").toString());
const redirectUri = `${env.APP_BASE_URL}/${gitlabAuthState.workspace_slug}/settings/integrations/gitlab/`;
try {
@@ -159,7 +157,7 @@ export default class GitlabController {
});
const { response: token, state: authState } = await gitlabAuthService.getAccessToken({
code: gitlab_code as string,
code: gitlab_code,
state: encoded_gitlab_state,
});
@@ -48,7 +48,7 @@ export const handleMergeRequest = async (data: GitlabMergeRequestEvent) => {
source_access_token: access_token,
source_refresh_token: refresh_token,
workspace_id: workspaceConnection.workspace_id,
user_id: credentials.user_id!,
user_id: credentials.user_id,
});
};
@@ -358,7 +358,7 @@ async function fetchJiraResources(axiosInstance: AxiosInstance, credentials: TWo
if (isRetry) {
throw new JiraApiError("Invalid access token", 401);
} else {
return await refreshAndRetry(credentials.workspace_id!, credentials.user_id!, credentials, axiosInstance);
return await refreshAndRetry(credentials.workspace_id, credentials.user_id, credentials, axiosInstance);
}
}
throw error;
@@ -119,7 +119,7 @@ export const createJiraClient = (
isPAT: false,
accessToken: credentials.source_access_token!,
refreshToken: credentials.source_refresh_token!,
cloudId: job.config?.resource.id as string,
cloudId: job.config?.resource.id,
refreshTokenFunc: jiraAuth.getRefreshToken.bind(jiraAuth),
refreshTokenCallback: refreshTokenCallback,
});
@@ -129,9 +129,9 @@ export const createJiraClient = (
}
return new JiraService({
isPAT: true,
patToken: credentials.source_access_token!,
patToken: credentials.source_access_token,
hostname: credentials.source_hostname,
userEmail: credentials.source_auth_email!,
userEmail: credentials.source_auth_email,
});
}
};
@@ -98,7 +98,7 @@ export const createJiraClient = (
return new JiraV2Service({
email: credentials.source_auth_email,
patToken: credentials.source_access_token!,
patToken: credentials.source_access_token,
hostname: credentials.source_hostname,
authenticationType,
});
@@ -192,7 +192,7 @@ export class JiraCyclesStep implements IStep {
// Store mappings: sprint_external_id -> cycle_id
const mappings = created
?.map((c) => ({
externalId: c.external_id!,
externalId: c.external_id,
planeId: c.id,
}))
.filter((m) => m.externalId && m.planeId);
@@ -273,7 +273,7 @@ export class JiraIssuePropertiesStep implements IStep {
const mappings = properties
.filter((prop) => prop.external_id && prop.id)
.map((prop) => ({
externalId: prop.external_id!,
externalId: prop.external_id,
planeId: prop.id!,
}));
@@ -282,9 +282,9 @@ export class JiraIssuePropertiesStep implements IStep {
// Store raw data including original Jira fields for options step
const propertiesData: TIssuePropertiesData = properties.map((prop) => ({
id: prop.id!,
external_id: prop.external_id!,
display_name: prop.display_name!,
property_type: prop.property_type!,
external_id: prop.external_id,
display_name: prop.display_name,
property_type: prop.property_type,
relation_type: prop.relation_type,
}));
@@ -93,7 +93,7 @@ export class JiraIssuePropertyOptionsStep implements IStep {
transformIssueFieldOptions({ resourceId, projectId: job.project_id, source: this.source }, option)
) || []
)
.filter(Boolean) as Partial<ExIssuePropertyOption>[];
.filter(Boolean);
logger.info(`[${job.id}] [${this.name}] Transformed options`, {
jobId: job.id,
@@ -245,7 +245,7 @@ export class JiraIssuePropertyOptionsStep implements IStep {
const mappings = options
.filter((option) => option.external_id && option.id)
.map((option) => ({
externalId: option.external_id!,
externalId: option.external_id,
planeId: option.id!,
}));
@@ -316,7 +316,7 @@ export class JiraIssueTypesStep implements IStep {
// Store mappings: external_id -> issue_type_id
const validIssueTypes = issueTypes.filter((type) => type.external_id && type.id);
const mappings = validIssueTypes.map((type) => ({
externalId: type.external_id!,
externalId: type.external_id,
planeId: type.id!,
}));
@@ -325,7 +325,7 @@ export class JiraIssueTypesStep implements IStep {
// Store raw issue types data for dependent steps
const issueTypesData: TIssueTypesData = validIssueTypes.map((type) => ({
id: type.id!,
external_id: type.external_id!,
external_id: type.external_id,
name: type.name || "",
is_default: type.is_default || false,
is_epic: type.is_epic || false,
@@ -134,7 +134,7 @@ export class JiraModulesStep implements IStep {
.filter((module) => module.external_id && module.id)
.map((module) => ({
externalId: module.external_id,
planeId: module.id!,
planeId: module.id,
}));
await storage.storeMapping(job.id, this.name, mappings);
@@ -275,13 +275,13 @@ export class JiraUsersStep implements IStep {
? [
{
externalId: email,
planeId: user.id!,
planeId: user.id,
},
]
: []),
{
externalId: displayName,
planeId: user.id!,
planeId: user.id,
},
];
});
@@ -136,7 +136,7 @@ export const getTransformedDocuments = async (
userMap: userMap,
};
const pages = await Promise.all(documents.map((document) => transformDocument(document as LinearDocument, options)));
const pages = await Promise.all(documents.map((document) => transformDocument(document, options)));
return pages;
};
@@ -173,5 +173,5 @@ export const getTransformedProjects = (job: TImportJob<LinearConfig>, entities:
};
});
return modules as Partial<ExModule>[];
return modules;
};
@@ -98,7 +98,7 @@ export abstract class NotionMigratorBase extends TaskHandler {
return JSON.parse(credentials) as TWorkspaceCredential;
}
const credentialsData = await getJobCredentials(job as TImportJob);
const credentialsData = await getJobCredentials(job);
this.store.set(credentialsKey, JSON.stringify(credentialsData), 60 * 60 * 4); // 4 hours
return credentialsData;
}
@@ -131,7 +131,7 @@ export abstract class NotionMigratorBase extends TaskHandler {
// Get the services required for the migration
const zipManager = await this.getZipManager(fileId);
const client = await this.getPlaneClient(job as TImportJob);
const zipDriver = await this.getZipDriver(zipManager, type as EZipDriverType);
const zipDriver = await this.getZipDriver(zipManager, type);
// Determine the current node to process
let currentNode: TZipFileNode | undefined = data.node;
@@ -233,7 +233,7 @@ export abstract class NotionMigratorBase extends TaskHandler {
* @throws Error if access token is not available
*/
async getPlaneClient(job: TImportJob): Promise<Client> {
const credentials = await this.getCachesJobCredentials(job as TImportJob);
const credentials = await this.getCachesJobCredentials(job);
if (!credentials?.target_access_token) {
throw new Error(`Job ${job.id} has no target access token`);
}
@@ -124,11 +124,11 @@ export class SentryAlertHandler implements ISentryTaskHandler {
const state = sentryEventAlert.data.issue_alert.settings.find((setting) => setting.name === "state");
if (assigneeIds?.value && !Array.isArray(assigneeIds.value)) {
assigneeIds.value = [assigneeIds.value as string];
assigneeIds.value = [assigneeIds.value];
}
if (labels?.value && !Array.isArray(labels.value)) {
labels.value = [labels.value as string];
labels.value = [labels.value];
}
return {
@@ -275,9 +275,7 @@ export default class SlackController {
const { slack_code, encoded_slack_state } = slackState;
const authState = JSON.parse(
Buffer.from(encoded_slack_state as string, "base64").toString("utf-8")
) as SlackUserAuthState;
const authState = JSON.parse(Buffer.from(encoded_slack_state, "base64").toString("utf-8")) as SlackUserAuthState;
let redirectUri = `${env.APP_BASE_URL}/${authState.workspaceSlug}/settings/integrations/slack/`;
if (authState.profileRedirect) {
redirectUri = `${env.APP_BASE_URL}/${authState.workspaceSlug}/settings/account/connections/?workspaceId=${authState.workspaceId}`;
@@ -285,7 +283,7 @@ export default class SlackController {
try {
const { state, response } = await slackAuth.getUserAuthToken({
code: slack_code as string,
code: slack_code,
state: authState,
});
@@ -44,8 +44,8 @@ export const getConnectionDetails = async (
// Create admin-based SlackService that we can use regardless of user credential state
const refreshHandler = getRefreshCredentialHandler(
workspaceConnection.workspace_id,
adminCredentials.user_id as string,
adminCredentials.target_access_token as string
adminCredentials.user_id,
adminCredentials.target_access_token
);
const slackService = createSlackService(
@@ -130,7 +130,7 @@ export const findPlaneUserId = async (
slackUser: { id: string; email?: string }
): Promise<string | null> => {
// Check for the userId in the workspace connection map
const config = workspaceConnection.config as TSlackWorkspaceConnectionConfig;
const config = workspaceConnection.config;
let planeUser: string | null = null;
@@ -190,7 +190,7 @@ export const updateUserMap = async (
slackUserId: string | null
): Promise<void> => {
const existingConfig = workspaceConnection.config || {};
const existingUserMap = (existingConfig as TSlackWorkspaceConnectionConfig)?.userMap || [];
const existingUserMap = existingConfig?.userMap || [];
// If both IDs are null, no changes needed
if (!planeUserId && !slackUserId) return;
// Filter out any existing mappings that match either ID being removed
@@ -21,7 +21,6 @@ export type IssueModalViewFull = {
};
export type IssueModalViewBlocks = (
| StaticSelectInputBlock
| StaticSelectInputBlock
| PlainTextInputBlock
| RichTextInputBlock
@@ -73,7 +73,7 @@ export const createCycles = async (
workspaceSlug,
projectId,
cycleId,
cycleIssueIds.filter((issue: string | undefined) => issue !== undefined) as string[]
cycleIssueIds.filter((issue: string | undefined) => issue !== undefined)
);
} catch (error) {
logger.error(`[${jobId.slice(0, 7)}] Error while adding issues to the cycle: ${cycle.name}`, error);
@@ -82,7 +82,7 @@ export const createOrUpdateIssueProperties = async (
// Process all issue properties in batches of 5
const createdUpdatedIssueProperties = await processBatchPromises(issueProperties, processIssueProperty, 2);
return createdUpdatedIssueProperties.filter((property) => property !== undefined) as ExIssueProperty[];
return createdUpdatedIssueProperties.filter((property) => property !== undefined);
};
export const createOrUpdateIssuePropertiesOptions = async (
@@ -145,5 +145,5 @@ export const createOrUpdateIssuePropertiesOptions = async (
2
);
return createdUpdatedIssuePropertiesOptions.filter((option) => option !== undefined) as ExIssuePropertyOption[];
return createdUpdatedIssuePropertiesOptions.filter((option) => option !== undefined);
};
@@ -64,5 +64,5 @@ export const createOrUpdateIssueTypes = async (props: TCreateOrUpdateIssueTypes)
const createdUpdatedIssueTypes = await processBatchPromises(issueTypes, createOrUpdateIssueType, 2);
return createdUpdatedIssueTypes.filter((issueType) => issueType !== undefined) as ExIssueType[];
return createdUpdatedIssueTypes.filter((issueType) => issueType !== undefined);
};
@@ -61,13 +61,13 @@ export const createIssuesWithParent = async (payload: IssueWithParentPayload): P
// If the parent issue is not found, then try to find the issue from
// external id and source from the api
try {
const parent = (await protect(
const parent = await protect(
planeClient.issue.getIssueWithExternalId.bind(planeClient.issue),
workspaceSlug,
projectId,
issue.parent,
issue.external_source
)) as ExIssue;
);
issue.parent = parent.id;
} catch (error) {
logger.error("Error while fetching the parent issue", error);
@@ -588,7 +588,7 @@ export const createOrUpdateIssue = async (
logger.info(
`[${issue.external_source}][${issue.external_id.slice(0, 5)}...][${meta.batchId}] Created Issue: ${issue.external_id.slice(0, 7)} ----------- [${issueProcessIndex} / ${meta.batch_end}][${meta.total.issues}]`
);
return createdIssue as ExIssue;
return createdIssue;
} catch (error) {
if (AssertAPIErrorResponse(error)) {
// Update the issue if the issue already exist
@@ -959,7 +959,7 @@ const getPlaneIssueLabels = (issue: ExIssue, planeLabels: ExIssueLabel[]): strin
return createdLabel.id;
}
})
.filter((label) => label !== undefined) as string[];
.filter((label) => label !== undefined);
}
return [];
};
@@ -33,5 +33,5 @@ export const createLabelsForIssues = async (
};
const createdLabels = await processBatchPromises(labels, createOrUpdateLabel, 2);
return createdLabels.filter((label) => label !== undefined) as ExIssueLabel[];
return createdLabels.filter((label) => label !== undefined);
};
@@ -48,7 +48,7 @@ export const createProjects = async (
const createdProjects = await processBatchPromises(projects, createProject, 2);
return createdProjects.filter((project) => project !== undefined) as ExProject[];
return createdProjects.filter((project) => project !== undefined);
};
export const enableIssueTypeForProject = async (
@@ -59,5 +59,5 @@ export const createStates = async (
// batch the state creation
const createdStates = await processBatchPromises(states, createState, 2);
return createdStates.filter((state) => state !== undefined) as TCreateState[];
return createdStates.filter((state) => state !== undefined);
};
+1 -1
View File
@@ -75,6 +75,6 @@ export async function getConnectionDetails<T extends TWorkspaceConnection, Z ext
return {
workspaceConnection: workspaceConnection as T,
entityConnection: entityConnection as Z,
credential: credential as TWorkspaceCredential,
credential: credential,
};
}
+1 -1
View File
@@ -74,5 +74,5 @@ export const getJobCredentials = async (job: TImportJob): Promise<TWorkspaceCred
if (!credentials || credentials.length === 0) {
throw new Error(`Credentials not available for job ${job.workspace_id}`);
}
return credentials[0] as TWorkspaceCredential;
return credentials[0];
};
+2 -2
View File
@@ -15,7 +15,7 @@ export const removeSpanAroundImg = (htmlContent: string): string => {
const imgTags = root.querySelectorAll("img");
imgTags.forEach((img) => {
const parent = img.parentNode as HTMLElement;
const parent = img.parentNode;
// Check if the parent is a <span> tag
if (parent && parent.tagName === "SPAN") {
@@ -47,7 +47,7 @@ export const splitStringTillPart = (input: string, part: string): string => {
return "/" + result;
};
export const downloadFile = async (url: string, authToken?: string | undefined): Promise<Blob | undefined> => {
export const downloadFile = async (url: string, authToken?: string): Promise<Blob | undefined> => {
try {
const response = await axios({
url,
@@ -294,7 +294,7 @@ export class PullRequestBehaviour {
prDetails.repository.owner,
prDetails.repository.name,
prDetails.number.toString()
) as Promise<IGitComment[]>;
);
}
/**
+1 -1
View File
@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable @typescript-eslint/no-wrapper-object-types */
/* eslint-disable @typescript-eslint/no-unsafe-function-type */
import "reflect-metadata";
// external middlewares
import type { E_INTEGRATION_KEYS } from "@plane/types";
@@ -51,7 +51,7 @@ export class OptionFormFieldsService {
const baseField = {
id: `${issueTypeId}:${property.id}`,
name: property.displayName ?? "",
type: property.propertyType as PropertyTypeEnum,
type: property.propertyType,
required: property.isRequired ?? false,
visible: property.isActive ?? true,
order: property.sortOrder ?? 0,
+1 -1
View File
@@ -368,7 +368,7 @@ export class OAuthController {
client_id: planeAppClientId,
client_secret: planeAppClientSecret,
grant_type: EOAuthGrantType.AUTHORIZATION_CODE,
code: planeOAuthCode as string,
code: planeOAuthCode,
redirect_uri: `${env.SILO_API_BASE_URL}${env.SILO_BASE_PATH}/api/oauth/${providerUrlSlug}/plane-oauth/callback`,
app_installation_id: credential.target_identifier as string,
user_id: authState.user_id,
+1 -1
View File
@@ -16,7 +16,7 @@ export const convertProviderToIntegrationKey = (provider: string): E_INTEGRATION
export const convertIntegrationKeyToProvider = (integrationKey: E_INTEGRATION_KEYS): string => {
// Validate if the integration key is a valid E_INTEGRATION_KEYS
if (!Object.values(E_INTEGRATION_KEYS).includes(integrationKey as E_INTEGRATION_KEYS)) {
if (!Object.values(E_INTEGRATION_KEYS).includes(integrationKey)) {
throw new Error(`Invalid integration key: ${integrationKey}`);
}
// Convert "GITHUB" to "github"
@@ -47,7 +47,7 @@ export class GithubEnterpriseStrategy implements OAuthStrategy {
if (!state.config_key) {
throw new Error(E_SILO_ERROR_CODES.INVALID_APP_CREDENTIALS.toString());
}
const githubAuthService = await this.getGithubAuthService(state.config_key as string);
const githubAuthService = await this.getGithubAuthService(state.config_key);
return githubAuthService.getAuthUrl(state);
}
@@ -63,7 +63,7 @@ export class GithubEnterpriseStrategy implements OAuthStrategy {
// add the config key to the state to be used in getUserAuthUrl and handleUserCallback
state.config_key = configKey;
const githubAuthService = await this.getGithubAuthService(state.config_key as string);
const githubAuthService = await this.getGithubAuthService(state.config_key);
return githubAuthService.getUserAuthUrl(state);
}
@@ -71,7 +71,7 @@ export class GithubEnterpriseStrategy implements OAuthStrategy {
code: string,
state: string
): Promise<{ stateBuffer: string; redirectUri?: string }> {
const authState: GithubUserAuthState = JSON.parse(Buffer.from(state as string, "base64").toString());
const authState: GithubUserAuthState = JSON.parse(Buffer.from(state, "base64").toString());
let redirectUri = `${env.APP_BASE_URL}/${authState.workspace_slug}/settings/integrations/github-enterprise/`;
if (authState.profile_redirect) {
@@ -79,8 +79,8 @@ export class GithubEnterpriseStrategy implements OAuthStrategy {
}
const githubState: GithubPlaneOAuthState = {
github_code: code as string,
encoded_github_state: state as string,
github_code: code,
encoded_github_state: state,
};
const stateBuffer = Buffer.from(JSON.stringify(githubState)).toString("base64");
@@ -101,11 +101,11 @@ export class GithubEnterpriseStrategy implements OAuthStrategy {
throw new Error(E_SILO_ERROR_CODES.INVALID_INSTALLATION_ACCOUNT.toString());
}
const authState: GithubAuthorizeState = JSON.parse(Buffer.from(state as string, "base64").toString());
const authState: GithubAuthorizeState = JSON.parse(Buffer.from(state, "base64").toString());
const redirectUri = `${env.APP_BASE_URL}/${authState.workspace_slug}/settings/integrations/github-enterprise/`;
// Create github service from the installation id
const service = await this.getGithubService(installation_id as string, authState.config_key as string);
const service = await this.getGithubService(installation_id, authState.config_key as string);
// Get the installation details
const installation = await service.getInstallation(Number(installation_id));
@@ -120,7 +120,7 @@ export class GithubEnterpriseStrategy implements OAuthStrategy {
response: {
identifier: installation.data.account.id.toString(),
authorization_type: ESourceAuthorizationType.TOKEN,
access_token: installation_id as string,
access_token: installation_id,
connection_id: installation.data.account.id.toString(),
// @ts-expect-error - Ignoring ts error for dynamic key assignment
connection_slug: installation.data.account.login,
@@ -144,13 +144,11 @@ export class GithubEnterpriseStrategy implements OAuthStrategy {
async handlePlaneOAuthCallback(
encodedIntegrationState: string
): Promise<{ response: OAuthTokenResponse; state: OAuthState; redirectUri?: string }> {
const githubState: GithubPlaneOAuthState = JSON.parse(
Buffer.from(encodedIntegrationState as string, "base64").toString()
);
const githubState: GithubPlaneOAuthState = JSON.parse(Buffer.from(encodedIntegrationState, "base64").toString());
const { github_code: code, encoded_github_state } = githubState;
const authState: GithubUserAuthState = JSON.parse(Buffer.from(encoded_github_state as string, "base64").toString());
const authState: GithubUserAuthState = JSON.parse(Buffer.from(encoded_github_state, "base64").toString());
let redirectUri = `${env.APP_BASE_URL}/${authState.workspace_slug}/settings/integrations/github-enterprise/`;
@@ -160,7 +158,7 @@ export class GithubEnterpriseStrategy implements OAuthStrategy {
const githubAuthService = await this.getGithubAuthService(authState.config_key as string);
const { response, state: githubUserState } = await githubAuthService.getUserAccessToken({
code: code as string,
code: code,
state: authState,
});
@@ -204,7 +202,7 @@ export class GithubEnterpriseStrategy implements OAuthStrategy {
}
const githubService = getGithubService(
wsConnection as TGithubWorkspaceConnection,
wsCredential.source_access_token as string,
wsCredential.source_access_token,
true
);
const installation = await githubService.getInstallation(Number(wsCredential.source_access_token));
@@ -43,7 +43,7 @@ export class GitlabEnterpriseStrategy implements OAuthStrategy {
if (!state.config_key) {
throw new Error(E_SILO_ERROR_CODES.INVALID_APP_CREDENTIALS.toString());
}
const gitlabAuthService = await this.getGitlabAuthService(state.config_key as string);
const gitlabAuthService = await this.getGitlabAuthService(state.config_key);
return gitlabAuthService.getAuthUrl(state);
}
@@ -56,15 +56,15 @@ export class GitlabEnterpriseStrategy implements OAuthStrategy {
throw new Error(E_SILO_ERROR_CODES.INVALID_INSTALLATION_ACCOUNT.toString());
}
const authState: GitLabAuthorizeState = JSON.parse(Buffer.from(state as string, "base64").toString());
const authState: GitLabAuthorizeState = JSON.parse(Buffer.from(state, "base64").toString());
const redirectUri = getIntegrationPageUrl(authState.workspace_slug, this.integrationKey);
// Create gitlab auth service
const gitlabAuthService = await this.getGitlabAuthService(authState.config_key as string);
const { response: tokenResponse } = await gitlabAuthService.getAccessToken({
code: code as string,
state: state as string,
code: code,
state: state,
});
if (!tokenResponse || !tokenResponse.access_token) {
@@ -33,7 +33,7 @@ export class SentryOAuthStrategy implements OAuthStrategy {
state: string,
additionalParams: Record<string, string>
): Promise<{ response: OAuthTokenResponse; state: OAuthState; redirectUri?: string }> {
const sentryAuthState: SentryAuthState = JSON.parse(Buffer.from(state as string, "base64").toString());
const sentryAuthState: SentryAuthState = JSON.parse(Buffer.from(state, "base64").toString());
const installationId = additionalParams.installationId;
const org = additionalParams.orgSlug;
-1
View File
@@ -1,4 +1,3 @@
/* eslint-disable import/order */
import * as Sentry from "@sentry/react-router";
import { startTransition, StrictMode } from "react";
import { hydrateRoot } from "react-dom/client";
+1 -3
View File
@@ -1,12 +1,10 @@
"use client";
import { observer } from "mobx-react";
// hooks
import { usePublish } from "@/hooks/store/publish";
import CreateIssueModal from "@/plane-web/components/intake/create/create-issue-modal";
import type { Route } from "./+types/page";
const IssuesPage = observer((props: Route.ComponentProps) => {
const IssuesPage = observer(function IssuesPage(props: Route.ComponentProps) {
const { params } = props;
const { anchor } = params;
// params
@@ -1,11 +1,9 @@
"use client";
import { observer } from "mobx-react";
import CreateTypeFormModal from "@/plane-web/components/intake/create/create-type-form-modal";
import { useIntake } from "@/plane-web/hooks/store/use-intake";
import type { Route } from "./+types/page";
const TypeFormPage = observer((props: Route.ComponentProps) => {
const TypeFormPage = observer(function TypeFormPage(props: Route.ComponentProps) {
const { params } = props;
const { anchor } = params;
-2
View File
@@ -1,5 +1,3 @@
"use client";
import useSWR from "swr";
// hooks
import { useMember } from "@/hooks/store/use-member";
+1 -3
View File
@@ -1,5 +1,3 @@
"use client";
import { observer } from "mobx-react";
import { useParams, useSearchParams } from "next/navigation";
// components
@@ -9,7 +7,7 @@ import { usePublish } from "@/hooks/store/publish";
// plane-web
import { ViewLayoutsRoot } from "@/plane-web/components/issue-layouts/root";
const ViewsPage = observer(() => {
const ViewsPage = observer(function ViewsPage() {
// params
const params = useParams<{ anchor: string }>();
const { anchor } = params;
@@ -11,7 +11,7 @@ interface Props {
subGroupId: string | undefined,
isSubGroupCumulative: boolean
) => number | undefined;
getIssueLoader: (groupId?: string | undefined, subGroupId?: string | undefined) => TLoader;
getIssueLoader: (groupId?: string, subGroupId?: string) => TLoader;
}
export const IssueLayoutHOC = observer(function IssueLayoutHOC(props: Props) {
@@ -37,7 +37,7 @@ export interface IKanBan {
isSubGroupCumulative: boolean
) => number | undefined;
getPaginationData: (groupId: string | undefined, subGroupId: string | undefined) => TPaginationData | undefined;
getIssueLoader: (groupId?: string | undefined, subGroupId?: string | undefined) => TLoader;
getIssueLoader: (groupId?: string, subGroupId?: string) => TLoader;
scrollableContainerRef?: MutableRefObject<HTMLDivElement | null>;
showEmptyGroup?: boolean;
}
@@ -29,7 +29,7 @@ interface IKanbanGroup {
isSubGroupCumulative: boolean
) => number | undefined;
getPaginationData: (groupId: string | undefined, subGroupId: string | undefined) => TPaginationData | undefined;
getIssueLoader: (groupId?: string | undefined, subGroupId?: string | undefined) => TLoader;
getIssueLoader: (groupId?: string, subGroupId?: string) => TLoader;
scrollableContainerRef?: MutableRefObject<HTMLDivElement | null>;
}
@@ -37,7 +37,7 @@ export interface IKanBanSwimLanes {
isSubGroupCumulative: boolean
) => number | undefined;
getPaginationData: (groupId: string | undefined, subGroupId: string | undefined) => TPaginationData | undefined;
getIssueLoader: (groupId?: string | undefined, subGroupId?: string | undefined) => TLoader;
getIssueLoader: (groupId?: string, subGroupId?: string) => TLoader;
showEmptyGroup: boolean;
scrollableContainerRef?: MutableRefObject<HTMLDivElement | null>;
orderBy: TIssueOrderByOptions | undefined;
@@ -163,7 +163,7 @@ interface ISubGroupSwimlane extends ISubGroupSwimlaneHeader {
isSubGroupCumulative: boolean
) => number | undefined;
getPaginationData: (groupId: string | undefined, subGroupId: string | undefined) => TPaginationData | undefined;
getIssueLoader: (groupId?: string | undefined, subGroupId?: string | undefined) => TLoader;
getIssueLoader: (groupId?: string, subGroupId?: string) => TLoader;
scrollableContainerRef?: MutableRefObject<HTMLDivElement | null>;
loadMoreIssues: (groupId?: string, subGroupId?: string) => void;
}
@@ -220,7 +220,7 @@ interface ISubGroup {
isSubGroupCumulative: boolean
) => number | undefined;
getPaginationData: (groupId: string | undefined, subGroupId: string | undefined) => TPaginationData | undefined;
getIssueLoader: (groupId?: string | undefined, subGroupId?: string | undefined) => TLoader;
getIssueLoader: (groupId?: string, subGroupId?: string) => TLoader;
scrollableContainerRef?: MutableRefObject<HTMLDivElement | null>;
loadMoreIssues: (groupId?: string, subGroupId?: string) => void;
}
@@ -32,7 +32,7 @@ export interface IList {
isSubGroupCumulative: boolean
) => number | undefined;
getPaginationData: (groupId: string | undefined, subGroupId: string | undefined) => TPaginationData | undefined;
getIssueLoader: (groupId?: string | undefined, subGroupId?: string | undefined) => TLoader;
getIssueLoader: (groupId?: string, subGroupId?: string) => TLoader;
}
export const List = observer(function List(props: IList) {
@@ -32,7 +32,7 @@ interface Props {
isSubGroupCumulative: boolean
) => number | undefined;
getPaginationData: (groupId: string | undefined, subGroupId: string | undefined) => TPaginationData | undefined;
getIssueLoader: (groupId?: string | undefined, subGroupId?: string | undefined) => TLoader;
getIssueLoader: (groupId?: string, subGroupId?: string) => TLoader;
}
// List loader component
@@ -1,5 +1,3 @@
"use client";
import { observer } from "mobx-react";
// plane ui
import { StateGroupIcon } from "@plane/propel/icons";
@@ -41,7 +41,7 @@ export const getGroupByColumns = (
case "labels":
return getLabelsColumns(label) as any;
case "assignees":
return getAssigneeColumns(member) as any;
return getAssigneeColumns(member);
case "created_by":
return getCreatedByColumns(member) as any;
default:
@@ -62,7 +62,7 @@ const getCycleColumns = (cycleStore: ICycleStore): IGroupByColumn[] | undefined
cycleGroups.push({
id: cycle.id,
name: cycle.name,
icon: <CycleGroupIcon cycleGroup={cycleStatus as TCycleGroups} className="h-3.5 w-3.5" />,
icon: <CycleGroupIcon cycleGroup={cycleStatus} className="h-3.5 w-3.5" />,
payload: { cycle_id: cycle.id },
});
}
@@ -193,11 +193,8 @@ export const getDisplayPropertiesCount = (
return count;
};
export const getIssueBlockId = (
issueId: string | undefined,
groupId: string | undefined,
subGroupId?: string | undefined
) => `issue_${issueId}_${groupId}_${subGroupId}`;
export const getIssueBlockId = (issueId: string | undefined, groupId: string | undefined, subGroupId?: string) =>
`issue_${issueId}_${groupId}_${subGroupId}`;
/**
* returns empty Array if groupId is None
@@ -6,7 +6,7 @@ const useClipboardWritePermission = () => {
useEffect(() => {
const checkClipboardWriteAccess = () => {
navigator.permissions
//eslint-disable-next-line no-undef
.query({ name: "clipboard-write" as PermissionName })
.then((result) => {
if (result.state === "granted") {
@@ -32,7 +32,6 @@ export const useIntersectionObserver = (
observer.observe(elementRef);
return () => {
if (elementRef) {
// eslint-disable-next-line react-hooks/exhaustive-deps
observer.unobserve(elementRef);
}
};
@@ -105,15 +105,15 @@ export abstract class BaseIssuesStore implements IBaseIssuesStore {
const allIssues = groupedIssueIds[ALL_ISSUES] ?? [];
if (allIssues && Array.isArray(allIssues)) {
return allIssues as string[];
return allIssues;
}
if (groupId && groupedIssueIds?.[groupId] && Array.isArray(groupedIssueIds[groupId])) {
return (groupedIssueIds[groupId] ?? []) as string[];
return groupedIssueIds[groupId] ?? [];
}
if (groupId && subGroupId) {
return ((groupedIssueIds as TSubGroupedIssues)[groupId]?.[subGroupId] ?? []) as string[];
return (groupedIssueIds as TSubGroupedIssues)[groupId]?.[subGroupId] ?? [];
}
return undefined;
@@ -445,7 +445,7 @@ export abstract class BaseIssuesStore implements IBaseIssuesStore {
// if groupedIssueIds is an array, update the `groupedIssueIds` store at the issuePath
if (groupedIssueIds && Array.isArray(groupedIssueIds)) {
update(this, ["groupedIssueIds", ...issuePath], (issueIds: string[] = []) =>
uniq(concat(issueIds, groupedIssueIds as string[]))
uniq(concat(issueIds, groupedIssueIds))
);
// return true to indicate the store has been updated
return true;
@@ -8,7 +8,7 @@ export type TEditorMentionComponentProps = TCallbackMentionComponentProps & {
getMentionDetails?: (mentionType: TEditorMentionType, entityId: string) => TEditorMentionItem | undefined;
};
export const EditorAdditionalMentionsRoot: React.FC<TEditorMentionComponentProps> = (props) => {
export function EditorAdditionalMentionsRoot(props: TEditorMentionComponentProps) {
const { entity_name } = props;
switch (entity_name) {
@@ -17,4 +17,4 @@ export const EditorAdditionalMentionsRoot: React.FC<TEditorMentionComponentProps
default:
return null;
}
};
}
@@ -8,7 +8,7 @@ type Props = {
workItemDetails: TEditorWorkItemMention;
};
export const EditorWorkItemMentionContent: React.FC<Props> = observer((props) => {
export const EditorWorkItemMentionContent = observer(function EditorWorkItemMentionContent(props: Props) {
const { workItemDetails } = props;
// derived values
const trimmedName =
@@ -9,7 +9,7 @@ type Props = {
stateGroup: TStateGroups;
};
export const EditorWorkItemMentionLogo: React.FC<Props> = observer((props) => {
export const EditorWorkItemMentionLogo = observer(function EditorWorkItemMentionLogo(props: Props) {
const { className, stateColor, stateGroup } = props;
return <StateGroupIcon stateGroup={stateGroup} color={stateColor} className={className} />;
@@ -7,7 +7,7 @@ type Props = {
workItemDetails: TEditorWorkItemMention;
};
export const EditorWorkItemMentionPreview: React.FC<Props> = observer((props) => {
export const EditorWorkItemMentionPreview = observer(function EditorWorkItemMentionPreview(props: Props) {
const { workItemDetails } = props;
return (
@@ -6,7 +6,7 @@ import type { TEditorMentionComponentProps } from "../root";
import { EditorWorkItemMentionContent } from "./content";
import { EditorWorkItemMentionPreview } from "./preview";
export const EditorWorkItemMention: React.FC<TEditorMentionComponentProps> = observer((props) => {
export const EditorWorkItemMention = observer(function EditorWorkItemMention(props: TEditorMentionComponentProps) {
const { entity_identifier: workItemId, getMentionDetails } = props;
// derived values
const workItemDetails = getMentionDetails?.("issue_mention", workItemId);
@@ -18,7 +18,7 @@ export const EmbedHandler: React.FC<ExternalEmbedNodeViewProps> = memo(
))
);
const EmbedHandlerRender: React.FC<ExternalEmbedNodeViewProps> = observer((props) => {
const EmbedHandlerRender = observer(function EmbedHandlerRender(props: ExternalEmbedNodeViewProps) {
const { node } = props;
const {
src,
@@ -12,13 +12,13 @@ import type { ChartDataType, IGanttBlock } from "../types";
type Props = {
blockId: string;
getBlockById: (id: string, currentViewData?: ChartDataType | undefined) => IGanttBlock | undefined;
getBlockById: (id: string, currentViewData?: ChartDataType) => IGanttBlock | undefined;
showAllBlocks: boolean;
blockToRender: (data: any) => React.ReactNode;
ganttContainerRef: React.RefObject<HTMLDivElement>;
};
export const GanttChartBlock: React.FC<Props> = observer((props) => {
export const GanttChartBlock = observer(function GanttChartBlock(props: Props) {
const { blockId, getBlockById, showAllBlocks, blockToRender, ganttContainerRef } = props;
// store hooks
const { currentViewData, updateActiveBlockId, isBlockActive } = useGanttChart();
@@ -10,13 +10,13 @@ import { GanttChartBlock } from "./block";
export type GanttChartBlocksProps = {
itemsContainerWidth: number;
blockIds: string[];
getBlockById: (id: string, currentViewData?: ChartDataType | undefined) => IGanttBlock | undefined;
getBlockById: (id: string, currentViewData?: ChartDataType) => IGanttBlock | undefined;
blockToRender: (data: any) => React.ReactNode;
ganttContainerRef: React.RefObject<HTMLDivElement>;
showAllBlocks: boolean;
};
export const GanttChartBlocksList: FC<GanttChartBlocksProps> = (props) => {
export function GanttChartBlocksList(props: GanttChartBlocksProps) {
const { itemsContainerWidth, blockIds, blockToRender, getBlockById, ganttContainerRef, showAllBlocks } = props;
return (
@@ -39,4 +39,4 @@ export const GanttChartBlocksList: FC<GanttChartBlocksProps> = (props) => {
))}
</div>
);
};
}
@@ -7,7 +7,7 @@ type Props = {
toggleFullScreenMode: () => void;
};
export const GanttChartHeader: React.FC<Props> = observer((props) => {
export const GanttChartHeader = observer(function GanttChartHeader(props: Props) {
const { fullScreenMode, handleToday, toggleFullScreenMode } = props;
// chart hook
@@ -21,7 +21,7 @@ import { useGanttChart } from "../hooks/use-gantt-chart";
type Props = {
blockIds: string[];
getBlockById: (id: string, currentViewData?: ChartDataType | undefined) => IGanttBlock | undefined;
getBlockById: (id: string, currentViewData?: ChartDataType) => IGanttBlock | undefined;
canLoadMoreBlocks?: boolean;
loadMoreBlocks?: () => void;
blockToRender: (data: any) => React.ReactNode;
@@ -33,7 +33,7 @@ type Props = {
updateCurrentViewRenderPayload: (direction: "left" | "right", currentView: TGanttViews) => void;
};
export const GanttChartMainContent: React.FC<Props> = observer((props) => {
export const GanttChartMainContent = observer(function GanttChartMainContent(props: Props) {
const {
blockIds,
getBlockById,
@@ -20,12 +20,12 @@ type ChartViewRootProps = {
sidebarToRender: (props: any) => React.ReactNode;
bottomSpacing: boolean;
showAllBlocks: boolean;
getBlockById: (id: string, currentViewData?: ChartDataType | undefined) => IGanttBlock | undefined;
getBlockById: (id: string, currentViewData?: ChartDataType) => IGanttBlock | undefined;
loadMoreBlocks?: () => void;
canLoadMoreBlocks?: boolean;
};
export const ChartViewRoot: FC<ChartViewRootProps> = observer((props) => {
export const ChartViewRoot = observer(function ChartViewRoot(props: ChartViewRootProps) {
const {
border,
title,

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