From 9334b67f2c82a9a831376c554a8df29e055fd077 Mon Sep 17 00:00:00 2001 From: Rajiv Sahal Date: Mon, 9 Dec 2024 20:05:57 +0530 Subject: [PATCH] feat: banner and avatars for `Booker` atom (#17821) * init * added bannerUrl to output * cleanup * fixup * fix response DTOs * remove logs * send back avatar url for user * enable passing avatar urls for managed user * dont include urls for platform * remove logs * add team banner * update docs * nit * PR feedback * fix type error * add prop to pass in bannerUrl * update DTOs * update tests * fix tests --------- Co-authored-by: Somay Chauhan Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com> --- .../oauth-client-users.controller.e2e-spec.ts | 5 ++++ .../oauth-client-users.controller.ts | 1 + .../outputs/managed-user.output.ts | 14 ++++++++-- .../services/oauth-clients-users.service.ts | 2 ++ ...organizations-teams.controller.e2e-spec.ts | 14 ++++++++++ .../inputs/create-organization-team.input.ts | 28 +++++++++++++++++++ .../inputs/update-organization-team.input.ts | 28 +++++++++++++++++++ .../organizations-event-types.repository.ts | 16 +++++++++-- .../services/event-types/output.service.ts | 12 ++++++-- .../users/inputs/create-managed-user.input.ts | 14 ++++++++-- .../users/inputs/update-managed-user.input.ts | 14 ++++++++-- packages/features/bookings/Booker/Booker.tsx | 2 +- .../bookings/Booker/components/EventMeta.tsx | 14 ++++------ .../components/event-meta/Members.tsx | 10 +++++-- .../atoms/booker/BookerPlatformWrapper.tsx | 4 ++- .../transformApiEventTypeForAtom.ts | 5 ++-- .../base/src/pages/api/managed-user.ts | 5 ++++ .../outputs/event-type.output.ts | 10 +++++++ 18 files changed, 173 insertions(+), 25 deletions(-) diff --git a/apps/api/v2/src/modules/oauth-clients/controllers/oauth-client-users/oauth-client-users.controller.e2e-spec.ts b/apps/api/v2/src/modules/oauth-clients/controllers/oauth-client-users/oauth-client-users.controller.e2e-spec.ts index d0df40af54..9cf42f32e2 100644 --- a/apps/api/v2/src/modules/oauth-clients/controllers/oauth-client-users/oauth-client-users.controller.e2e-spec.ts +++ b/apps/api/v2/src/modules/oauth-clients/controllers/oauth-client-users/oauth-client-users.controller.e2e-spec.ts @@ -159,6 +159,7 @@ describe("OAuth Client Users Endpoints", () => { email: userEmail, timeZone: "incorrect-time-zone", name: "Alice Smith", + avatarUrl: "https://cal.com/api/avatar/2b735186-b01b-46d3-87da-019b8f61776b.png", }; await request(app.getHttpServer()) @@ -191,6 +192,7 @@ describe("OAuth Client Users Endpoints", () => { timeFormat: 24, locale: Locales.FR, name: "Alice Smith", + avatarUrl: "https://cal.com/api/avatar/2b735186-b01b-46d3-87da-019b8f61776b.png", }; const response = await request(app.getHttpServer()) @@ -211,6 +213,7 @@ describe("OAuth Client Users Endpoints", () => { expect(responseBody.data.user.weekStart).toEqual(requestBody.weekStart); expect(responseBody.data.user.timeFormat).toEqual(requestBody.timeFormat); expect(responseBody.data.user.locale).toEqual(requestBody.locale); + expect(responseBody.data.user.avatarUrl).toEqual(requestBody.avatarUrl); expect(responseBody.data.accessToken).toBeDefined(); expect(responseBody.data.refreshToken).toBeDefined(); @@ -265,6 +268,7 @@ describe("OAuth Client Users Endpoints", () => { timeFormat: 24, locale: Locales.FR, name: "Alice Smith", + avatarUrl: "https://cal.com/api/avatar/2b735186-b01b-46d3-87da-019b8f61776b.png", }; const response = await request(app.getHttpServer()) @@ -535,6 +539,7 @@ describe("OAuth Client Users Endpoints", () => { timeFormat: 24, locale: Locales.FR, name: "Alice Smith", + avatarUrl: "https://cal.com/api/avatar/2b735186-b01b-46d3-87da-019b8f61776b.png", }; const response = await request(app.getHttpServer()) diff --git a/apps/api/v2/src/modules/oauth-clients/controllers/oauth-client-users/oauth-client-users.controller.ts b/apps/api/v2/src/modules/oauth-clients/controllers/oauth-client-users/oauth-client-users.controller.ts index a9e361797e..b935146406 100644 --- a/apps/api/v2/src/modules/oauth-clients/controllers/oauth-client-users/oauth-client-users.controller.ts +++ b/apps/api/v2/src/modules/oauth-clients/controllers/oauth-client-users/oauth-client-users.controller.ts @@ -213,6 +213,7 @@ export class OAuthClientUsersController { timeFormat: user.timeFormat, defaultScheduleId: user.defaultScheduleId, locale: user.locale as Locales, + avatarUrl: user.avatarUrl, }; } } diff --git a/apps/api/v2/src/modules/oauth-clients/controllers/oauth-client-users/outputs/managed-user.output.ts b/apps/api/v2/src/modules/oauth-clients/controllers/oauth-client-users/outputs/managed-user.output.ts index fee340c659..c8f8eec959 100644 --- a/apps/api/v2/src/modules/oauth-clients/controllers/oauth-client-users/outputs/managed-user.output.ts +++ b/apps/api/v2/src/modules/oauth-clients/controllers/oauth-client-users/outputs/managed-user.output.ts @@ -1,7 +1,7 @@ import { Locales } from "@/lib/enums/locales"; -import { ApiProperty } from "@nestjs/swagger"; +import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; import { Transform } from "class-transformer"; -import { IsEnum, IsOptional } from "class-validator"; +import { IsEnum, IsOptional, IsUrl } from "class-validator"; export class ManagedUserOutput { @ApiProperty({ example: 1 }) @@ -36,4 +36,14 @@ export class ManagedUserOutput { @IsOptional() @ApiProperty({ example: Locales.EN, enum: Locales }) locale?: Locales; + + @IsUrl() + @IsOptional() + @ApiPropertyOptional({ + type: String, + example: "https://cal.com/api/avatar/2b735186-b01b-46d3-87da-019b8f61776b.png", + description: `URL of the user's avatar image`, + required: false, + }) + avatarUrl?: string | null; } diff --git a/apps/api/v2/src/modules/oauth-clients/services/oauth-clients-users.service.ts b/apps/api/v2/src/modules/oauth-clients/services/oauth-clients-users.service.ts index a8e57d7a5c..9e64bcf40c 100644 --- a/apps/api/v2/src/modules/oauth-clients/services/oauth-clients-users.service.ts +++ b/apps/api/v2/src/modules/oauth-clients/services/oauth-clients-users.service.ts @@ -66,9 +66,11 @@ export class OAuthClientUsersService { const updatedUser = await this.userRepository.update(user.id, { name: body.name, locale: body.locale, + avatarUrl: body.avatarUrl, }); user.locale = updatedUser.locale; user.name = updatedUser.name; + user.avatarUrl = updatedUser.avatarUrl; } const { accessToken, refreshToken, accessTokenExpiresAt } = await this.tokensRepository.createOAuthTokens( diff --git a/apps/api/v2/src/modules/organizations/controllers/teams/organizations-teams.controller.e2e-spec.ts b/apps/api/v2/src/modules/organizations/controllers/teams/organizations-teams.controller.e2e-spec.ts index 34e1cf1b5a..f2409b80a4 100644 --- a/apps/api/v2/src/modules/organizations/controllers/teams/organizations-teams.controller.e2e-spec.ts +++ b/apps/api/v2/src/modules/organizations/controllers/teams/organizations-teams.controller.e2e-spec.ts @@ -137,6 +137,8 @@ describe("Organizations Team Endpoints", () => { .post(`/v2/organizations/${org.id}/teams`) .send({ name: "Team created via API", + slug: "team-created-via-api", + bio: "This is our test team created via API", } satisfies CreateOrgTeamDto) .expect(201) .then(async (response) => { @@ -144,6 +146,8 @@ describe("Organizations Team Endpoints", () => { expect(responseBody.status).toEqual(SUCCESS_STATUS); teamCreatedViaApi = responseBody.data; expect(teamCreatedViaApi.name).toEqual("Team created via API"); + expect(teamCreatedViaApi.slug).toEqual("team-created-via-api"); + expect(teamCreatedViaApi.bio).toEqual("This is our test team created via API"); expect(teamCreatedViaApi.parentId).toEqual(org.id); const membership = await membershipsRepositoryFixture.getUserMembershipByTeamId( user.id, @@ -171,6 +175,9 @@ describe("Organizations Team Endpoints", () => { .patch(`/v2/organizations/${org.id}/teams/${teamCreatedViaApi.id}`) .send({ name: "Team created via API Updated", + weekStart: "Monday", + logoUrl: "https://i.cal.com/api/avatar/b0b58752-68ad-4c0d-8024-4fa382a77752.png", + bannerUrl: "https://i.cal.com/api/avatar/949be534-7a88-4185-967c-c020b0c0bef3.png", } satisfies CreateOrgTeamDto) .expect(200) .then((response) => { @@ -178,6 +185,13 @@ describe("Organizations Team Endpoints", () => { expect(responseBody.status).toEqual(SUCCESS_STATUS); teamCreatedViaApi = responseBody.data; expect(teamCreatedViaApi.name).toEqual("Team created via API Updated"); + expect(teamCreatedViaApi.weekStart).toEqual("Monday"); + expect(teamCreatedViaApi.logoUrl).toEqual( + "https://i.cal.com/api/avatar/b0b58752-68ad-4c0d-8024-4fa382a77752.png" + ); + expect(teamCreatedViaApi.bannerUrl).toEqual( + "https://i.cal.com/api/avatar/949be534-7a88-4185-967c-c020b0c0bef3.png" + ); expect(teamCreatedViaApi.parentId).toEqual(org.id); }); }); diff --git a/apps/api/v2/src/modules/organizations/inputs/create-organization-team.input.ts b/apps/api/v2/src/modules/organizations/inputs/create-organization-team.input.ts index 6c454dce6e..4ce6bc1a39 100644 --- a/apps/api/v2/src/modules/organizations/inputs/create-organization-team.input.ts +++ b/apps/api/v2/src/modules/organizations/inputs/create-organization-team.input.ts @@ -1,16 +1,25 @@ +import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; import { IsBoolean, IsOptional, IsString, IsUrl, Length } from "class-validator"; export class CreateOrgTeamDto { @IsString() @Length(1) + @ApiProperty({ description: "Name of the team", example: "CalTeam", required: true }) readonly name!: string; @IsOptional() @IsString() + @ApiPropertyOptional({ type: String, description: "Team slug", example: "caltel", required: false }) readonly slug?: string; @IsOptional() @IsUrl() + @ApiPropertyOptional({ + type: String, + example: "https://i.cal.com/api/avatar/b0b58752-68ad-4c0d-8024-4fa382a77752.png", + description: `URL of the teams logo image`, + required: false, + }) readonly logoUrl?: string; @IsOptional() @@ -59,6 +68,12 @@ export class CreateOrgTeamDto { @IsOptional() @IsUrl() + @ApiPropertyOptional({ + type: String, + example: "https://i.cal.com/api/avatar/949be534-7a88-4185-967c-c020b0c0bef3.png", + description: `URL of the teams banner image which is shown on booker`, + required: false, + }) readonly bannerUrl?: string; @IsOptional() @@ -67,10 +82,23 @@ export class CreateOrgTeamDto { @IsOptional() @IsString() + @ApiPropertyOptional({ + type: String, + example: "America/New_York", + description: `Timezone is used to create teams's default schedule from Monday to Friday from 9AM to 5PM. It will default to Europe/London if not passed.`, + required: false, + default: "Europe/London", + }) readonly timeZone?: string = "Europe/London"; @IsOptional() @IsString() + @ApiPropertyOptional({ + type: String, + example: "Monday", + required: false, + default: "Sunday", + }) readonly weekStart?: string = "Sunday"; @IsOptional() diff --git a/apps/api/v2/src/modules/organizations/inputs/update-organization-team.input.ts b/apps/api/v2/src/modules/organizations/inputs/update-organization-team.input.ts index 081c241f4d..dd13e2178f 100644 --- a/apps/api/v2/src/modules/organizations/inputs/update-organization-team.input.ts +++ b/apps/api/v2/src/modules/organizations/inputs/update-organization-team.input.ts @@ -1,16 +1,25 @@ +import { ApiPropertyOptional } from "@nestjs/swagger"; import { IsBoolean, IsOptional, IsString, IsUrl, Length } from "class-validator"; export class UpdateOrgTeamDto { @IsString() @Length(1) + @ApiPropertyOptional({ description: "Name of the team", example: "CalTeam", required: false }) readonly name?: string; @IsOptional() @IsString() + @ApiPropertyOptional({ type: String, description: "Team slug", example: "caltel", required: false }) readonly slug?: string; @IsOptional() @IsUrl() + @ApiPropertyOptional({ + type: String, + example: "https://i.cal.com/api/avatar/b0b58752-68ad-4c0d-8024-4fa382a77752.png", + description: `URL of the teams logo image`, + required: false, + }) readonly logoUrl?: string; @IsOptional() @@ -59,6 +68,12 @@ export class UpdateOrgTeamDto { @IsOptional() @IsUrl() + @ApiPropertyOptional({ + type: String, + example: "https://i.cal.com/api/avatar/949be534-7a88-4185-967c-c020b0c0bef3.png", + description: `URL of the teams banner image which is shown on booker`, + required: false, + }) readonly bannerUrl?: string; @IsOptional() @@ -67,10 +82,23 @@ export class UpdateOrgTeamDto { @IsOptional() @IsString() + @ApiPropertyOptional({ + type: String, + example: "America/New_York", + description: `Timezone is used to create teams's default schedule from Monday to Friday from 9AM to 5PM. It will default to Europe/London if not passed.`, + required: false, + default: "Europe/London", + }) readonly timeZone?: string = "Europe/London"; @IsOptional() @IsString() + @ApiPropertyOptional({ + type: String, + example: "Monday", + required: false, + default: "Sunday", + }) readonly weekStart?: string = "Sunday"; @IsOptional() diff --git a/apps/api/v2/src/modules/organizations/repositories/organizations-event-types.repository.ts b/apps/api/v2/src/modules/organizations/repositories/organizations-event-types.repository.ts index d00b594956..e03b96c0fd 100644 --- a/apps/api/v2/src/modules/organizations/repositories/organizations-event-types.repository.ts +++ b/apps/api/v2/src/modules/organizations/repositories/organizations-event-types.repository.ts @@ -24,7 +24,13 @@ export class OrganizationsEventTypesRepository { slug: eventTypeSlug, }, }, - include: { users: true, schedule: true, hosts: true, destinationCalendar: true }, + include: { + users: true, + schedule: true, + hosts: true, + destinationCalendar: true, + team: { select: { bannerUrl: true } }, + }, }); } @@ -33,7 +39,13 @@ export class OrganizationsEventTypesRepository { where: { teamId, }, - include: { users: true, schedule: true, hosts: true, destinationCalendar: true }, + include: { + users: true, + schedule: true, + hosts: true, + destinationCalendar: true, + team: { select: { bannerUrl: true } }, + }, }); } diff --git a/apps/api/v2/src/modules/organizations/services/event-types/output.service.ts b/apps/api/v2/src/modules/organizations/services/event-types/output.service.ts index 0d0c8f4f3a..8cc780733c 100644 --- a/apps/api/v2/src/modules/organizations/services/event-types/output.service.ts +++ b/apps/api/v2/src/modules/organizations/services/event-types/output.service.ts @@ -3,7 +3,7 @@ import { OrganizationsEventTypesRepository } from "@/modules/organizations/repos import { UsersRepository } from "@/modules/users/users.repository"; import { Injectable } from "@nestjs/common"; import type { EventType, User, Schedule, Host, DestinationCalendar } from "@prisma/client"; -import { SchedulingType } from "@prisma/client"; +import { SchedulingType, Team } from "@prisma/client"; import { HostPriority, TeamEventTypeResponseHost } from "@calcom/platform-types"; @@ -12,6 +12,7 @@ type EventTypeRelations = { schedule: Schedule | null; hosts: Host[]; destinationCalendar?: DestinationCalendar | null; + team?: Pick | null; }; export type DatabaseTeamEventType = EventType & EventTypeRelations; @@ -66,6 +67,7 @@ type Input = Pick< | "eventName" | "useEventTypeDestinationCalendarEmail" | "hideCalendarEventDetails" + | "team" >; @Injectable() @@ -95,6 +97,7 @@ export class OutputOrganizationsEventTypesService { ownerId: userId, parentEventTypeId: parentId, schedulingType: databaseEventType.schedulingType, + bannerUrl: databaseEventType?.team?.bannerUrl, assignAllTeamMembers: teamId ? assignAllTeamMembers : undefined, }; } @@ -129,9 +132,14 @@ export class OutputOrganizationsEventTypesService { name: databaseUser?.name || "", mandatory: databaseHost.isFixed, priority: getPriorityLabel(databaseHost.priority || 2), + avatarUrl: databaseUser?.avatarUrl, }); } else { - transformedHosts.push({ userId: databaseHost.userId, name: databaseUser?.name || "" }); + transformedHosts.push({ + userId: databaseHost.userId, + name: databaseUser?.name || "", + avatarUrl: databaseUser?.avatarUrl, + }); } } diff --git a/apps/api/v2/src/modules/users/inputs/create-managed-user.input.ts b/apps/api/v2/src/modules/users/inputs/create-managed-user.input.ts index 848a677193..d03a694f55 100644 --- a/apps/api/v2/src/modules/users/inputs/create-managed-user.input.ts +++ b/apps/api/v2/src/modules/users/inputs/create-managed-user.input.ts @@ -1,7 +1,7 @@ import { Locales } from "@/lib/enums/locales"; import { CapitalizeTimeZone } from "@/lib/inputs/capitalize-timezone"; -import { ApiProperty } from "@nestjs/swagger"; -import { IsOptional, IsTimeZone, IsString, IsEnum, IsIn } from "class-validator"; +import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; +import { IsOptional, IsTimeZone, IsString, IsEnum, IsIn, IsUrl } from "class-validator"; export type WeekDay = "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday" | "Saturday" | "Sunday"; export type TimeFormat = 12 | 24; @@ -42,4 +42,14 @@ export class CreateManagedUserInput { @IsOptional() @ApiProperty({ example: Locales.EN, enum: Locales }) locale?: Locales; + + @IsUrl() + @IsOptional() + @ApiPropertyOptional({ + type: String, + example: "https://cal.com/api/avatar/2b735186-b01b-46d3-87da-019b8f61776b.png", + description: `URL of the user's avatar image`, + required: false, + }) + avatarUrl?: string; } diff --git a/apps/api/v2/src/modules/users/inputs/update-managed-user.input.ts b/apps/api/v2/src/modules/users/inputs/update-managed-user.input.ts index 9bdf3180b0..a0b3bb33be 100644 --- a/apps/api/v2/src/modules/users/inputs/update-managed-user.input.ts +++ b/apps/api/v2/src/modules/users/inputs/update-managed-user.input.ts @@ -1,8 +1,8 @@ import { Locales } from "@/lib/enums/locales"; import { CapitalizeTimeZone } from "@/lib/inputs/capitalize-timezone"; import { TimeFormat, WeekDay } from "@/modules/users/inputs/create-managed-user.input"; -import { ApiProperty } from "@nestjs/swagger"; -import { IsEnum, IsIn, IsNumber, IsOptional, IsString, IsTimeZone } from "class-validator"; +import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; +import { IsEnum, IsIn, IsNumber, IsOptional, IsString, IsTimeZone, IsUrl } from "class-validator"; export class UpdateManagedUserInput { @IsString() @@ -40,4 +40,14 @@ export class UpdateManagedUserInput { @IsOptional() @ApiProperty({ example: Locales.EN, enum: Locales }) locale?: Locales; + + @IsUrl() + @IsOptional() + @ApiPropertyOptional({ + type: String, + example: "https://cal.com/api/avatar/2b735186-b01b-46d3-87da-019b8f61776b.png", + description: `URL of the user's avatar image`, + required: false, + }) + avatarUrl?: string; } diff --git a/packages/features/bookings/Booker/Booker.tsx b/packages/features/bookings/Booker/Booker.tsx index f551bce4ad..a135452f13 100644 --- a/packages/features/bookings/Booker/Booker.tsx +++ b/packages/features/bookings/Booker/Booker.tsx @@ -335,7 +335,7 @@ const BookerComponent = ({ - {!hideEventTypeDetails && orgBannerUrl && !isPlatform && ( + {!hideEventTypeDetails && orgBannerUrl && ( - {!isPlatform && ( - - )} + {event?.title} {(event.description || translatedDescription) && ( diff --git a/packages/features/bookings/components/event-meta/Members.tsx b/packages/features/bookings/components/event-meta/Members.tsx index b888395ddf..ef9bcb76a6 100644 --- a/packages/features/bookings/components/event-meta/Members.tsx +++ b/packages/features/bookings/components/event-meta/Members.tsx @@ -1,3 +1,4 @@ +import { useIsPlatform } from "@calcom/atoms/monorepo"; import { useIsEmbed } from "@calcom/embed-core/embed-iframe"; import { useBookerStore } from "@calcom/features/bookings/Booker/store"; import type { BookerEvent } from "@calcom/features/bookings/types"; @@ -22,6 +23,7 @@ export const EventMembers = ({ schedulingType, users, profile, entity }: EventMe const username = useBookerStore((state) => state.username); const isDynamic = !!(username && username.indexOf("+") > -1); const isEmbed = useIsEmbed(); + const isPlatform = useIsPlatform(); const showMembers = schedulingType !== SchedulingType.ROUND_ROBIN; const shownUsers = showMembers ? users : []; @@ -56,9 +58,11 @@ export const EventMembers = ({ schedulingType, users, profile, entity }: EventMe items={[ ...orgOrTeamAvatarItem, ...shownUsers.map((user) => ({ - href: `${getBookerBaseUrlSync(user.profile?.organization?.slug ?? null)}/${ - user.profile?.username - }?redirect=false`, + href: isPlatform + ? null + : `${getBookerBaseUrlSync(user.profile?.organization?.slug ?? null)}/${ + user.profile?.username + }?redirect=false`, alt: user.name || "", title: user.name || "", image: getUserAvatarUrl(user), diff --git a/packages/platform/atoms/booker/BookerPlatformWrapper.tsx b/packages/platform/atoms/booker/BookerPlatformWrapper.tsx index 8e004f1bf6..e4a1628870 100644 --- a/packages/platform/atoms/booker/BookerPlatformWrapper.tsx +++ b/packages/platform/atoms/booker/BookerPlatformWrapper.tsx @@ -77,6 +77,7 @@ export type BookerPlatformWrapperAtomProps = Omit< locationUrl?: string; view?: VIEW_TYPE; metadata?: Record; + bannerUrl?: string; }; type VIEW_TYPE = keyof typeof BookerLayouts; @@ -95,7 +96,7 @@ export type BookerPlatformWrapperAtomPropsForTeam = BookerPlatformWrapperAtomPro export const BookerPlatformWrapper = ( props: BookerPlatformWrapperAtomPropsForIndividual | BookerPlatformWrapperAtomPropsForTeam ) => { - const { view = "MONTH_VIEW" } = props; + const { view = "MONTH_VIEW", bannerUrl } = props; const layout = BookerLayouts[view]; const { clientId } = useAtomsContext(); @@ -482,6 +483,7 @@ export const BookerPlatformWrapper = ( bookerForm={bookerForm} event={event} schedule={schedule} + orgBannerUrl={bannerUrl ?? event.data?.bannerUrl} bookerLayout={bookerLayout} verifyCode={undefined} isPlatform diff --git a/packages/platform/atoms/event-types/atom-api-transformers/transformApiEventTypeForAtom.ts b/packages/platform/atoms/event-types/atom-api-transformers/transformApiEventTypeForAtom.ts index ebda1e2eb7..5f76d7b41a 100644 --- a/packages/platform/atoms/event-types/atom-api-transformers/transformApiEventTypeForAtom.ts +++ b/packages/platform/atoms/event-types/atom-api-transformers/transformApiEventTypeForAtom.ts @@ -29,7 +29,7 @@ import { import type { BookerPlatformWrapperAtomProps } from "../../booker/BookerPlatformWrapper"; export function transformApiEventTypeForAtom( - eventType: Omit, + eventType: Omit & { bannerUrl?: string }, entity: BookerPlatformWrapperAtomProps["entity"] | undefined, defaultFormValues: BookerPlatformWrapperAtomProps["defaultFormValues"] | undefined ) { @@ -132,7 +132,7 @@ export function transformApiTeamEventTypeForAtom( isDynamic: false, profile: { username: "team", - name: "team", + name: "Team", weekStart: "Sunday", image: "", brandColor: null, @@ -171,6 +171,7 @@ export function transformApiTeamEventTypeForAtom( }, })), users: hosts.map((host) => ({ + ...host, metadata: undefined, bookerUrl: getBookerBaseUrlSync(null), profile: { diff --git a/packages/platform/examples/base/src/pages/api/managed-user.ts b/packages/platform/examples/base/src/pages/api/managed-user.ts index d28a03fdd2..a7cca4f405 100644 --- a/packages/platform/examples/base/src/pages/api/managed-user.ts +++ b/packages/platform/examples/base/src/pages/api/managed-user.ts @@ -54,6 +54,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< body: JSON.stringify({ email: emailOne, name: "John Jones", + avatarUrl: + "https://images.unsplash.com/photo-1527980965255-d3b416303d12?q=80&w=3023&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", }), } ); @@ -83,6 +85,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< body: JSON.stringify({ email: emailTwo, name: "Jane Doe", + avatarUrl: + "https://plus.unsplash.com/premium_photo-1668319915476-5cc7717e00f1?q=80&w=3164&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", }), } ); @@ -139,6 +143,7 @@ async function createTeam(orgId: number, name: string) { }, body: JSON.stringify({ name, + bannerUrl: "https://i.cal.com/api/avatar/949be534-7a88-4185-967c-c020b0c0bef3.png", }), } ); diff --git a/packages/platform/types/event-types/event-types_2024_06_14/outputs/event-type.output.ts b/packages/platform/types/event-types/event-types_2024_06_14/outputs/event-type.output.ts index 636ff16747..6d43d6acef 100644 --- a/packages/platform/types/event-types/event-types_2024_06_14/outputs/event-type.output.ts +++ b/packages/platform/types/event-types/event-types_2024_06_14/outputs/event-type.output.ts @@ -362,6 +362,11 @@ export class TeamEventTypeResponseHost extends TeamEventTypeHostInput { @IsString() @DocsProperty({ example: "John Doe" }) name!: string; + + @IsString() + @IsOptional() + @DocsProperty({ example: "https://cal.com/api/avatar/d95949bc-ccb1-400f-acf6-045c51a16856.png" }) + avatarUrl?: string | null; } export class EventTypeOutput_2024_06_14 extends BaseEventTypeOutput_2024_06_14 { @@ -413,4 +418,9 @@ export class TeamEventTypeOutput_2024_06_14 extends BaseEventTypeOutput_2024_06_ @IsBoolean() @DocsProperty() hideCalendarEventDetails?: boolean; + + @IsString() + @IsOptional() + @DocsProperty() + bannerUrl?: string; }