feat: add cal video logo whitelabel for organization (#12616)

This commit is contained in:
Udit Takkar 2023-12-09 14:32:14 +05:30 committed by GitHub
parent 090b166b1c
commit e9ea0fcc20
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 115 additions and 35 deletions

View File

@ -76,15 +76,27 @@ export default function JoinCall(props: JoinCallPageProps) {
<meta property="twitter:description" content={t("quick_video_meeting")} />
</Head>
<div style={{ zIndex: 2, position: "relative" }}>
<img
className="h-5·w-auto fixed z-10 hidden sm:inline-block"
src={`${WEBSITE_URL}/cal-logo-word-dark.svg`}
alt="Cal.com Logo"
style={{
top: 46,
left: 24,
}}
/>
{booking?.user?.organization?.calVideoLogo ? (
<img
className="min-w-16 min-h-16 fixed z-10 hidden aspect-square h-16 w-16 rounded-full sm:inline-block"
src={booking.user.organization.calVideoLogo}
alt="My Org Logo"
style={{
top: 32,
left: 32,
}}
/>
) : (
<img
className="fixed z-10 hidden sm:inline-block"
src={`${WEBSITE_URL}/cal-logo-word-dark.svg`}
alt="Logo"
style={{
top: 32,
left: 32,
}}
/>
)}
</div>
<VideoMeetingInfo booking={booking} />
</>
@ -260,6 +272,11 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
timeZone: true,
name: true,
email: true,
organization: {
select: {
calVideoLogo: true,
},
},
},
},
references: {

View File

@ -1994,7 +1994,7 @@
"select_time": "اختيار الوقت",
"select_date": "اختيار التاريخ",
"see_all_available_times": "رؤية كل الأوقات المتاحة",
"org_team_names_example": "مثال، فريق التسويق",
"org_team_names_example_1": "مثال، فريق التسويق",
"org_team_names_example_2": "مثال، فريق المبيعات",
"org_team_names_example_3": "مثال، فريق التصميم",
"org_team_names_example_4": "مثال، الفريق الهندسي",

View File

@ -1994,7 +1994,7 @@
"select_time": "Vyberte čas",
"select_date": "Vyberte datum",
"see_all_available_times": "Zobrazit všechny dostupné časy",
"org_team_names_example": "Např. marketingový tým",
"org_team_names_example_1": "Např. marketingový tým",
"org_team_names_example_2": "Např. obchodní tým",
"org_team_names_example_3": "Např. designérský tým",
"org_team_names_example_4": "Např. inženýrský tým",

View File

@ -1994,7 +1994,7 @@
"select_time": "Zeit auswählen",
"select_date": "Datum auswählen",
"see_all_available_times": "Alle verfügbaren Zeiten ansehen",
"org_team_names_example": "z.B. Marketing-Team",
"org_team_names_example_1": "z.B. Marketing-Team",
"org_team_names_example_2": "z.B. Vertriebsteam",
"org_team_names_example_3": "z. B. Design-Team",
"org_team_names_example_4": "z.B. Engineering-Team",

View File

@ -2025,7 +2025,7 @@
"select_time": "Select Time",
"select_date": "Select Date",
"see_all_available_times": "See all available times",
"org_team_names_example": "e.g. Marketing Team",
"org_team_names_example_1": "e.g. Marketing Team",
"org_team_names_example_2": "e.g. Sales Team",
"org_team_names_example_3": "e.g. Design Team",
"org_team_names_example_4": "e.g. Engineering Team",
@ -2041,6 +2041,9 @@
"description_requires_booker_email_verification": "To ensure booker's email verification before scheduling events",
"requires_confirmation_mandatory": "Text messages can only be sent to attendees when event type requires confirmation.",
"organizations": "Organizations",
"upload_cal_video_logo":"Upload Cal Video Logo",
"update_cal_video_logo":"Update Cal Video Logo",
"cal_video_logo_upload_instruction":"To ensure your logo is visible against Cal video's dark background, please upload a light-colored image in PNG or SVG format to maintain transparency.",
"org_admin_other_teams": "Other teams",
"org_admin_other_teams_description": "Here you can see teams inside your organization that you are not part of. You can add yourself to them if needed.",
"no_other_teams_found": "No other teams found",
@ -2088,7 +2091,7 @@
"oAuth": "OAuth",
"recently_added":"Recently added",
"connect_all_calendars":"Connect all your calendars",
"connect_all_calendars_description":"{{appName}} reads availability from all your existing calendars.",
"connect_all_calendars_description":"{{appName}} reads availability from all your existing calendars.",
"workflow_automation":"Workflow automation",
"workflow_automation_description":"Personalise your scheduling experience with workflows",
"scheduling_for_your_team":"Workflow automation",

View File

@ -1994,7 +1994,7 @@
"select_time": "Seleccione la hora",
"select_date": "Seleccione la fecha",
"see_all_available_times": "Ver todas las horas disponibles",
"org_team_names_example": "ej. Equipo de marketing",
"org_team_names_example_1": "ej. Equipo de marketing",
"org_team_names_example_2": "ej. Equipo de ventas",
"org_team_names_example_3": "ej. Equipo de diseño",
"org_team_names_example_4": "ej. Equipo de ingeniería",

View File

@ -2000,7 +2000,7 @@
"select_time": "Sélectionner un créneau",
"select_date": "Sélectionner une date",
"see_all_available_times": "Voir tous les créneaux disponibles",
"org_team_names_example": "p. ex. Équipe marketing",
"org_team_names_example_1": "p. ex. Équipe marketing",
"org_team_names_example_2": "p. ex. Équipe de vente",
"org_team_names_example_3": "p. ex. Équipe de design",
"org_team_names_example_4": "p. ex. Équipe d'ingénierie",

View File

@ -1994,7 +1994,7 @@
"select_time": "בחירת שעה",
"select_date": "בחירת תאריך",
"see_all_available_times": "לצפייה בכל המועדים הפנויים",
"org_team_names_example": "לדוגמה, מחלקת שיווק",
"org_team_names_example_1": "לדוגמה, מחלקת שיווק",
"org_team_names_example_2": "לדוגמה, מחלקת מכירות",
"org_team_names_example_3": "לדוגמה, מחלקת עיצוב",
"org_team_names_example_4": "לדוגמה, מחלקת הנדסה",

View File

@ -1994,7 +1994,7 @@
"select_time": "Seleziona l'ora",
"select_date": "Seleziona la data",
"see_all_available_times": "Vedi tutti gli orari disponibili",
"org_team_names_example": "ad es., team di marketing",
"org_team_names_example_1": "ad es., team di marketing",
"org_team_names_example_2": "ad es., team vendite",
"org_team_names_example_3": "ad es., team di progettazione",
"org_team_names_example_4": "ad es., team di ingegneria",

View File

@ -1994,7 +1994,7 @@
"select_time": "時間帯を選ぶ",
"select_date": "日付を選ぶ",
"see_all_available_times": "出席できる時間帯をすべて表示",
"org_team_names_example": "例:マーケティングチーム",
"org_team_names_example_1": "例:マーケティングチーム",
"org_team_names_example_2": "例:営業チーム",
"org_team_names_example_3": "例:デザインチーム",
"org_team_names_example_4": "例:エンジニアリングチーム",

View File

@ -1994,7 +1994,7 @@
"select_time": "시간 선택",
"select_date": "날짜 선택",
"see_all_available_times": "모든 사용 가능한 시간 보기",
"org_team_names_example": "예: 마케팅 팀",
"org_team_names_example_1": "예: 마케팅 팀",
"org_team_names_example_2": "예: 세일즈 팀",
"org_team_names_example_3": "예: 디자인 팀",
"org_team_names_example_4": "예: 엔지니어링 팀",

View File

@ -1994,7 +1994,7 @@
"select_time": "Tijd selecteren",
"select_date": "Datum selecteren",
"see_all_available_times": "Bekijk alle beschikbare tijden",
"org_team_names_example": "bijvoorbeeld Marketingteam",
"org_team_names_example_1": "bijvoorbeeld Marketingteam",
"org_team_names_example_2": "bijvoorbeeld Verkoopteam",
"org_team_names_example_3": "bijvoorbeeld Ontwerpteam",
"org_team_names_example_4": "bijvoorbeeld Engineeringteam",

View File

@ -1994,7 +1994,7 @@
"select_time": "Wybierz godzinę",
"select_date": "Wybierz datę",
"see_all_available_times": "Zobacz wszystkie dostępne godziny",
"org_team_names_example": "np. zespół marketingowy",
"org_team_names_example_1": "np. zespół marketingowy",
"org_team_names_example_2": "np. zespół ds. sprzedaży",
"org_team_names_example_3": "np. zespół projektowy",
"org_team_names_example_4": "np. zespół ds. inżynierii",

View File

@ -1994,7 +1994,7 @@
"select_time": "Selecione o horário",
"select_date": "Selecione a data",
"see_all_available_times": "Veja todos os horários disponíveis",
"org_team_names_example": "ex.: Time de Marketing",
"org_team_names_example_1": "ex.: Time de Marketing",
"org_team_names_example_2": "ex: Time de Vendas",
"org_team_names_example_3": "ex: Time de Design",
"org_team_names_example_4": "ex: Time de Engenharia",

View File

@ -1994,7 +1994,7 @@
"select_time": "Selecionar horário",
"select_date": "Selecionar data",
"see_all_available_times": "Ver todos os horários disponíveis",
"org_team_names_example": "Por exemplo, Equipa de Marketing",
"org_team_names_example_1": "Por exemplo, Equipa de Marketing",
"org_team_names_example_2": "Por exemplo, Equipa de Vendas",
"org_team_names_example_3": "Por exemplo, Equipa de Design",
"org_team_names_example_4": "Por exemplo, Equipa de Engenharia",

View File

@ -1994,7 +1994,7 @@
"select_time": "Selectați ora",
"select_date": "Selectați data",
"see_all_available_times": "Vedeți toate orele disponibile",
"org_team_names_example": "de ex. echipa de marketing",
"org_team_names_example_1": "de ex. echipa de marketing",
"org_team_names_example_2": "de ex. echipa de vânzări",
"org_team_names_example_3": "de ex. echipa de design",
"org_team_names_example_4": "de ex. echipa de inginerie",

View File

@ -1994,7 +1994,7 @@
"select_time": "Выбрать время",
"select_date": "Выбрать дату",
"see_all_available_times": "Посмотреть все доступные интервалы времени",
"org_team_names_example": "например, команда по маркетингу",
"org_team_names_example_1": "например, команда по маркетингу",
"org_team_names_example_2": "например, Отдел продаж",
"org_team_names_example_3": "например, отдел дизайна",
"org_team_names_example_4": "например, технический отдел",

View File

@ -1994,7 +1994,7 @@
"select_time": "Izaberite vreme",
"select_date": "Izaberite datum",
"see_all_available_times": "Pogledajte sva dostupna vremena",
"org_team_names_example": "npr. Marketing tim",
"org_team_names_example_1": "npr. Marketing tim",
"org_team_names_example_2": "npr. Prodajni tim",
"org_team_names_example_3": "npr. Dizajnerski tim",
"org_team_names_example_4": "npr. Inženjerski tim",

View File

@ -1994,7 +1994,7 @@
"select_time": "Välj tid",
"select_date": "Välj datum",
"see_all_available_times": "Se alla tillgängliga tider",
"org_team_names_example": "t.ex. marknadsföringsteam",
"org_team_names_example_1": "t.ex. marknadsföringsteam",
"org_team_names_example_2": "t.ex. säljteam",
"org_team_names_example_3": "t.ex. designteam",
"org_team_names_example_4": "t.ex. ingenjörsteam",

View File

@ -1994,7 +1994,7 @@
"select_time": "Saati Seçin",
"select_date": "Tarihi Seçin",
"see_all_available_times": "Tüm müsait saatleri görün",
"org_team_names_example": "Örneğin. Pazarlama ekibi",
"org_team_names_example_1": "Örneğin. Pazarlama ekibi",
"org_team_names_example_2": "Örn. Satış Ekibi",
"org_team_names_example_3": "Örn. Tasarım Ekibi",
"org_team_names_example_4": "Örn. Mühendislik Ekibi",

View File

@ -1994,7 +1994,7 @@
"select_time": "Виберіть час",
"select_date": "Виберіть дату",
"see_all_available_times": "Переглянути доступні часові проміжки",
"org_team_names_example": "напр. команда маркетингу",
"org_team_names_example_1": "напр. команда маркетингу",
"org_team_names_example_2": "напр. відділ продажів",
"org_team_names_example_3": "напр. дизайнерський відділ",
"org_team_names_example_4": "e.g. інженерний відділ",

View File

@ -1994,7 +1994,7 @@
"select_time": "Chọn thời gian",
"select_date": "Chọn ngày",
"see_all_available_times": "Xem tất cả những thời gian trống",
"org_team_names_example": "ví dụ Nhóm Tiếp thị",
"org_team_names_example_1": "ví dụ Nhóm Tiếp thị",
"org_team_names_example_2": "ví dụ Nhóm Kinh doanh",
"org_team_names_example_3": "ví dụ Nhóm Thiết kế",
"org_team_names_example_4": "ví dụ Nhóm Kỹ thuật",

View File

@ -1995,7 +1995,7 @@
"select_time": "选择时间",
"select_date": "选择日期",
"see_all_available_times": "查看所有可预约时间",
"org_team_names_example": "例如,营销团队",
"org_team_names_example_1": "例如,营销团队",
"org_team_names_example_2": "例如,销售团队",
"org_team_names_example_3": "例如,设计团队",
"org_team_names_example_4": "例如,工程团队",

View File

@ -1994,7 +1994,7 @@
"select_time": "選取時間",
"select_date": "選取日期",
"see_all_available_times": "查看所有可預約時段",
"org_team_names_example": "例如行銷團隊",
"org_team_names_example_1": "例如行銷團隊",
"org_team_names_example_2": "例如銷售團隊",
"org_team_names_example_3": "例如設計團隊",
"org_team_names_example_4": "例如工程團隊",

View File

@ -110,7 +110,7 @@ export const AddNewTeamsForm = () => {
onChange={(e) => handleInputChange(index, e)}
addOnClassname="bg-transparent p-0 border-l-0"
className={index > 0 ? "mb-2" : ""}
placeholder={t(`org_team_names_example_${index + 1}`) || t("org_team_names_example")}
placeholder={t(`org_team_names_example_${index + 1}`) || t("org_team_names_example_1")}
addOnSuffix={
index > 0 && (
<Button

View File

@ -14,7 +14,8 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
import { MembershipRole } from "@calcom/prisma/enums";
import { trpc } from "@calcom/trpc/react";
import type { RouterOutputs } from "@calcom/trpc/react";
import { Button, Form, Meta, showToast, SettingsToggle } from "@calcom/ui";
import { Button, Form, Meta, showToast, SettingsToggle, Avatar, ImageUploader } from "@calcom/ui";
import { Plus } from "@calcom/ui/components/icon";
type BrandColorsFormValues = {
brandColor: string;
@ -83,6 +84,48 @@ const OrgAppearanceView = ({
/>
{isAdminOrOwner ? (
<div>
<div className="my-6">
<div className="flex items-center text-sm">
<Avatar
alt="calVideoLogo"
imageSrc={currentOrg?.calVideoLogo}
fallback={<Plus className="text-subtle h-6 w-6" />}
size="lg"
/>
<div className="ms-4">
<div className="flex gap-2">
<ImageUploader
target="avatar"
id="cal-video-logo-upload"
buttonMsg={
currentOrg?.calVideoLogo ? t("update_cal_video_logo") : t("upload_cal_video_logo")
}
handleAvatarChange={(newLogo) => {
mutation.mutate({
calVideoLogo: newLogo,
});
}}
disabled={mutation.isLoading}
imageSrc={currentOrg?.calVideoLogo ?? undefined}
uploadInstruction={t("cal_video_logo_upload_instruction")}
triggerButtonColor={currentOrg?.calVideoLogo ? "secondary" : "primary"}
/>
{currentOrg?.calVideoLogo && (
<Button
color="destructive"
disabled={mutation.isLoading}
onClick={() => {
mutation.mutate({
calVideoLogo: null,
});
}}>
{t("remove")}
</Button>
)}
</div>
</div>
</div>
</div>
<Form
form={themeForm}
handleSubmit={(value) => {

View File

@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "Team" ADD COLUMN "calVideoLogo" TEXT;

View File

@ -282,6 +282,7 @@ model Team {
slug String?
logo String?
logoUrl String?
calVideoLogo String?
appLogo String?
appIconLogo String?
bio String?

View File

@ -61,6 +61,7 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {
const data: Prisma.TeamUpdateArgs["data"] = {
name: input.name,
logo: input.logo,
calVideoLogo: input.calVideoLogo,
bio: input.bio,
hideBranding: input.hideBranding,
hideBookATeamMember: input.hideBookATeamMember,

View File

@ -16,6 +16,11 @@ export const ZUpdateInputSchema = z.object({
.optional()
.nullable()
.transform((v) => v || null),
calVideoLogo: z
.string()
.optional()
.nullable()
.transform((v) => v || null),
slug: z.string().optional(),
hideBranding: z.boolean().optional(),
hideBookATeamMember: z.boolean().optional(),

View File

@ -68,6 +68,8 @@ type ImageUploaderProps = {
imageSrc?: string;
target: string;
triggerButtonColor?: ButtonColor;
uploadInstruction?: string;
disabled?: boolean;
};
interface FileEvent<T = Element> extends FormEvent<T> {
@ -122,6 +124,8 @@ export default function ImageUploader({
handleAvatarChange,
triggerButtonColor,
imageSrc,
uploadInstruction,
disabled = false,
}: ImageUploaderProps) {
const { t } = useLocale();
const [croppedAreaPixels, setCroppedAreaPixels] = useState<Area | null>(null);
@ -173,6 +177,7 @@ export default function ImageUploader({
<Button
color={triggerButtonColor ?? "secondary"}
type="button"
disabled={disabled}
data-testid="open-upload-avatar-dialog"
className="cursor-pointer py-1 text-sm">
{buttonMsg}
@ -207,6 +212,9 @@ export default function ImageUploader({
/>
{t("choose_a_file")}
</label>
{uploadInstruction && (
<p className="text-muted mt-4 text-center text-sm">({uploadInstruction})</p>
)}
</div>
</div>
<DialogFooter className="relative">