fix: Apply organization brand colors and theme to member personal events (#24456)
* fix: Apply organization brand colors and theme to member personal events - Fetch organization brand colors and theme in getEventTypesFromDB - Override user brand colors/theme with org values for personal events - Apply to booking confirmation pages, user booking pages, and routing forms - Follow same pattern as hideBranding for consistency - Fixes issue where org brand colors only applied to team events Co-Authored-By: [email protected] <[email protected]> * fix: Resolve type errors for organization brand color and theme overrides - Added brandColor, darkBrandColor, theme to ProfileRepository findById organization select - Updated test mock to include new organization fields - Ensures consistent organization branding types across all queries - All type errors related to brand color changes now resolved Co-Authored-By: [email protected] <[email protected]> * fix: Remove redundant profile assignment causing type errors The spread operator already includes profile when it exists. Explicit assignment causes type conflicts with union types where profile is not guaranteed to exist in all branches. Resolves TypeScript error at bookings-single-view.getServerSideProps.tsx:134 Co-Authored-By: [email protected] <[email protected]> * fix: Use eventTypeRaw.profile for organization brand color access Changed eventType.profile to eventTypeRaw.profile in profile object construction to fix TypeScript errors where profile property doesn't exist on transformed eventType object. The eventTypeRaw object maintains the original profile field from the database query. Resolves TypeScript errors at lines 155, 158, 161 in bookings-single-view.getServerSideProps.tsx Co-Authored-By: [email protected] <[email protected]> * fix type error * refactor: Extract branding logic into getBrandingForEventType utility - Create getBrandingForEventType utility function that handles organization brand color overrides for both team and personal events - For team events: org branding → team branding → null - For personal events: org branding → user branding → null - Refactor bookings-single-view to use utility function - Update team booking page to apply organization brand overrides - Add organization branding fields to ProfileRepository and team queries Addresses review feedback from @hariombalhara on PR #24456 Co-Authored-By: [email protected] <[email protected]> * Update getBranding.ts * Change Set themeBasis to null instead of branding.theme. * refactor: Simplify branding fallback logic to prevent mixing org/team settings - Changed getBrandingForEventType to use either parent or team branding entirely - Simplified team parent branding structure in getServerSideProps - Prevents inconsistent branding when some properties exist in parent but not others - Addresses PR review feedback from hariombalhara Co-Authored-By: [email protected] <[email protected]> * addressed review * test: Add comprehensive unit tests for branding utility functions - Add 20 unit tests covering getBrandingForEventType, getBrandingForUser, and getBrandingForTeam - Test organization branding override scenarios for both team and personal events - Test fallback behavior when organization branding is not set - Test handling of null and optional branding properties - Verify theme and color inheritance from parent organizations Co-Authored-By: [email protected] <[email protected]> * test: Simplify branding tests to focus on core scenarios - Reduce from 20 to 8 essential test cases - Focus on org override and fallback behavior for each utility - Remove redundant edge case tests while maintaining full coverage Co-Authored-By: [email protected] <[email protected]> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: [email protected] <[email protected]>
This commit is contained in:
co-authored by
Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
[email protected] <[email protected]>
parent
9d4522825b
commit
fc4ecf500a
@@ -83,9 +83,12 @@ export const getServerSideProps = async function getServerSideProps(
|
||||
props: {
|
||||
isEmbed,
|
||||
profile: {
|
||||
theme: form.user.theme,
|
||||
brandColor: form.user.brandColor,
|
||||
darkBrandColor: form.user.darkBrandColor,
|
||||
theme: formWithUserProfile.user.profile?.organization?.theme ?? formWithUserProfile.user.theme,
|
||||
brandColor:
|
||||
formWithUserProfile.user.profile?.organization?.brandColor ?? formWithUserProfile.user.brandColor,
|
||||
darkBrandColor:
|
||||
formWithUserProfile.user.profile?.organization?.darkBrandColor ??
|
||||
formWithUserProfile.user.darkBrandColor,
|
||||
},
|
||||
form: await getSerializableForm({ form: enrichFormWithMigrationData(formWithUserProfile) }),
|
||||
},
|
||||
|
||||
+15
-3
@@ -49,6 +49,13 @@ export const getEventTypesFromDB = async (id: number) => {
|
||||
profile: {
|
||||
select: {
|
||||
organizationId: true,
|
||||
organization: {
|
||||
select: {
|
||||
brandColor: true,
|
||||
darkBrandColor: true,
|
||||
theme: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
teamId: true,
|
||||
@@ -71,9 +78,15 @@ export const getEventTypesFromDB = async (id: number) => {
|
||||
slug: true,
|
||||
name: true,
|
||||
hideBranding: true,
|
||||
brandColor: true,
|
||||
darkBrandColor: true,
|
||||
theme: true,
|
||||
parent: {
|
||||
select: {
|
||||
hideBranding: true,
|
||||
brandColor: true,
|
||||
darkBrandColor: true,
|
||||
theme: true,
|
||||
},
|
||||
},
|
||||
createdByOAuthClientId: true,
|
||||
@@ -116,12 +129,11 @@ export const getEventTypesFromDB = async (id: number) => {
|
||||
}
|
||||
|
||||
const metadata = EventTypeMetaDataSchema.parse(eventType.metadata);
|
||||
const { profile, ...restEventType } = eventType;
|
||||
const isOrgTeamEvent = !!eventType?.team && !!profile?.organizationId;
|
||||
const isOrgTeamEvent = !!eventType?.team && !!eventType.profile?.organizationId;
|
||||
|
||||
return {
|
||||
isDynamic: false,
|
||||
...restEventType,
|
||||
...eventType,
|
||||
bookingFields: getBookingFieldsWithSystemFields({ ...eventType, isOrgTeamEvent }),
|
||||
metadata,
|
||||
};
|
||||
|
||||
@@ -7,8 +7,9 @@ import { getBookingForReschedule } from "@calcom/features/bookings/lib/get-booki
|
||||
import { getSlugOrRequestedSlug, orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
|
||||
import { getOrganizationSEOSettings } from "@calcom/features/ee/organizations/lib/orgSettings";
|
||||
import { FeaturesRepository } from "@calcom/features/flags/features.repository";
|
||||
import { getPlaceholderAvatar } from "@calcom/lib/defaultAvatarImage";
|
||||
import { getBrandingForEventType } from "@calcom/features/profile/lib/getBranding";
|
||||
import { shouldHideBrandingForTeamEvent } from "@calcom/features/profile/lib/hideBranding";
|
||||
import { getPlaceholderAvatar } from "@calcom/lib/defaultAvatarImage";
|
||||
import slugify from "@calcom/lib/slugify";
|
||||
import { prisma } from "@calcom/prisma";
|
||||
import type { User } from "@calcom/prisma/client";
|
||||
@@ -30,7 +31,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
|
||||
const { req, params, query } = context;
|
||||
const session = await getServerSession({ req });
|
||||
const { slug: teamSlug, type: meetingSlug } = paramsSchema.parse(params);
|
||||
const { rescheduleUid, isInstantMeeting: queryIsInstantMeeting, email } = query;
|
||||
const { rescheduleUid, isInstantMeeting: queryIsInstantMeeting } = query;
|
||||
const allowRescheduleForCancelledBooking = query.allowRescheduleForCancelledBooking === "true";
|
||||
const { currentOrgDomain, isValidOrgDomain } = orgDomainConfig(req, params?.orgSlug);
|
||||
|
||||
@@ -133,6 +134,14 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
|
||||
const teamHasApiV2Route = await featureRepo.checkIfTeamHasFeature(team.id, "use-api-v2-for-team-slots");
|
||||
const useApiV2 = teamHasApiV2Route && hasApiV2RouteInEnv();
|
||||
|
||||
const branding = getBrandingForEventType({
|
||||
eventType: {
|
||||
team: team.parent ?? team,
|
||||
users: [],
|
||||
profile: null,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
props: {
|
||||
useApiV2,
|
||||
@@ -153,6 +162,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
|
||||
: getPlaceholderAvatar(team.logoUrl, team.name),
|
||||
name,
|
||||
username: orgSlug ?? null,
|
||||
...branding,
|
||||
},
|
||||
title: eventData.title,
|
||||
users: eventHostsUserData,
|
||||
@@ -204,6 +214,9 @@ const getTeamWithEventsData = async (
|
||||
bannerUrl: true,
|
||||
logoUrl: true,
|
||||
hideBranding: true,
|
||||
brandColor: true,
|
||||
darkBrandColor: true,
|
||||
theme: true,
|
||||
organizationSettings: {
|
||||
select: {
|
||||
allowSEOIndexing: true,
|
||||
@@ -214,6 +227,9 @@ const getTeamWithEventsData = async (
|
||||
logoUrl: true,
|
||||
name: true,
|
||||
slug: true,
|
||||
brandColor: true,
|
||||
darkBrandColor: true,
|
||||
theme: true,
|
||||
eventTypes: {
|
||||
where: {
|
||||
slug: meetingSlug,
|
||||
|
||||
@@ -6,12 +6,13 @@ import { eventTypeMetaDataSchemaWithTypedApps } from "@calcom/app-store/zod-util
|
||||
import { orgDomainConfig } from "@calcom/ee/organizations/lib/orgDomains";
|
||||
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
||||
import getBookingInfo from "@calcom/features/bookings/lib/getBookingInfo";
|
||||
import { BookingRepository } from "@calcom/features/bookings/repositories/BookingRepository";
|
||||
import { getDefaultEvent } from "@calcom/features/eventtypes/lib/defaultEvents";
|
||||
import { getBrandingForEventType } from "@calcom/features/profile/lib/getBranding";
|
||||
import { shouldHideBrandingForEvent } from "@calcom/features/profile/lib/hideBranding";
|
||||
import { parseRecurringEvent } from "@calcom/lib/isRecurringEvent";
|
||||
import { markdownToSafeHTML } from "@calcom/lib/markdownToSafeHTML";
|
||||
import { maybeGetBookingUidFromSeat } from "@calcom/lib/server/maybeGetBookingUidFromSeat";
|
||||
import { BookingRepository } from "@calcom/features/bookings/repositories/BookingRepository";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { customInputSchema } from "@calcom/prisma/zod-utils";
|
||||
import { meRouter } from "@calcom/trpc/server/routers/viewer/me/_router";
|
||||
@@ -115,7 +116,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||
bookingInfo["startTime"] = (bookingInfo?.startTime as Date)?.toISOString() as unknown as Date;
|
||||
bookingInfo["endTime"] = (bookingInfo?.endTime as Date)?.toISOString() as unknown as Date;
|
||||
|
||||
eventTypeRaw.users = !!eventTypeRaw.hosts?.length
|
||||
eventTypeRaw.users = eventTypeRaw.hosts?.length
|
||||
? eventTypeRaw.hosts.map((host) => host.user)
|
||||
: eventTypeRaw.users;
|
||||
|
||||
@@ -150,9 +151,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||
const profile = {
|
||||
name: eventType.team?.name || eventType.users[0]?.name || null,
|
||||
email: eventType.team ? null : eventType.users[0].email || null,
|
||||
theme: (!eventType.team?.name && eventType.users[0]?.theme) || null,
|
||||
brandColor: eventType.team ? null : eventType.users[0].brandColor || null,
|
||||
darkBrandColor: eventType.team ? null : eventType.users[0].darkBrandColor || null,
|
||||
...getBrandingForEventType({ eventType: eventTypeRaw }),
|
||||
slug: eventType.team?.slug || eventType.users[0]?.username || null,
|
||||
};
|
||||
|
||||
|
||||
@@ -20,7 +20,14 @@ function mockedUserPageComponentProps(props: Partial<React.ComponentProps<typeof
|
||||
theme: "dark",
|
||||
brandColor: "red",
|
||||
darkBrandColor: "black",
|
||||
organization: { requestedSlug: "slug", slug: "slug", id: 1 },
|
||||
organization: {
|
||||
requestedSlug: "slug",
|
||||
slug: "slug",
|
||||
id: 1,
|
||||
brandColor: null,
|
||||
darkBrandColor: null,
|
||||
theme: null,
|
||||
},
|
||||
allowSEOIndexing: true,
|
||||
username: "john",
|
||||
},
|
||||
|
||||
@@ -4,14 +4,15 @@ import { encode } from "querystring";
|
||||
import type { z } from "zod";
|
||||
|
||||
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
|
||||
import { getEventTypesPublic } from "@calcom/features/eventtypes/lib/getEventTypesPublic";
|
||||
import { DEFAULT_DARK_BRAND_COLOR, DEFAULT_LIGHT_BRAND_COLOR } from "@calcom/lib/constants";
|
||||
import { getUsernameList } from "@calcom/features/eventtypes/lib/defaultEvents";
|
||||
import { getEventTypesPublic } from "@calcom/features/eventtypes/lib/getEventTypesPublic";
|
||||
import { getBrandingForUser } from "@calcom/features/profile/lib/getBranding";
|
||||
import { UserRepository } from "@calcom/features/users/repositories/UserRepository";
|
||||
import { DEFAULT_DARK_BRAND_COLOR, DEFAULT_LIGHT_BRAND_COLOR } from "@calcom/lib/constants";
|
||||
import { getUserAvatarUrl } from "@calcom/lib/getAvatarUrl";
|
||||
import logger from "@calcom/lib/logger";
|
||||
import { markdownToSafeHTML } from "@calcom/lib/markdownToSafeHTML";
|
||||
import { safeStringify } from "@calcom/lib/safeStringify";
|
||||
import { UserRepository } from "@calcom/features/users/repositories/UserRepository";
|
||||
import { stripMarkdown } from "@calcom/lib/stripMarkdown";
|
||||
import { prisma } from "@calcom/prisma";
|
||||
import type { EventType, User } from "@calcom/prisma/client";
|
||||
@@ -33,6 +34,9 @@ type UserPageProps = {
|
||||
requestedSlug: string | null;
|
||||
slug: string | null;
|
||||
id: number | null;
|
||||
brandColor: string | null;
|
||||
darkBrandColor: string | null;
|
||||
theme: string | null;
|
||||
} | null;
|
||||
allowSEOIndexing: boolean;
|
||||
username: string | null;
|
||||
@@ -130,15 +134,18 @@ export const getServerSideProps: GetServerSideProps<UserPageProps> = async (cont
|
||||
|
||||
const [user] = usersInOrgContext; //to be used when dealing with single user, not dynamic group
|
||||
|
||||
const branding = getBrandingForUser({ user });
|
||||
|
||||
const profile = {
|
||||
name: user.name || user.username || "",
|
||||
image: getUserAvatarUrl({
|
||||
avatarUrl: user.avatarUrl,
|
||||
}),
|
||||
theme: user.theme,
|
||||
brandColor: user.brandColor ?? DEFAULT_LIGHT_BRAND_COLOR,
|
||||
theme: branding.theme,
|
||||
brandColor: branding.brandColor ?? DEFAULT_LIGHT_BRAND_COLOR,
|
||||
avatarUrl: user.avatarUrl,
|
||||
darkBrandColor: user.darkBrandColor ?? DEFAULT_DARK_BRAND_COLOR,
|
||||
darkBrandColor:
|
||||
branding.darkBrandColor ?? DEFAULT_DARK_BRAND_COLOR,
|
||||
allowSEOIndexing: user.allowSEOIndexing ?? true,
|
||||
username: user.username,
|
||||
organization: user.profile.organization,
|
||||
|
||||
@@ -141,6 +141,7 @@ const commons = {
|
||||
restrictionScheduleId: null,
|
||||
useBookerTimezone: false,
|
||||
profileId: null,
|
||||
profile: null,
|
||||
requiresConfirmationWillBlockSlot: false,
|
||||
canSendCalVideoTranscriptionEmails: false,
|
||||
instantMeetingExpiryTimeOffsetInSeconds: 0,
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { getBrandingForEventType, getBrandingForUser, getBrandingForTeam } from "./getBranding";
|
||||
|
||||
describe("getBranding", () => {
|
||||
describe("getBrandingForEventType", () => {
|
||||
describe("team events", () => {
|
||||
it("should use parent org branding when available", () => {
|
||||
const eventType = {
|
||||
team: {
|
||||
name: "Team A",
|
||||
brandColor: "#AAAAAA",
|
||||
darkBrandColor: "#BBBBBB",
|
||||
theme: "light",
|
||||
parent: {
|
||||
brandColor: "#111111",
|
||||
darkBrandColor: "#222222",
|
||||
theme: "dark",
|
||||
},
|
||||
},
|
||||
users: [],
|
||||
};
|
||||
|
||||
const result = getBrandingForEventType({ eventType });
|
||||
|
||||
expect(result).toEqual({
|
||||
theme: "dark",
|
||||
brandColor: "#111111",
|
||||
darkBrandColor: "#222222",
|
||||
});
|
||||
});
|
||||
|
||||
it("should fallback to team branding when no parent", () => {
|
||||
const eventType = {
|
||||
team: {
|
||||
name: "Team A",
|
||||
brandColor: "#AAAAAA",
|
||||
darkBrandColor: "#BBBBBB",
|
||||
theme: "light",
|
||||
parent: null,
|
||||
},
|
||||
users: [],
|
||||
};
|
||||
|
||||
const result = getBrandingForEventType({ eventType });
|
||||
|
||||
expect(result).toEqual({
|
||||
theme: "light",
|
||||
brandColor: "#AAAAAA",
|
||||
darkBrandColor: "#BBBBBB",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("personal events", () => {
|
||||
it("should use organization branding when available", () => {
|
||||
const eventType = {
|
||||
team: null,
|
||||
profile: {
|
||||
organization: {
|
||||
brandColor: "#111111",
|
||||
darkBrandColor: "#222222",
|
||||
theme: "dark",
|
||||
},
|
||||
},
|
||||
users: [
|
||||
{
|
||||
theme: "light",
|
||||
brandColor: "#AAAAAA",
|
||||
darkBrandColor: "#BBBBBB",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const result = getBrandingForEventType({ eventType });
|
||||
|
||||
expect(result).toEqual({
|
||||
theme: "dark",
|
||||
brandColor: "#111111",
|
||||
darkBrandColor: "#222222",
|
||||
});
|
||||
});
|
||||
|
||||
it("should fallback to user branding when no organization", () => {
|
||||
const eventType = {
|
||||
team: null,
|
||||
profile: {
|
||||
organization: null,
|
||||
},
|
||||
users: [
|
||||
{
|
||||
theme: "light",
|
||||
brandColor: "#AAAAAA",
|
||||
darkBrandColor: "#BBBBBB",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const result = getBrandingForEventType({ eventType });
|
||||
|
||||
expect(result).toEqual({
|
||||
theme: "light",
|
||||
brandColor: "#AAAAAA",
|
||||
darkBrandColor: "#BBBBBB",
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("getBrandingForUser", () => {
|
||||
it("should use organization branding when available", () => {
|
||||
const user = {
|
||||
theme: "light",
|
||||
brandColor: "#AAAAAA",
|
||||
darkBrandColor: "#BBBBBB",
|
||||
profile: {
|
||||
organization: {
|
||||
brandColor: "#111111",
|
||||
darkBrandColor: "#222222",
|
||||
theme: "dark",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const result = getBrandingForUser({ user });
|
||||
|
||||
expect(result).toEqual({
|
||||
theme: "dark",
|
||||
brandColor: "#111111",
|
||||
darkBrandColor: "#222222",
|
||||
});
|
||||
});
|
||||
|
||||
it("should fallback to user branding when no organization", () => {
|
||||
const user = {
|
||||
theme: "light",
|
||||
brandColor: "#AAAAAA",
|
||||
darkBrandColor: "#BBBBBB",
|
||||
profile: {
|
||||
organization: null,
|
||||
},
|
||||
};
|
||||
|
||||
const result = getBrandingForUser({ user });
|
||||
|
||||
expect(result).toEqual({
|
||||
theme: "light",
|
||||
brandColor: "#AAAAAA",
|
||||
darkBrandColor: "#BBBBBB",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("getBrandingForTeam", () => {
|
||||
it("should use parent org branding when available", () => {
|
||||
const team = {
|
||||
brandColor: "#AAAAAA",
|
||||
darkBrandColor: "#BBBBBB",
|
||||
theme: "light",
|
||||
parent: {
|
||||
brandColor: "#111111",
|
||||
darkBrandColor: "#222222",
|
||||
theme: "dark",
|
||||
},
|
||||
};
|
||||
|
||||
const result = getBrandingForTeam({ team });
|
||||
|
||||
expect(result).toEqual({
|
||||
theme: "dark",
|
||||
brandColor: "#111111",
|
||||
darkBrandColor: "#222222",
|
||||
});
|
||||
});
|
||||
|
||||
it("should fallback to team branding when no parent", () => {
|
||||
const team = {
|
||||
brandColor: "#AAAAAA",
|
||||
darkBrandColor: "#BBBBBB",
|
||||
theme: "light",
|
||||
parent: null,
|
||||
};
|
||||
|
||||
const result = getBrandingForTeam({ team });
|
||||
|
||||
expect(result).toEqual({
|
||||
theme: "light",
|
||||
brandColor: "#AAAAAA",
|
||||
darkBrandColor: "#BBBBBB",
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,98 @@
|
||||
type EventTypeWithBranding = {
|
||||
team?: {
|
||||
name?: string;
|
||||
brandColor?: string | null;
|
||||
darkBrandColor?: string | null;
|
||||
theme?: string | null;
|
||||
parent?: {
|
||||
brandColor?: string | null;
|
||||
darkBrandColor?: string | null;
|
||||
theme?: string | null;
|
||||
} | null;
|
||||
} | null;
|
||||
profile?: {
|
||||
organization?: {
|
||||
brandColor?: string | null;
|
||||
darkBrandColor?: string | null;
|
||||
theme?: string | null;
|
||||
} | null;
|
||||
} | null;
|
||||
users: Array<{
|
||||
theme?: string | null;
|
||||
brandColor?: string | null;
|
||||
darkBrandColor?: string | null;
|
||||
}>;
|
||||
};
|
||||
|
||||
type UserWithBranding = {
|
||||
theme?: string | null;
|
||||
brandColor?: string | null;
|
||||
darkBrandColor?: string | null;
|
||||
profile: {
|
||||
organization?: {
|
||||
brandColor?: string | null;
|
||||
darkBrandColor?: string | null;
|
||||
theme?: string | null;
|
||||
} | null;
|
||||
};
|
||||
};
|
||||
|
||||
type TeamWithBranding = {
|
||||
brandColor?: string | null;
|
||||
darkBrandColor?: string | null;
|
||||
theme?: string | null;
|
||||
parent?: {
|
||||
brandColor?: string | null;
|
||||
darkBrandColor?: string | null;
|
||||
theme?: string | null;
|
||||
} | null;
|
||||
};
|
||||
|
||||
type BrandingResult = {
|
||||
theme: string | null;
|
||||
brandColor: string | null;
|
||||
darkBrandColor: string | null;
|
||||
};
|
||||
|
||||
export function getBrandingForEventType(params: { eventType: EventTypeWithBranding }): BrandingResult {
|
||||
const { eventType } = params;
|
||||
|
||||
if (eventType.team) {
|
||||
const brandColorData =
|
||||
eventType.team.parent?.brandColor || eventType.team.parent?.darkBrandColor
|
||||
? eventType.team.parent
|
||||
: eventType.team;
|
||||
return {
|
||||
theme: eventType.team.parent?.theme ?? eventType.team.theme ?? null,
|
||||
brandColor: brandColorData.brandColor ?? null,
|
||||
darkBrandColor: brandColorData.darkBrandColor ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
const branding = eventType.profile?.organization ?? eventType.users[0];
|
||||
return {
|
||||
theme: branding?.theme ?? null,
|
||||
brandColor: branding?.brandColor ?? null,
|
||||
darkBrandColor: branding?.darkBrandColor ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
export function getBrandingForUser(params: { user: UserWithBranding }): BrandingResult {
|
||||
const { user } = params;
|
||||
const branding = user.profile.organization ?? user;
|
||||
return {
|
||||
theme: branding.theme ?? null,
|
||||
brandColor: branding.brandColor ?? null,
|
||||
darkBrandColor: branding.darkBrandColor ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
export function getBrandingForTeam(params: { team: TeamWithBranding }): BrandingResult {
|
||||
const { team } = params;
|
||||
const brandColorData = team.parent?.brandColor || team.parent?.darkBrandColor ? team.parent : team;
|
||||
return {
|
||||
theme: team.parent?.theme ?? team.theme ?? null,
|
||||
brandColor: brandColorData.brandColor ?? null,
|
||||
darkBrandColor: brandColorData.darkBrandColor ?? null,
|
||||
};
|
||||
}
|
||||
@@ -50,6 +50,9 @@ const organizationSelect = {
|
||||
bannerUrl: true,
|
||||
isPlatform: true,
|
||||
hideBranding: true,
|
||||
brandColor: true,
|
||||
darkBrandColor: true,
|
||||
theme: true,
|
||||
};
|
||||
const organizationWithSettingsSelect = {
|
||||
...organizationSelect,
|
||||
@@ -496,6 +499,9 @@ export class ProfileRepository {
|
||||
isPrivate: true,
|
||||
isPlatform: true,
|
||||
hideBranding: true,
|
||||
brandColor: true,
|
||||
darkBrandColor: true,
|
||||
theme: true,
|
||||
organizationSettings: {
|
||||
select: {
|
||||
lockEventTypeCreationForUsers: true,
|
||||
|
||||
Reference in New Issue
Block a user