fix: avatar URL breaking for team/orgs in BookerEmbed atom (#27424)
* fix: avatar URL breaking for team/orgs in booker embed * fix: api v2 breaking because of type mismatch * fix: atoms build * chore: implement PR feedback
This commit is contained in:
@@ -1,21 +1,20 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { AVATAR_FALLBACK, CAL_URL } from "@calcom/lib/constants";
|
||||
import type { User } from "@calcom/prisma/client";
|
||||
import { z } from "zod";
|
||||
|
||||
export const getAbsoluteAvatarUrl = (url: string): string => {
|
||||
const isAbsolute = z.string().url().safeParse(url).success;
|
||||
return isAbsolute ? url : CAL_URL + url;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gives an organization aware avatar url for a user
|
||||
* It ensures that the wrong avatar isn't fetched by ensuring that organizationId is always passed
|
||||
* It should always return a fully formed url
|
||||
*/
|
||||
export const getUserAvatarUrl = (user: Pick<User, "avatarUrl"> | undefined) => {
|
||||
export const getUserAvatarUrl = (user: Pick<User, "avatarUrl"> | undefined): string => {
|
||||
if (user?.avatarUrl) {
|
||||
const isAbsoluteUrl = z.string().url().safeParse(user.avatarUrl).success;
|
||||
if (isAbsoluteUrl) {
|
||||
return user.avatarUrl;
|
||||
} else {
|
||||
return CAL_URL + user.avatarUrl;
|
||||
}
|
||||
return getAbsoluteAvatarUrl(user.avatarUrl);
|
||||
}
|
||||
return CAL_URL + AVATAR_FALLBACK;
|
||||
};
|
||||
|
||||
@@ -2,12 +2,14 @@ import { useQuery } from "@tanstack/react-query";
|
||||
import { useMemo } from "react";
|
||||
|
||||
import { getUsernameList } from "@calcom/features/eventtypes/lib/defaultEvents";
|
||||
import { getAbsoluteAvatarUrl } from "@calcom/lib/getAvatarUrl";
|
||||
import { SUCCESS_STATUS, V2_ENDPOINTS } from "@calcom/platform-constants";
|
||||
import type { PublicEventType } from "@calcom/features/eventtypes/lib/getPublicEvent";
|
||||
import type { ApiResponse } from "@calcom/platform-types";
|
||||
|
||||
import http from "../../../lib/http";
|
||||
import { useAtomsContext } from "../../../hooks/useAtomsContext";
|
||||
import { useIsPlatformBookerEmbed } from "../../../hooks/useIsPlatformBookerEmbed";
|
||||
|
||||
export const QUERY_KEY = "get-public-event";
|
||||
export type UsePublicEventReturnType = ReturnType<typeof useAtomGetPublicEvent>;
|
||||
@@ -20,9 +22,15 @@ type Props = {
|
||||
selectedDuration: number | null;
|
||||
};
|
||||
|
||||
export const useAtomGetPublicEvent = ({ username, eventSlug, isTeamEvent, teamId, selectedDuration }: Props) => {
|
||||
|
||||
export const useAtomGetPublicEvent = ({
|
||||
username,
|
||||
eventSlug,
|
||||
isTeamEvent,
|
||||
teamId,
|
||||
selectedDuration,
|
||||
}: Props) => {
|
||||
const { organizationId } = useAtomsContext();
|
||||
const isPlatformBookerEmbed = useIsPlatformBookerEmbed();
|
||||
|
||||
const isDynamic = useMemo(() => {
|
||||
return getUsernameList(username ?? "").length > 1;
|
||||
@@ -31,22 +39,30 @@ export const useAtomGetPublicEvent = ({ username, eventSlug, isTeamEvent, teamId
|
||||
const pathname = `/atoms/${V2_ENDPOINTS.eventTypes}/${eventSlug}/public`;
|
||||
|
||||
const event = useQuery({
|
||||
queryKey: [QUERY_KEY, username, eventSlug, isTeamEvent, teamId, organizationId],
|
||||
queryKey: [
|
||||
QUERY_KEY,
|
||||
username,
|
||||
eventSlug,
|
||||
isTeamEvent,
|
||||
teamId,
|
||||
organizationId,
|
||||
],
|
||||
queryFn: () => {
|
||||
const params: Record<string, any> = {
|
||||
isTeamEvent,
|
||||
teamId,
|
||||
username: getUsernameList(username ?? "").join("+")
|
||||
username: getUsernameList(username ?? "").join("+"),
|
||||
};
|
||||
|
||||
|
||||
// Only include orgId if it's not 0
|
||||
if (organizationId !== 0) {
|
||||
params.orgId = organizationId;
|
||||
}
|
||||
|
||||
return http?.get<ApiResponse<PublicEventType>>(pathname, {
|
||||
params,
|
||||
})
|
||||
|
||||
return http
|
||||
?.get<ApiResponse<PublicEventType>>(pathname, {
|
||||
params,
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.data.status === SUCCESS_STATUS) {
|
||||
if (isDynamic && selectedDuration && res.data.data) {
|
||||
@@ -54,6 +70,18 @@ export const useAtomGetPublicEvent = ({ username, eventSlug, isTeamEvent, teamId
|
||||
// but we are re-using the dynamic event type as a team event, so we must set the event length to whatever the event length is.
|
||||
res.data.data.length = selectedDuration;
|
||||
}
|
||||
if (isPlatformBookerEmbed && res.data.data) {
|
||||
if (res.data.data.profile?.image) {
|
||||
res.data.data.profile.image = getAbsoluteAvatarUrl(
|
||||
res.data.data.profile.image
|
||||
);
|
||||
}
|
||||
if (res.data.data.entity?.logoUrl) {
|
||||
res.data.data.entity.logoUrl = getAbsoluteAvatarUrl(
|
||||
res.data.data.entity.logoUrl
|
||||
);
|
||||
}
|
||||
}
|
||||
return res.data.data;
|
||||
}
|
||||
throw new Error(res.data.error.message);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import path, { resolve } from "node:path";
|
||||
import react from "@vitejs/plugin-react-swc";
|
||||
import path from "node:path"
|
||||
import { resolve } from "node:path";
|
||||
import { defineConfig, loadEnv } from "vite";
|
||||
import dts from "vite-plugin-dts";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user