Compare commits
2 Commits
main
...
fix-tsWarn
Author | SHA1 | Date |
---|---|---|
GitStart-Cal.com | 236959ab17 | |
gitstart-calcom | a6d7b8975a |
|
@ -2,7 +2,7 @@ import type { GetServerSideProps } from "next";
|
|||
|
||||
import { csp } from "@lib/csp";
|
||||
|
||||
export type WithNonceProps<T extends Record<string, any>> = T & {
|
||||
export type WithNonceProps<T extends Record<string, unknown>> = T & {
|
||||
nonce?: string;
|
||||
};
|
||||
|
||||
|
@ -11,7 +11,7 @@ export type WithNonceProps<T extends Record<string, any>> = T & {
|
|||
* Note that if the Components are not adding any script tag then this is not needed. Even in absence of this, Document.getInitialProps would be able to generate nonce itself which it needs to add script tags common to all pages
|
||||
* There is no harm in wrapping a `getServerSideProps` fn with this even if it doesn't add any script tag.
|
||||
*/
|
||||
export default function withNonce<T extends Record<string, any>>(
|
||||
export default function withNonce<T extends Record<string, unknown>>(
|
||||
getServerSideProps: GetServerSideProps<T>
|
||||
): GetServerSideProps<WithNonceProps<T>> {
|
||||
return async (context) => {
|
||||
|
|
|
@ -28,6 +28,7 @@ MyApp.getInitialProps = async (ctx: AppContextType) => {
|
|||
|
||||
if (req) {
|
||||
const { getLocale } = await import("@calcom/features/auth/lib/getLocale");
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
newLocale = await getLocale(req as IncomingMessage & { cookies: Record<string, any> });
|
||||
} else if (typeof window !== "undefined" && window.calNewLocale) {
|
||||
newLocale = window.calNewLocale;
|
||||
|
|
|
@ -32,7 +32,8 @@ class MyDocument extends Document<Props> {
|
|||
|
||||
const newLocale =
|
||||
ctx.req && getLocaleModule
|
||||
? await getLocaleModule.getLocale(ctx.req as IncomingMessage & { cookies: Record<string, any> })
|
||||
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
await getLocaleModule.getLocale(ctx.req as IncomingMessage & { cookies: Record<string, any> })
|
||||
: "en";
|
||||
|
||||
const asPath = ctx.asPath || "";
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import { useSession } from "next-auth/react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
|
|
|
@ -907,6 +907,7 @@ const EventTypesPage = () => {
|
|||
const searchParams = useSearchParams();
|
||||
const { open } = useIntercom();
|
||||
const { data: user } = useMeQuery();
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [showProfileBanner, setShowProfileBanner] = useState(false);
|
||||
const orgBranding = useOrgBranding();
|
||||
const routerQuery = useRouterQuery();
|
||||
|
@ -919,12 +920,6 @@ const EventTypesPage = () => {
|
|||
staleTime: 1 * 60 * 60 * 1000,
|
||||
});
|
||||
|
||||
function closeBanner() {
|
||||
setShowProfileBanner(false);
|
||||
document.cookie = `calcom-profile-banner=1;max-age=${60 * 60 * 24 * 90}`; // 3 months
|
||||
showToast(t("we_wont_show_again"), "success");
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (searchParams?.get("openIntercom") === "true") {
|
||||
open();
|
||||
|
|
|
@ -13,9 +13,7 @@ test.describe("Payment app", () => {
|
|||
const user = await users.create();
|
||||
await user.apiLogin();
|
||||
const paymentEvent = user.eventTypes.find((item) => item.slug === "paid");
|
||||
if (!paymentEvent) {
|
||||
throw new Error("No payment event found");
|
||||
}
|
||||
expect(paymentEvent).not.toBeNull();
|
||||
await prisma.credential.create({
|
||||
data: {
|
||||
type: "alby_payment",
|
||||
|
@ -30,7 +28,7 @@ test.describe("Payment app", () => {
|
|||
},
|
||||
});
|
||||
|
||||
await page.goto(`event-types/${paymentEvent.id}?tabName=apps`);
|
||||
await page.goto(`event-types/${paymentEvent?.id}?tabName=apps`);
|
||||
|
||||
await page.locator("#event-type-form").getByRole("switch").click();
|
||||
await page.getByPlaceholder("Price").click();
|
||||
|
@ -38,7 +36,7 @@ test.describe("Payment app", () => {
|
|||
await page.getByText("SatoshissatsCurrencyBTCPayment optionCollect payment on booking").click();
|
||||
await page.getByTestId("update-eventtype").click();
|
||||
|
||||
await page.goto(`${user.username}/${paymentEvent.slug}`);
|
||||
await page.goto(`${user.username}/${paymentEvent?.slug}`);
|
||||
|
||||
// expect 200 sats to be displayed in page
|
||||
expect(await page.locator("text=200 sats").first()).toBeTruthy();
|
||||
|
@ -55,9 +53,7 @@ test.describe("Payment app", () => {
|
|||
const user = await users.create();
|
||||
await user.apiLogin();
|
||||
const paymentEvent = user.eventTypes.find((item) => item.slug === "paid");
|
||||
if (!paymentEvent) {
|
||||
throw new Error("No payment event found");
|
||||
}
|
||||
expect(paymentEvent).not.toBeNull();
|
||||
await prisma.credential.create({
|
||||
data: {
|
||||
type: "stripe_payment",
|
||||
|
@ -75,7 +71,7 @@ test.describe("Payment app", () => {
|
|||
},
|
||||
});
|
||||
|
||||
await page.goto(`event-types/${paymentEvent.id}?tabName=apps`);
|
||||
await page.goto(`event-types/${paymentEvent?.id}?tabName=apps`);
|
||||
await page.locator("#event-type-form").getByRole("switch").click();
|
||||
await page.locator(".text-black > .bg-default > div > div:nth-child(2)").first().click();
|
||||
await page.getByTestId("select-option-usd").click();
|
||||
|
@ -84,7 +80,7 @@ test.describe("Payment app", () => {
|
|||
await page.getByTestId("price-input-stripe").fill("350");
|
||||
await page.getByTestId("update-eventtype").click();
|
||||
|
||||
await page.goto(`${user.username}/${paymentEvent.slug}`);
|
||||
await page.goto(`${user.username}/${paymentEvent?.slug}`);
|
||||
|
||||
// expect 200 sats to be displayed in page
|
||||
expect(await page.locator("text=350").first()).toBeTruthy();
|
||||
|
@ -101,9 +97,7 @@ test.describe("Payment app", () => {
|
|||
const user = await users.create();
|
||||
await user.apiLogin();
|
||||
const paymentEvent = user.eventTypes.find((item) => item.slug === "paid");
|
||||
if (!paymentEvent) {
|
||||
throw new Error("No payment event found");
|
||||
}
|
||||
expect(paymentEvent).not.toBeNull();
|
||||
await prisma.credential.create({
|
||||
data: {
|
||||
type: "paypal_payment",
|
||||
|
@ -116,7 +110,7 @@ test.describe("Payment app", () => {
|
|||
},
|
||||
});
|
||||
|
||||
await page.goto(`event-types/${paymentEvent.id}?tabName=apps`);
|
||||
await page.goto(`event-types/${paymentEvent?.id}?tabName=apps`);
|
||||
|
||||
await page.locator("#event-type-form").getByRole("switch").click();
|
||||
|
||||
|
@ -131,7 +125,7 @@ test.describe("Payment app", () => {
|
|||
await page.getByText("$MXNCurrencyMexican pesoPayment option").click();
|
||||
await page.getByTestId("update-eventtype").click();
|
||||
|
||||
await page.goto(`${user.username}/${paymentEvent.slug}`);
|
||||
await page.goto(`${user.username}/${paymentEvent?.slug}`);
|
||||
|
||||
// expect 150 to be displayed in page
|
||||
expect(await page.locator("text=MX$150.00").first()).toBeTruthy();
|
||||
|
@ -149,9 +143,7 @@ test.describe("Payment app", () => {
|
|||
const user = await users.create();
|
||||
await user.apiLogin();
|
||||
const paymentEvent = user.eventTypes.find((item) => item.slug === "paid");
|
||||
if (!paymentEvent) {
|
||||
throw new Error("No payment event found");
|
||||
}
|
||||
expect(paymentEvent).not.toBeNull();
|
||||
await prisma.credential.create({
|
||||
data: {
|
||||
type: "alby_payment",
|
||||
|
@ -160,7 +152,7 @@ test.describe("Payment app", () => {
|
|||
},
|
||||
});
|
||||
|
||||
await page.goto(`event-types/${paymentEvent.id}?tabName=apps`);
|
||||
await page.goto(`event-types/${paymentEvent?.id}?tabName=apps`);
|
||||
|
||||
await page.locator("#event-type-form").getByRole("switch").click();
|
||||
|
||||
|
@ -177,9 +169,7 @@ test.describe("Payment app", () => {
|
|||
const user = await users.create();
|
||||
await user.apiLogin();
|
||||
const paymentEvent = user.eventTypes.find((item) => item.slug === "paid");
|
||||
if (!paymentEvent) {
|
||||
throw new Error("No payment event found");
|
||||
}
|
||||
expect(paymentEvent).not.toBeNull();
|
||||
await prisma.credential.create({
|
||||
data: {
|
||||
type: "paypal_payment",
|
||||
|
@ -188,7 +178,7 @@ test.describe("Payment app", () => {
|
|||
},
|
||||
});
|
||||
|
||||
await page.goto(`event-types/${paymentEvent.id}?tabName=apps`);
|
||||
await page.goto(`event-types/${paymentEvent?.id}?tabName=apps`);
|
||||
|
||||
await page.locator("#event-type-form").getByRole("switch").click();
|
||||
|
||||
|
@ -211,9 +201,7 @@ test.describe("Payment app", () => {
|
|||
await user.apiLogin();
|
||||
// Any event should work here
|
||||
const paymentEvent = user.eventTypes.find((item) => item.slug === "paid");
|
||||
if (!paymentEvent) {
|
||||
throw new Error("No payment event found");
|
||||
}
|
||||
expect(paymentEvent).not.toBeNull();
|
||||
|
||||
await prisma.credential.create({
|
||||
data: {
|
||||
|
@ -225,7 +213,7 @@ test.describe("Payment app", () => {
|
|||
},
|
||||
});
|
||||
|
||||
await page.goto(`event-types/${paymentEvent.id}?tabName=apps`);
|
||||
await page.goto(`event-types/${paymentEvent?.id}?tabName=apps`);
|
||||
|
||||
await page.locator("#event-type-form").getByRole("switch").click();
|
||||
// make sure Tracking ID is displayed
|
||||
|
|
|
@ -252,6 +252,7 @@ test.describe("Reschedule Tests", async () => {
|
|||
let firstOfNextMonth = dayjs().add(1, "month").startOf("month");
|
||||
|
||||
// find first available slot of next month (available monday-friday)
|
||||
// eslint-disable-next-line playwright/no-conditional-in-test
|
||||
while (firstOfNextMonth.day() < 1 || firstOfNextMonth.day() > 5) {
|
||||
firstOfNextMonth = firstOfNextMonth.add(1, "day");
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import prismaMock from "../../../../tests/libs/__mocks__/prismaMock";
|
||||
|
||||
import type { EventType } from "@prisma/client";
|
||||
|
@ -97,7 +98,6 @@ describe("handleChildrenEventTypes", () => {
|
|||
it("Adds new users", async () => {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line
|
||||
const {
|
||||
schedulingType,
|
||||
id,
|
||||
|
@ -141,7 +141,6 @@ describe("handleChildrenEventTypes", () => {
|
|||
it("Updates old users", async () => {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line
|
||||
const {
|
||||
schedulingType,
|
||||
id,
|
||||
|
@ -237,7 +236,6 @@ describe("handleChildrenEventTypes", () => {
|
|||
it("Deletes existent event types for new users added", async () => {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line
|
||||
const {
|
||||
schedulingType,
|
||||
id,
|
||||
|
@ -282,7 +280,6 @@ describe("handleChildrenEventTypes", () => {
|
|||
it("Deletes existent event types for old users updated", async () => {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line
|
||||
const {
|
||||
schedulingType,
|
||||
id,
|
||||
|
|
|
@ -1020,8 +1020,7 @@ export function mockVideoApp({
|
|||
//@ts-ignore
|
||||
VideoApiAdapter: (credential) => {
|
||||
return {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
createMeeting: (...rest: any[]) => {
|
||||
createMeeting: (...rest: unknown[]) => {
|
||||
if (creationCrash) {
|
||||
throw new Error("MockVideoApiAdapter.createMeeting fake error");
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ export type ParseRefreshTokenResponse<S extends z.ZodTypeAny> =
|
|||
| z.infer<S>
|
||||
| z.infer<typeof minimumTokenResponseSchema>;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const parseRefreshTokenResponse = (response: any, schema: z.ZodTypeAny) => {
|
||||
let refreshTokenResponse;
|
||||
const credentialSyncingEnabled =
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { APP_CREDENTIAL_SHARING_ENABLED } from "@calcom/lib/constants";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const refreshOAuthTokens = async (refreshFunction: () => any, appSlug: string, userId: number | null) => {
|
||||
// Check that app syncing is enabled and that the credential belongs to a user
|
||||
if (APP_CREDENTIAL_SHARING_ENABLED && process.env.CALCOM_CREDENTIAL_SYNC_ENDPOINT && userId) {
|
||||
|
|
|
@ -18,9 +18,11 @@ const EventTypeAppCard: EventTypeAppCardComponent = function EventTypeAppCard({
|
|||
useEffect(() => {
|
||||
setSelectedProject({
|
||||
value: data?.projects.currentProject,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
label: data?.projects?.find((project: any) => project.id === data?.currentProject)?.name,
|
||||
});
|
||||
setProjects(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
data?.projects?.map((project: any) => {
|
||||
return {
|
||||
value: project.id,
|
||||
|
|
|
@ -59,6 +59,7 @@ export default class BasecampCalendarService implements Calendar {
|
|||
|
||||
constructor(credential: CredentialPayload) {
|
||||
this.integrationName = "basecamp3";
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
getAppKeysFromSlug("basecamp3").then(({ user_agent }: any) => {
|
||||
this.userAgent = user_agent as string;
|
||||
});
|
||||
|
|
|
@ -3,6 +3,7 @@ import { router } from "@calcom/trpc/server/trpc";
|
|||
|
||||
import { ZProjectMutationInputSchema } from "./projectMutation.schema";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const UNSTABLE_HANDLER_CACHE: any = {};
|
||||
|
||||
const appBasecamp3 = router({
|
||||
|
|
|
@ -16,6 +16,10 @@ interface ProjectMutationHandlerOptions {
|
|||
input: TProjectMutationInputSchema;
|
||||
}
|
||||
|
||||
interface IDock {
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
export const projectMutationHandler = async ({ ctx, input }: ProjectMutationHandlerOptions) => {
|
||||
const { user_agent } = await getAppKeysFromSlug("basecamp3");
|
||||
const { user, prisma } = ctx;
|
||||
|
@ -48,7 +52,7 @@ export const projectMutationHandler = async ({ ctx, input }: ProjectMutationHand
|
|||
}
|
||||
);
|
||||
const scheduleJson = await scheduleResponse.json();
|
||||
const scheduleId = scheduleJson.dock.find((dock: any) => dock.name === "schedule").id;
|
||||
const scheduleId = scheduleJson.dock.find((dock: IDock) => dock.name === "schedule").id;
|
||||
await prisma.credential.update({
|
||||
where: { id: credential.id },
|
||||
data: { key: { ...credentialKey, projectId: Number(projectId), scheduleId } },
|
||||
|
|
|
@ -48,6 +48,7 @@ const EventTypeAppCard: EventTypeAppCardComponent = function EventTypeAppCard({
|
|||
setAppData("paymentOption", paymentOptions[0].value);
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
return (
|
||||
|
|
|
@ -5,7 +5,6 @@ import z from "zod";
|
|||
import Paypal from "@calcom/app-store/paypal/lib/Paypal";
|
||||
import { WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { CalendarEvent } from "@calcom/types/Calendar";
|
||||
import type { IAbstractPaymentService } from "@calcom/types/PaymentService";
|
||||
|
||||
import { paymentOptionEnum } from "../zod";
|
||||
|
@ -170,10 +169,7 @@ export class PaymentService implements IAbstractPaymentService {
|
|||
throw new Error("Payment could not be created");
|
||||
}
|
||||
}
|
||||
chargeCard(
|
||||
payment: Pick<Prisma.PaymentUncheckedCreateInput, "amount" | "currency">,
|
||||
bookingId: number
|
||||
): Promise<Payment> {
|
||||
chargeCard(): Promise<Payment> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
getPaymentPaidStatus(): Promise<string> {
|
||||
|
@ -182,19 +178,10 @@ export class PaymentService implements IAbstractPaymentService {
|
|||
getPaymentDetails(): Promise<Payment> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
afterPayment(
|
||||
event: CalendarEvent,
|
||||
booking: {
|
||||
user: { email: string | null; name: string | null; timeZone: string } | null;
|
||||
id: number;
|
||||
startTime: { toISOString: () => string };
|
||||
uid: string;
|
||||
},
|
||||
paymentData: Payment
|
||||
): Promise<void> {
|
||||
afterPayment(): Promise<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
deletePayment(paymentId: number): Promise<boolean> {
|
||||
deletePayment(): Promise<boolean> {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { Prisma } from "@prisma/client";
|
||||
|
||||
import { getLocationGroupedOptions } from "@calcom/app-store/server";
|
||||
import type { StripeData } from "@calcom/app-store/stripepayment/lib/server";
|
||||
import { getEventTypeAppData } from "@calcom/app-store/utils";
|
||||
import type { LocationObject } from "@calcom/core/location";
|
||||
import { getBookingFieldsWithSystemFields } from "@calcom/features/bookings/lib/getBookingFields";
|
||||
|
@ -9,7 +8,6 @@ import { parseBookingLimit, parseDurationLimit, parseRecurringEvent } from "@cal
|
|||
import { getUserAvatarUrl } from "@calcom/lib/getAvatarUrl";
|
||||
import { getTranslation } from "@calcom/lib/server/i18n";
|
||||
import type { PrismaClient } from "@calcom/prisma";
|
||||
import type { Credential } from "@calcom/prisma/client";
|
||||
import { SchedulingType, MembershipRole } from "@calcom/prisma/enums";
|
||||
import { customInputSchema, EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
|
||||
|
||||
|
@ -380,19 +378,3 @@ export default async function getEventTypeById({
|
|||
};
|
||||
return finalObj;
|
||||
}
|
||||
|
||||
const getStripeCurrency = (stripeMetadata: { currency: string }, credentials: Credential[]) => {
|
||||
// Favor the currency from the metadata as EventType.currency was not always set and should be deprecated
|
||||
if (stripeMetadata.currency) {
|
||||
return stripeMetadata.currency;
|
||||
}
|
||||
|
||||
// Legacy support for EventType.currency
|
||||
const stripeCredential = credentials.find((integration) => integration.type === "stripe_payment");
|
||||
if (stripeCredential) {
|
||||
return (stripeCredential.key as unknown as StripeData)?.default_currency || "usd";
|
||||
}
|
||||
|
||||
// Fallback to USD but should not happen
|
||||
return "usd";
|
||||
};
|
||||
|
|
|
@ -2,8 +2,6 @@ import { prisma } from "@calcom/prisma";
|
|||
import { MembershipRole } from "@calcom/prisma/enums";
|
||||
import type { TrpcSessionUser } from "@calcom/trpc/server/trpc";
|
||||
|
||||
const ROLES_WITH_EDIT_PERMISSION = [MembershipRole.ADMIN, MembershipRole.OWNER] as MembershipRole[];
|
||||
|
||||
type InputOptions = {
|
||||
ctx: {
|
||||
user: NonNullable<TrpcSessionUser>;
|
||||
|
|
|
@ -96,6 +96,7 @@ export async function getBooking(bookingId: number) {
|
|||
}),
|
||||
organizer: {
|
||||
email: user.email,
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
name: user.name!,
|
||||
timeZone: user.timeZone,
|
||||
timeFormat: getTimeFormatStringFromUserTimeFormat(user.timeFormat),
|
||||
|
|
|
@ -51,7 +51,6 @@ export const integrationsHandler = async ({ ctx, input }: IntegrationsOptions) =
|
|||
extendsFeature,
|
||||
teamId,
|
||||
sortByMostPopular,
|
||||
categories,
|
||||
appId,
|
||||
} = input;
|
||||
let credentials = await getUsersCredentials(user.id);
|
||||
|
|
|
@ -186,7 +186,7 @@ export const listTeamAvailabilityHandler = async ({ ctx, input }: GetOptions) =>
|
|||
let nextCursor: typeof cursor | undefined = undefined;
|
||||
if (teamMembers && teamMembers.length > limit) {
|
||||
const nextItem = teamMembers.pop();
|
||||
nextCursor = nextItem!.id;
|
||||
nextCursor = nextItem?.id;
|
||||
}
|
||||
|
||||
const dateFrom = dayjs(input.startDate).tz(input.loggedInUsersTz).subtract(1, "day");
|
||||
|
|
|
@ -14,7 +14,7 @@ type OAuthRouterHandlerCache = {
|
|||
const UNSTABLE_HANDLER_CACHE: OAuthRouterHandlerCache = {};
|
||||
|
||||
export const oAuthRouter = router({
|
||||
getClient: authedProcedure.input(ZGetClientInputSchema).query(async ({ ctx, input }) => {
|
||||
getClient: authedProcedure.input(ZGetClientInputSchema).query(async ({ input }) => {
|
||||
if (!UNSTABLE_HANDLER_CACHE.getClient) {
|
||||
UNSTABLE_HANDLER_CACHE.getClient = await import("./getClient.handler").then(
|
||||
(mod) => mod.getClientHandler
|
||||
|
|
Loading…
Reference in New Issue