fix: fetch workflows on the backend (#15796)
* fix: fetch workflows on the router * chore: remove workflows * chore: import zod * chore: move to repository
This commit is contained in:
@@ -859,7 +859,7 @@ const EventTypePageWrapper: React.FC<PageProps> & {
|
||||
|
||||
const { data: workflows } = trpc.viewer.workflows.getAllActiveWorkflows.useQuery({
|
||||
eventType: {
|
||||
workflows: eventType.workflows,
|
||||
id: props.type,
|
||||
teamId: eventType.teamId,
|
||||
userId: eventType.userId,
|
||||
parent: eventType.parent,
|
||||
|
||||
@@ -7,6 +7,7 @@ import { getBookingFieldsWithSystemFields } from "@calcom/features/bookings/lib/
|
||||
import { parseBookingLimit, parseDurationLimit, parseRecurringEvent } from "@calcom/lib";
|
||||
import { getUserAvatarUrl } from "@calcom/lib/getAvatarUrl";
|
||||
import { getTranslation } from "@calcom/lib/server/i18n";
|
||||
import { EventTypeRepository } from "@calcom/lib/server/repository/eventType";
|
||||
import { UserRepository } from "@calcom/lib/server/repository/user";
|
||||
import type { PrismaClient } from "@calcom/prisma";
|
||||
import { SchedulingType, MembershipRole } from "@calcom/prisma/enums";
|
||||
@@ -46,216 +47,7 @@ export const getEventTypeById = async ({
|
||||
defaultScheduleId: true,
|
||||
});
|
||||
|
||||
const rawEventType = await prisma.eventType.findFirst({
|
||||
where: {
|
||||
AND: [
|
||||
{
|
||||
OR: [
|
||||
{
|
||||
users: {
|
||||
some: {
|
||||
id: userId,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
team: {
|
||||
members: {
|
||||
some: {
|
||||
userId: userId,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
userId: userId,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: eventTypeId,
|
||||
},
|
||||
],
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
title: true,
|
||||
slug: true,
|
||||
description: true,
|
||||
length: true,
|
||||
isInstantEvent: true,
|
||||
instantMeetingExpiryTimeOffsetInSeconds: true,
|
||||
aiPhoneCallConfig: true,
|
||||
offsetStart: true,
|
||||
hidden: true,
|
||||
locations: true,
|
||||
eventName: true,
|
||||
customInputs: true,
|
||||
timeZone: true,
|
||||
periodType: true,
|
||||
metadata: true,
|
||||
periodDays: true,
|
||||
periodStartDate: true,
|
||||
periodEndDate: true,
|
||||
periodCountCalendarDays: true,
|
||||
lockTimeZoneToggleOnBookingPage: true,
|
||||
requiresConfirmation: true,
|
||||
requiresBookerEmailVerification: true,
|
||||
recurringEvent: true,
|
||||
hideCalendarNotes: true,
|
||||
disableGuests: true,
|
||||
minimumBookingNotice: true,
|
||||
beforeEventBuffer: true,
|
||||
afterEventBuffer: true,
|
||||
slotInterval: true,
|
||||
hashedLink: true,
|
||||
bookingLimits: true,
|
||||
onlyShowFirstAvailableSlot: true,
|
||||
durationLimits: true,
|
||||
assignAllTeamMembers: true,
|
||||
successRedirectUrl: true,
|
||||
forwardParamsSuccessRedirect: true,
|
||||
currency: true,
|
||||
bookingFields: true,
|
||||
useEventTypeDestinationCalendarEmail: true,
|
||||
owner: {
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
},
|
||||
parent: {
|
||||
select: {
|
||||
id: true,
|
||||
teamId: true,
|
||||
},
|
||||
},
|
||||
teamId: true,
|
||||
team: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
slug: true,
|
||||
parentId: true,
|
||||
parent: {
|
||||
select: {
|
||||
slug: true,
|
||||
organizationSettings: {
|
||||
select: {
|
||||
lockEventTypeCreationForUsers: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
members: {
|
||||
select: {
|
||||
role: true,
|
||||
accepted: true,
|
||||
user: {
|
||||
select: {
|
||||
...userSelect,
|
||||
eventTypes: {
|
||||
select: {
|
||||
slug: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
users: {
|
||||
select: userSelect,
|
||||
},
|
||||
schedulingType: true,
|
||||
schedule: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
hosts: {
|
||||
select: {
|
||||
isFixed: true,
|
||||
userId: true,
|
||||
priority: true,
|
||||
},
|
||||
},
|
||||
userId: true,
|
||||
price: true,
|
||||
children: {
|
||||
select: {
|
||||
owner: {
|
||||
select: {
|
||||
avatarUrl: true,
|
||||
name: true,
|
||||
username: true,
|
||||
email: true,
|
||||
id: true,
|
||||
},
|
||||
},
|
||||
hidden: true,
|
||||
slug: true,
|
||||
},
|
||||
},
|
||||
destinationCalendar: true,
|
||||
seatsPerTimeSlot: true,
|
||||
seatsShowAttendees: true,
|
||||
seatsShowAvailabilityCount: true,
|
||||
webhooks: {
|
||||
select: {
|
||||
id: true,
|
||||
subscriberUrl: true,
|
||||
payloadTemplate: true,
|
||||
active: true,
|
||||
eventTriggers: true,
|
||||
secret: true,
|
||||
eventTypeId: true,
|
||||
},
|
||||
},
|
||||
workflows: {
|
||||
include: {
|
||||
workflow: {
|
||||
select: {
|
||||
name: true,
|
||||
id: true,
|
||||
trigger: true,
|
||||
time: true,
|
||||
timeUnit: true,
|
||||
userId: true,
|
||||
teamId: true,
|
||||
team: {
|
||||
select: {
|
||||
id: true,
|
||||
slug: true,
|
||||
name: true,
|
||||
members: true,
|
||||
},
|
||||
},
|
||||
activeOn: {
|
||||
select: {
|
||||
eventType: {
|
||||
select: {
|
||||
id: true,
|
||||
title: true,
|
||||
parentId: true,
|
||||
_count: {
|
||||
select: {
|
||||
children: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
steps: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
secondaryEmailId: true,
|
||||
},
|
||||
});
|
||||
const rawEventType = await EventTypeRepository.findById({ id: eventTypeId, userId });
|
||||
|
||||
if (!rawEventType) {
|
||||
if (isTrpcCall) {
|
||||
|
||||
@@ -194,6 +194,231 @@ export class EventTypeRepository {
|
||||
});
|
||||
}
|
||||
|
||||
static async findById({ id, userId }: { id: number; userId: number }) {
|
||||
const userSelect = Prisma.validator<Prisma.UserSelect>()({
|
||||
name: true,
|
||||
avatarUrl: true,
|
||||
username: true,
|
||||
id: true,
|
||||
email: true,
|
||||
locale: true,
|
||||
defaultScheduleId: true,
|
||||
});
|
||||
|
||||
const CompleteEventTypeSelect = Prisma.validator<Prisma.EventTypeSelect>()({
|
||||
id: true,
|
||||
title: true,
|
||||
slug: true,
|
||||
description: true,
|
||||
length: true,
|
||||
isInstantEvent: true,
|
||||
instantMeetingExpiryTimeOffsetInSeconds: true,
|
||||
aiPhoneCallConfig: true,
|
||||
offsetStart: true,
|
||||
hidden: true,
|
||||
locations: true,
|
||||
eventName: true,
|
||||
customInputs: true,
|
||||
timeZone: true,
|
||||
periodType: true,
|
||||
metadata: true,
|
||||
periodDays: true,
|
||||
periodStartDate: true,
|
||||
periodEndDate: true,
|
||||
periodCountCalendarDays: true,
|
||||
lockTimeZoneToggleOnBookingPage: true,
|
||||
requiresConfirmation: true,
|
||||
requiresBookerEmailVerification: true,
|
||||
recurringEvent: true,
|
||||
hideCalendarNotes: true,
|
||||
disableGuests: true,
|
||||
minimumBookingNotice: true,
|
||||
beforeEventBuffer: true,
|
||||
afterEventBuffer: true,
|
||||
slotInterval: true,
|
||||
hashedLink: true,
|
||||
bookingLimits: true,
|
||||
onlyShowFirstAvailableSlot: true,
|
||||
durationLimits: true,
|
||||
assignAllTeamMembers: true,
|
||||
successRedirectUrl: true,
|
||||
forwardParamsSuccessRedirect: true,
|
||||
currency: true,
|
||||
bookingFields: true,
|
||||
useEventTypeDestinationCalendarEmail: true,
|
||||
owner: {
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
},
|
||||
parent: {
|
||||
select: {
|
||||
id: true,
|
||||
teamId: true,
|
||||
},
|
||||
},
|
||||
teamId: true,
|
||||
team: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
slug: true,
|
||||
parentId: true,
|
||||
parent: {
|
||||
select: {
|
||||
slug: true,
|
||||
organizationSettings: {
|
||||
select: {
|
||||
lockEventTypeCreationForUsers: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
members: {
|
||||
select: {
|
||||
role: true,
|
||||
accepted: true,
|
||||
user: {
|
||||
select: {
|
||||
...userSelect,
|
||||
eventTypes: {
|
||||
select: {
|
||||
slug: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
users: {
|
||||
select: userSelect,
|
||||
},
|
||||
schedulingType: true,
|
||||
schedule: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
hosts: {
|
||||
select: {
|
||||
isFixed: true,
|
||||
userId: true,
|
||||
priority: true,
|
||||
},
|
||||
},
|
||||
userId: true,
|
||||
price: true,
|
||||
children: {
|
||||
select: {
|
||||
owner: {
|
||||
select: {
|
||||
avatarUrl: true,
|
||||
name: true,
|
||||
username: true,
|
||||
email: true,
|
||||
id: true,
|
||||
},
|
||||
},
|
||||
hidden: true,
|
||||
slug: true,
|
||||
},
|
||||
},
|
||||
destinationCalendar: true,
|
||||
seatsPerTimeSlot: true,
|
||||
seatsShowAttendees: true,
|
||||
seatsShowAvailabilityCount: true,
|
||||
webhooks: {
|
||||
select: {
|
||||
id: true,
|
||||
subscriberUrl: true,
|
||||
payloadTemplate: true,
|
||||
active: true,
|
||||
eventTriggers: true,
|
||||
secret: true,
|
||||
eventTypeId: true,
|
||||
},
|
||||
},
|
||||
workflows: {
|
||||
include: {
|
||||
workflow: {
|
||||
select: {
|
||||
name: true,
|
||||
id: true,
|
||||
trigger: true,
|
||||
time: true,
|
||||
timeUnit: true,
|
||||
userId: true,
|
||||
teamId: true,
|
||||
team: {
|
||||
select: {
|
||||
id: true,
|
||||
slug: true,
|
||||
name: true,
|
||||
members: true,
|
||||
},
|
||||
},
|
||||
activeOn: {
|
||||
select: {
|
||||
eventType: {
|
||||
select: {
|
||||
id: true,
|
||||
title: true,
|
||||
parentId: true,
|
||||
_count: {
|
||||
select: {
|
||||
children: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
steps: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
secondaryEmailId: true,
|
||||
});
|
||||
|
||||
return await prisma.eventType.findFirst({
|
||||
where: {
|
||||
AND: [
|
||||
{
|
||||
OR: [
|
||||
{
|
||||
users: {
|
||||
some: {
|
||||
id: userId,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
team: {
|
||||
members: {
|
||||
some: {
|
||||
userId: userId,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
userId: userId,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id,
|
||||
},
|
||||
],
|
||||
},
|
||||
select: CompleteEventTypeSelect,
|
||||
});
|
||||
}
|
||||
|
||||
static async findAllByTeamIdIncludeManagedEventTypes({ teamId }: { teamId?: number }) {
|
||||
return await prisma.eventType.findMany({
|
||||
where: {
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { TrpcSessionUser } from "@calcom/trpc/server/trpc";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
|
||||
import type { TGetAllActiveWorkflowsInputSchema } from "./getAllActiveWorkflows.schema";
|
||||
import { getAllWorkflowsFromEventType } from "./util";
|
||||
import { getAllWorkflowsFromEventType, getEventTypeWorkflows } from "./util";
|
||||
|
||||
type GetAllActiveWorkflowsOptions = {
|
||||
ctx: {
|
||||
@@ -15,6 +15,14 @@ type GetAllActiveWorkflowsOptions = {
|
||||
|
||||
export const getAllActiveWorkflowsHandler = async ({ input, ctx }: GetAllActiveWorkflowsOptions) => {
|
||||
const { eventType } = input;
|
||||
const workflows = await getEventTypeWorkflows(ctx.user.id, eventType.id);
|
||||
const completeEventType = {
|
||||
workflows,
|
||||
teamId: eventType.teamId,
|
||||
userId: eventType.userId,
|
||||
parent: eventType.parent,
|
||||
metadata: eventType.metadata,
|
||||
};
|
||||
|
||||
if (eventType.userId && eventType.userId !== ctx.user.id) {
|
||||
throw new TRPCError({
|
||||
@@ -32,7 +40,7 @@ export const getAllActiveWorkflowsHandler = async ({ input, ctx }: GetAllActiveW
|
||||
if (!team) throw new TRPCError({ code: "UNAUTHORIZED" });
|
||||
}
|
||||
|
||||
const allActiveWorkflows = await getAllWorkflowsFromEventType(eventType, eventType.userId);
|
||||
const allActiveWorkflows = await getAllWorkflowsFromEventType(completeEventType, eventType.userId);
|
||||
|
||||
return allActiveWorkflows;
|
||||
};
|
||||
|
||||
@@ -32,14 +32,16 @@ const ZWorkflow = z.object({
|
||||
.array(),
|
||||
});
|
||||
|
||||
export const ZWorkflows = z
|
||||
.object({
|
||||
workflow: ZWorkflow,
|
||||
})
|
||||
.array()
|
||||
.optional();
|
||||
|
||||
export const ZGetAllActiveWorkflowsInputSchema = z.object({
|
||||
eventType: z.object({
|
||||
workflows: z
|
||||
.object({
|
||||
workflow: ZWorkflow,
|
||||
})
|
||||
.array()
|
||||
.optional(),
|
||||
id: z.number(),
|
||||
teamId: z.number().optional().nullable(),
|
||||
parent: z
|
||||
.object({
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { Workflow } from "@prisma/client";
|
||||
import type { z } from "zod";
|
||||
|
||||
import { isSMSOrWhatsappAction } from "@calcom/ee/workflows/lib/actionHelperFunctions";
|
||||
import { getAllWorkflows } from "@calcom/ee/workflows/lib/getAllWorkflows";
|
||||
@@ -25,6 +26,7 @@ import { SENDER_ID, SENDER_NAME } from "@calcom/lib/constants";
|
||||
import getOrgIdFromMemberOrTeamId from "@calcom/lib/getOrgIdFromMemberOrTeamId";
|
||||
import { getTeamIdFromEventType } from "@calcom/lib/getTeamIdFromEventType";
|
||||
import logger from "@calcom/lib/logger";
|
||||
import { EventTypeRepository } from "@calcom/lib/server/repository/eventType";
|
||||
import { getTimeFormatStringFromUserTimeFormat } from "@calcom/lib/timeFormat";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma, WorkflowStep } from "@calcom/prisma/client";
|
||||
@@ -40,6 +42,8 @@ import { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
|
||||
|
||||
import { TRPCError } from "@trpc/server";
|
||||
|
||||
import type { ZWorkflows } from "./getAllActiveWorkflows.schema";
|
||||
|
||||
const log = logger.getSubLogger({ prefix: ["workflow"] });
|
||||
|
||||
export const bookingSelect = {
|
||||
@@ -804,3 +808,11 @@ export async function getAllWorkflowsFromEventType(
|
||||
|
||||
return allWorkflows;
|
||||
}
|
||||
|
||||
export const getEventTypeWorkflows = async (
|
||||
userId: number,
|
||||
eventTypeId: number
|
||||
): Promise<z.infer<typeof ZWorkflows>> => {
|
||||
const rawEventType = await EventTypeRepository.findById({ id: eventTypeId, userId });
|
||||
return rawEventType?.workflows;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user