diff --git a/apps/api/v2/src/ee/event-types/event-types_2024_04_15/event-types.repository.ts b/apps/api/v2/src/ee/event-types/event-types_2024_04_15/event-types.repository.ts index 84488df660138f..0a9c6b0d47aca9 100644 --- a/apps/api/v2/src/ee/event-types/event-types_2024_04_15/event-types.repository.ts +++ b/apps/api/v2/src/ee/event-types/event-types_2024_04_15/event-types.repository.ts @@ -1,12 +1,11 @@ +import { getEventTypeById } from "@calcom/platform-libraries/event-types"; +import type { PrismaClient } from "@calcom/prisma"; +import { Injectable } from "@nestjs/common"; import { CreateEventTypeInput_2024_04_15 } from "@/ee/event-types/event-types_2024_04_15/inputs/create-event-type.input"; import { PrismaReadService } from "@/modules/prisma/prisma-read.service"; import { PrismaWriteService } from "@/modules/prisma/prisma-write.service"; import { UsersService } from "@/modules/users/services/users.service"; import { UserWithProfile } from "@/modules/users/users.repository"; -import { Injectable } from "@nestjs/common"; - -import { getEventTypeById } from "@calcom/platform-libraries/event-types"; -import type { PrismaClient } from "@calcom/prisma"; @Injectable() export class EventTypesRepository_2024_04_15 { @@ -54,6 +53,7 @@ export class EventTypesRepository_2024_04_15 { currentOrganizationId: this.usersService.getUserMainOrgId(user), eventTypeId, userId: user.id, + userLocale: user.locale ?? "en", prisma: this.dbRead.prisma as unknown as PrismaClient, isUserOrganizationAdmin, isTrpcCall: true, diff --git a/apps/api/v2/src/modules/atoms/services/event-types-atom.service.ts b/apps/api/v2/src/modules/atoms/services/event-types-atom.service.ts index 3750f2486f0ceb..210d5ec08993c6 100644 --- a/apps/api/v2/src/modules/atoms/services/event-types-atom.service.ts +++ b/apps/api/v2/src/modules/atoms/services/event-types-atom.service.ts @@ -1,42 +1,43 @@ -import { EventTypesService_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/services/event-types.service"; -import { systemBeforeFieldEmail } from "@/ee/event-types/event-types_2024_06_14/transformers"; -import { AtomsRepository } from "@/modules/atoms/atoms.repository"; -import { CredentialsRepository } from "@/modules/credentials/credentials.repository"; -import { MembershipsRepository } from "@/modules/memberships/memberships.repository"; -import { OrganizationsTeamsRepository } from "@/modules/organizations/teams/index/organizations-teams.repository"; -import { PrismaReadService } from "@/modules/prisma/prisma-read.service"; -import { PrismaWriteService } from "@/modules/prisma/prisma-write.service"; -import { TeamsEventTypesService } from "@/modules/teams/event-types/services/teams-event-types.service"; -import { UsersService } from "@/modules/users/services/users.service"; -import { UserWithProfile } from "@/modules/users/users.repository"; -import { Injectable, NotFoundException, ForbiddenException, BadRequestException } from "@nestjs/common"; - -import { checkAdminOrOwner, getClientSecretFromPayment } from "@calcom/platform-libraries"; import type { TeamQuery } from "@calcom/platform-libraries"; -import { enrichUserWithDelegationConferencingCredentialsWithoutOrgId } from "@calcom/platform-libraries/app-store"; -import { getEnabledAppsFromCredentials, getAppFromSlug } from "@calcom/platform-libraries/app-store"; +import { checkAdminOrOwner, getClientSecretFromPayment } from "@calcom/platform-libraries"; import type { App, - TDependencyData, + CredentialDataWithTeamName, CredentialOwner, CredentialPayload, - CredentialDataWithTeamName, LocationOption, + TDependencyData, +} from "@calcom/platform-libraries/app-store"; +import { + enrichUserWithDelegationConferencingCredentialsWithoutOrgId, + getAppFromSlug, + getEnabledAppsFromCredentials, } from "@calcom/platform-libraries/app-store"; -import { type PublicEventType, getPublicEvent } from "@calcom/platform-libraries/event-types"; import { - getEventTypeById, bulkUpdateEventsToDefaultLocation, bulkUpdateTeamEventsToDefaultLocation, - getBulkUserEventTypes, + EventTypeMetaDataSchema, getBulkTeamEventTypes, -} from "@calcom/platform-libraries/event-types"; -import { - updateEventType, + getBulkUserEventTypes, + getEventTypeById, + getPublicEvent, + type PublicEventType, TUpdateEventTypeInputSchema, - EventTypeMetaDataSchema, + updateEventType, } from "@calcom/platform-libraries/event-types"; import type { PrismaClient } from "@calcom/prisma"; +import { BadRequestException, ForbiddenException, Injectable, NotFoundException } from "@nestjs/common"; +import { EventTypesService_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/services/event-types.service"; +import { systemBeforeFieldEmail } from "@/ee/event-types/event-types_2024_06_14/transformers"; +import { AtomsRepository } from "@/modules/atoms/atoms.repository"; +import { CredentialsRepository } from "@/modules/credentials/credentials.repository"; +import { MembershipsRepository } from "@/modules/memberships/memberships.repository"; +import { OrganizationsTeamsRepository } from "@/modules/organizations/teams/index/organizations-teams.repository"; +import { PrismaReadService } from "@/modules/prisma/prisma-read.service"; +import { PrismaWriteService } from "@/modules/prisma/prisma-write.service"; +import { TeamsEventTypesService } from "@/modules/teams/event-types/services/teams-event-types.service"; +import { UsersService } from "@/modules/users/services/users.service"; +import { UserWithProfile } from "@/modules/users/users.repository"; type EnabledAppType = App & { credential: CredentialDataWithTeamName; @@ -81,6 +82,7 @@ export class EventTypesAtomService { currentOrganizationId: this.usersService.getUserMainOrgId(user), eventTypeId, userId: user.id, + userLocale: user.locale ?? "en", prisma: this.dbRead.prisma as unknown as PrismaClient, isUserOrganizationAdmin, isTrpcCall: true, @@ -136,8 +138,6 @@ export class EventTypesAtomService { input: { ...body, id: eventTypeId, bookingFields }, ctx: { user: eventTypeUser, - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore prisma: this.dbWrite.prisma, }, }); @@ -166,8 +166,6 @@ export class EventTypesAtomService { input: { ...body, id: eventTypeId, bookingFields }, ctx: { user: eventTypeUser, - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore prisma: this.dbWrite.prisma, }, }); diff --git a/apps/web/public/static/locales/en/common.json b/apps/web/public/static/locales/en/common.json index bf207402ec9214..0e29c4a136f3e5 100644 --- a/apps/web/public/static/locales/en/common.json +++ b/apps/web/public/static/locales/en/common.json @@ -739,6 +739,7 @@ "booking_reschedule_confirmation": "Reschedule your {{eventTypeTitle}} with {{profileName}}", "in_person_meeting": "In-person meeting", "in_person": "In Person (Organizer Address)", + "in_person_category": "In person", "link_meeting": "Link meeting", "phone_number": "Phone number", "attendee_phone_number": "Attendee phone number", diff --git a/apps/web/public/static/locales/fr/common.json b/apps/web/public/static/locales/fr/common.json index 1a87726ca91fae..b6120cfc8d4325 100644 --- a/apps/web/public/static/locales/fr/common.json +++ b/apps/web/public/static/locales/fr/common.json @@ -719,6 +719,7 @@ "booking_reschedule_confirmation": "Replanifiez votre {{eventTypeTitle}} avec {{profileName}}", "in_person_meeting": "Rendez-vous en personne", "in_person": "En personne (adresse de l'organisateur)", + "in_person_category": "En personne", "link_meeting": "Rendez-vous avec lien", "phone_number": "Numéro de téléphone", "attendee_phone_number": "Numéro de téléphone du participant", diff --git a/packages/app-store/locations.ts b/packages/app-store/locations.ts index 366827f687fd0b..1d25f62dd7216c 100644 --- a/packages/app-store/locations.ts +++ b/packages/app-store/locations.ts @@ -1,20 +1,20 @@ /** * TODO: Consolidate this file with BookingLocationService and add tests */ -import type { TFunction } from "i18next"; -import { isValidPhoneNumber } from "libphonenumber-js/max"; -import { z } from "zod"; import { appStoreMetadata } from "@calcom/app-store/bookerAppsMetaData"; import logger from "@calcom/lib/logger"; import { BookingStatus } from "@calcom/prisma/enums"; import type { Ensure, Optional } from "@calcom/types/utils"; +import type { TFunction } from "i18next"; +import { isValidPhoneNumber } from "libphonenumber-js/max"; +import { z } from "zod"; import type { EventLocationTypeFromAppMeta } from "../types/App"; import { + DailyLocationType as importedDailyLocationType, MeetLocationType as importedMeetLocationType, MSTeamsLocationType as importedMSTeamsLocationType, - DailyLocationType as importedDailyLocationType, } from "./constants"; export const MeetLocationType = importedMeetLocationType; @@ -26,7 +26,7 @@ export type DefaultEventLocationType = { type: DefaultEventLocationTypeEnum; label: string; messageForOrganizer: string; - category: "in person" | "conferencing" | "other" | "phone"; + category: "in_person_category" | "conferencing" | "other" | "phone"; linkType: "static"; supportsCustomLabel?: boolean; @@ -114,7 +114,7 @@ export const defaultLocations: DefaultEventLocationType[] = [ attendeeInputPlaceholder: "enter_address", defaultValueVariable: "attendeeAddress", iconUrl: "/map-pin-dark.svg", - category: "in person", + category: "in_person_category", linkType: "static", supportsCustomLabel: true, }, @@ -143,7 +143,7 @@ export const defaultLocations: DefaultEventLocationType[] = [ variable: "locationAddress", defaultValueVariable: "address", iconUrl: "/map-pin-dark.svg", - category: "in person", + category: "in_person_category", linkType: "static", }, { @@ -242,7 +242,7 @@ for (const [appName, meta] of Object.entries(appStoreMetadata)) { for (const [key, value] of Object.entries(location)) { if (typeof value === "string") { // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore + // @ts-expect-error location[key] = value.replace(/{SLUG}/g, meta.slug).replace(/{TITLE}/g, meta.name); } } @@ -397,7 +397,7 @@ export const getLocationValueForDB = ( eventLocations: LocationObject[] ) => { let bookingLocation = bookingLocationTypeOrValue; - let conferenceCredentialId: number | undefined = undefined; + let conferenceCredentialId: number | undefined; eventLocations.forEach((location) => { if (location.type === bookingLocationTypeOrValue) { @@ -481,8 +481,8 @@ export const getTranslatedLocation = ( const translatedLocation = location.type.startsWith("integrations:") ? eventLocationType.label : translateAbleKeys.includes(locationKey) - ? t(locationKey) - : locationKey; + ? t(locationKey) + : locationKey; return translatedLocation; }; diff --git a/packages/features/eventtypes/lib/getEventTypeById.ts b/packages/features/eventtypes/lib/getEventTypeById.ts index a774c516c4062b..8897a347c0ba7b 100644 --- a/packages/features/eventtypes/lib/getEventTypeById.ts +++ b/packages/features/eventtypes/lib/getEventTypeById.ts @@ -4,7 +4,9 @@ import { getLocationGroupedOptions } from "@calcom/app-store/server"; import { getEventTypeAppData } from "@calcom/app-store/utils"; import { eventTypeMetaDataSchemaWithTypedApps } from "@calcom/app-store/zod-utils"; import { getBookingFieldsWithSystemFields } from "@calcom/features/bookings/lib/getBookingFields"; +import { getOrganizationRepository } from "@calcom/features/ee/organizations/di/OrganizationRepository.container"; import { getBookerBaseUrl } from "@calcom/features/ee/organizations/lib/getBookerUrlServer"; +import { OrganizationRepository } from "@calcom/features/ee/organizations/repositories/OrganizationRepository"; import { EventTypeRepository } from "@calcom/features/eventtypes/repositories/eventTypeRepository"; import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { WEBSITE_URL } from "@calcom/lib/constants"; @@ -16,11 +18,9 @@ import { parseRecurringEvent } from "@calcom/lib/isRecurringEvent"; import { getTranslation } from "@calcom/lib/server/i18n"; import type { PrismaClient } from "@calcom/prisma"; import type { Prisma } from "@calcom/prisma/client"; -import { SchedulingType, MembershipRole } from "@calcom/prisma/enums"; +import { MembershipRole, SchedulingType } from "@calcom/prisma/enums"; import { customInputSchema } from "@calcom/prisma/zod-utils"; -import { OrganizationRepository } from "@calcom/features/ee/organizations/repositories/OrganizationRepository"; import { TRPCError } from "@trpc/server"; -import { getOrganizationRepository } from "@calcom/features/ee/organizations/di/OrganizationRepository.container"; interface getEventTypeByIdProps { eventTypeId: number; @@ -29,6 +29,7 @@ interface getEventTypeByIdProps { isTrpcCall?: boolean; isUserOrganizationAdmin: boolean; currentOrganizationId: number | null; + userLocale?: string | null; } export type EventType = Awaited>; @@ -40,6 +41,7 @@ export const getEventTypeById = async ({ prisma, isTrpcCall = false, isUserOrganizationAdmin, + userLocale, }: getEventTypeByIdProps) => { const userSelect = { name: true, @@ -58,7 +60,7 @@ export const getEventTypeById = async ({ eventTypeId, isUserOrganizationAdmin, currentOrganizationId, - prisma + prisma, }); if (!rawEventType) { @@ -90,8 +92,8 @@ export const getEventTypeById = async ({ ...child, owner: child.owner ? await userRepo.enrichUserWithItsProfile({ - user: child.owner, - }) + user: child.owner, + }) : null, }); } @@ -141,19 +143,19 @@ export const getEventTypeById = async ({ children: childrenWithUserProfile.flatMap((ch) => ch.owner !== null ? { - ...ch, - owner: { - ...ch.owner, - avatar: getUserAvatarUrl(ch.owner), - email: ch.owner.email, - name: ch.owner.name ?? "", - username: ch.owner.username ?? "", - membership: - restEventType.team?.members.find((tm) => tm.user.id === ch.owner?.id)?.role || - MembershipRole.MEMBER, - }, - created: true, - } + ...ch, + owner: { + ...ch.owner, + avatar: getUserAvatarUrl(ch.owner), + email: ch.owner.email, + name: ch.owner.name ?? "", + username: ch.owner.username ?? "", + membership: + restEventType.team?.members.find((tm) => tm.user.id === ch.owner?.id)?.role || + MembershipRole.MEMBER, + }, + created: true, + } : [] ), }; @@ -187,7 +189,7 @@ export const getEventTypeById = async ({ const currentUser = eventType.users.find((u) => u.id === userId); - const t = await getTranslation(currentUser?.locale ?? "en", "common"); + const t = await getTranslation(userLocale ?? currentUser?.locale ?? "en", "common"); if (!currentUser?.id && !eventType.teamId) { throw new TRPCError({ @@ -224,19 +226,19 @@ export const getEventTypeById = async ({ const isOrgEventType = !!eventTypeObject.team?.parentId; const teamMembers = eventTypeObject.team ? eventTeamMembershipsWithUserProfile - .filter((member) => member.accepted || isOrgEventType) - .map((member) => { - const user: typeof member.user & { avatar: string } = { - ...member.user, - avatar: getUserAvatarUrl(member.user), - }; - return { - ...user, - profileId: user.profile.id, - eventTypes: user.eventTypes.map((evTy) => evTy.slug), - membership: member.role, - }; - }) + .filter((member) => member.accepted || isOrgEventType) + .map((member) => { + const user: typeof member.user & { avatar: string } = { + ...member.user, + avatar: getUserAvatarUrl(member.user), + }; + return { + ...user, + profileId: user.profile.id, + eventTypes: user.eventTypes.map((evTy) => evTy.slug), + membership: member.role, + }; + }) : []; // Find the current users membership so we can check role to enable/disable deletion. @@ -274,7 +276,9 @@ export async function getRawEventType({ }: Omit) { const eventTypeRepo = new EventTypeRepository(prisma); const organizationRepo = getOrganizationRepository(); - const isUserInPlatformOrganization = currentOrganizationId ? !!(await organizationRepo.findById({ id: currentOrganizationId }))?.isPlatform : false; + const isUserInPlatformOrganization = currentOrganizationId + ? !!(await organizationRepo.findById({ id: currentOrganizationId }))?.isPlatform + : false; if (isUserOrganizationAdmin && currentOrganizationId && isUserInPlatformOrganization) { // Platform Organization Admin can access any event of the organization even without being a member of the sub-teams @@ -284,7 +288,7 @@ export async function getRawEventType({ }); } - // Regular(Non Platform) Organization member(admin/non-admin) can access any event-type they are are a member of including sub-team events and Regular Team(non-subteam) events. + // Regular(Non Platform) Organization member(admin/non-admin) can access any event-type they are are a member of including sub-team events and Regular Team(non-subteam) events. // Remember an organization member can stay a part of Regular Team still if that team hasn't been moved to the organization yet. return await eventTypeRepo.findById({ id: eventTypeId, diff --git a/packages/trpc/server/routers/viewer/eventTypes/get.handler.ts b/packages/trpc/server/routers/viewer/eventTypes/get.handler.ts index 859787936380f9..d94a858f93401d 100644 --- a/packages/trpc/server/routers/viewer/eventTypes/get.handler.ts +++ b/packages/trpc/server/routers/viewer/eventTypes/get.handler.ts @@ -20,5 +20,6 @@ export const getHandler = ({ ctx, input }: GetOptions) => { prisma: ctx.prisma, isTrpcCall: true, isUserOrganizationAdmin: !!ctx.user?.organization?.isOrgAdmin, + userLocale: ctx.user.locale, }); };