2023-03-14 04:19:05 +00:00
import type { DestinationCalendar , Booking } from "@prisma/client" ;
2023-03-23 18:49:28 +00:00
import { cloneDeep , merge } from "lodash" ;
2021-09-22 19:52:38 +00:00
import { v5 as uuidv5 } from "uuid" ;
2023-02-25 03:57:49 +00:00
import type { z } from "zod" ;
2021-09-22 19:52:38 +00:00
2023-03-14 04:19:05 +00:00
import { getCalendar } from "@calcom/app-store/_utils/getCalendar" ;
2022-06-04 17:23:56 +00:00
import { FAKE_DAILY_CREDENTIAL } from "@calcom/app-store/dailyvideo/lib/VideoApiAdapter" ;
2023-07-20 16:57:10 +00:00
import { appKeysSchema as calVideoKeysSchema } from "@calcom/app-store/dailyvideo/zod" ;
2022-08-26 00:48:50 +00:00
import { getEventLocationTypeFromApp } from "@calcom/app-store/locations" ;
2023-01-10 02:01:57 +00:00
import { MeetLocationType } from "@calcom/app-store/locations" ;
2022-03-23 22:00:30 +00:00
import getApps from "@calcom/app-store/utils" ;
import prisma from "@calcom/prisma" ;
2022-09-05 19:13:49 +00:00
import { createdEventSchema } from "@calcom/prisma/zod-utils" ;
2023-04-03 17:13:57 +00:00
import type { NewCalendarEventType } from "@calcom/types/Calendar" ;
import type { AdditionalInformation , CalendarEvent } from "@calcom/types/Calendar" ;
2023-02-25 03:57:49 +00:00
import type { CredentialPayload , CredentialWithAppName } from "@calcom/types/Credential" ;
2022-06-17 18:34:41 +00:00
import type { Event } from "@calcom/types/Event" ;
2023-04-03 17:13:57 +00:00
import type { EventResult } from "@calcom/types/EventManager" ;
import type { CreateUpdateResult , PartialBooking , PartialReference } from "@calcom/types/EventManager" ;
2022-03-23 22:00:30 +00:00
import { createEvent , updateEvent } from "./CalendarManager" ;
import { createMeeting , updateMeeting } from "./videoClient" ;
2021-07-15 01:19:30 +00:00
2021-11-26 11:03:43 +00:00
export const isDedicatedIntegration = ( location : string ) : boolean = > {
2023-01-10 02:01:57 +00:00
return location !== MeetLocationType && location . includes ( "integrations:" ) ;
2021-11-26 11:03:43 +00:00
} ;
export const getLocationRequestFromIntegration = ( location : string ) = > {
2022-08-26 00:48:50 +00:00
const eventLocationType = getEventLocationTypeFromApp ( location ) ;
if ( eventLocationType ) {
2021-11-26 11:03:43 +00:00
const requestId = uuidv5 ( location , uuidv5 . URL ) ;
return {
conferenceData : {
createRequest : {
requestId : requestId ,
} ,
} ,
location ,
} ;
}
return null ;
} ;
export const processLocation = ( event : CalendarEvent ) : CalendarEvent = > {
// If location is set to an integration location
// Build proper transforms for evt object
// Extend evt object with those transformations
2022-08-26 00:48:50 +00:00
// TODO: Rely on linkType:"dynamic" here. static links don't send their type. They send their URL directly.
2021-11-26 11:03:43 +00:00
if ( event . location ? . includes ( "integration" ) ) {
const maybeLocationRequestObject = getLocationRequestFromIntegration ( event . location ) ;
event = merge ( event , maybeLocationRequestObject ) ;
}
return event ;
} ;
2021-07-25 12:19:49 +00:00
2023-02-25 03:57:49 +00:00
export type EventManagerUser = {
2022-10-31 22:06:03 +00:00
credentials : CredentialPayload [ ] ;
2021-12-09 15:51:37 +00:00
destinationCalendar : DestinationCalendar | null ;
} ;
2022-03-23 22:00:30 +00:00
2022-09-05 19:13:49 +00:00
type createdEventSchema = z . infer < typeof createdEventSchema > ;
2021-07-15 01:19:30 +00:00
export default class EventManager {
2022-10-31 22:06:03 +00:00
calendarCredentials : CredentialWithAppName [ ] ;
videoCredentials : CredentialWithAppName [ ] ;
2021-07-15 01:19:30 +00:00
2021-07-24 20:30:14 +00:00
/ * *
* Takes an array of credentials and initializes a new instance of the EventManager .
*
2022-03-23 22:00:30 +00:00
* @param user
2021-07-24 20:30:14 +00:00
* /
2021-12-09 15:51:37 +00:00
constructor ( user : EventManagerUser ) {
2022-10-19 16:11:50 +00:00
const appCredentials = getApps ( user . credentials ) . flatMap ( ( app ) = >
app . credentials . map ( ( creds ) = > ( { . . . creds , appName : app.name } ) )
) ;
2022-11-01 16:07:28 +00:00
// This includes all calendar-related apps, traditional calendars such as Google Calendar
// (type google_calendar) and non-traditional calendars such as CRMs like Close.com
// (type closecom_other_calendar)
2022-03-23 22:00:30 +00:00
this . calendarCredentials = appCredentials . filter ( ( cred ) = > cred . type . endsWith ( "_calendar" ) ) ;
this . videoCredentials = appCredentials . filter ( ( cred ) = > cred . type . endsWith ( "_video" ) ) ;
2021-07-15 01:19:30 +00:00
}
2021-07-24 20:30:14 +00:00
/ * *
* Takes a CalendarEvent and creates all necessary integration entries for it .
* When a video integration is chosen as the event ' s location , a video integration
* event will be scheduled for it as well .
*
* @param event
* /
2022-01-27 20:32:53 +00:00
public async create ( event : CalendarEvent ) : Promise < CreateUpdateResult > {
2021-11-26 11:03:43 +00:00
const evt = processLocation ( event ) ;
2022-12-01 15:20:01 +00:00
// Fallback to cal video if no location is set
2023-07-20 16:57:10 +00:00
if ( ! evt . location ) {
// See if cal video is enabled & has keys
const calVideo = await prisma . app . findFirst ( {
where : {
slug : "daily-video" ,
} ,
select : {
keys : true ,
enabled : true ,
} ,
} ) ;
const calVideoKeys = calVideoKeysSchema . safeParse ( calVideo ? . keys ) ;
if ( calVideo ? . enabled && calVideoKeys . success ) evt [ "location" ] = "integrations:daily" ;
}
2023-01-10 02:01:57 +00:00
// Fallback to Cal Video if Google Meet is selected w/o a Google Cal
if ( evt . location === MeetLocationType && evt . destinationCalendar ? . integration !== "google_calendar" ) {
evt [ "location" ] = "integrations:daily" ;
}
2021-11-26 11:03:43 +00:00
const isDedicated = evt . location ? isDedicatedIntegration ( evt . location ) : null ;
2021-07-20 18:07:59 +00:00
2022-06-17 18:34:41 +00:00
const results : Array < EventResult < Exclude < Event , AdditionalInformation > >> = [ ] ;
2023-01-10 02:01:57 +00:00
2021-09-22 22:43:10 +00:00
// If and only if event type is a dedicated meeting, create a dedicated video meeting.
2021-08-01 21:29:15 +00:00
if ( isDedicated ) {
2021-10-25 13:05:21 +00:00
const result = await this . createVideoEvent ( evt ) ;
2022-10-26 20:16:38 +00:00
2022-12-01 15:20:01 +00:00
if ( result ? . createdEvent ) {
2021-11-26 11:03:43 +00:00
evt . videoCallData = result . createdEvent ;
2022-10-26 20:16:38 +00:00
evt . location = result . originalEvent . location ;
result . type = result . createdEvent . type ;
2021-09-22 22:43:10 +00:00
}
2021-12-02 17:18:17 +00:00
2021-09-22 22:43:10 +00:00
results . push ( result ) ;
2021-07-15 01:19:30 +00:00
}
2023-03-14 04:19:05 +00:00
// Some calendar libraries may edit the original event so let's clone it
const clonedCalEvent = cloneDeep ( event ) ;
2021-12-02 17:18:17 +00:00
// Create the calendar event with the proper video call data
2023-03-14 04:19:05 +00:00
results . push ( . . . ( await this . createAllCalendarEvents ( clonedCalEvent ) ) ) ;
2021-12-02 17:18:17 +00:00
2023-04-03 17:13:57 +00:00
// Since the result can be a new calendar event or video event, we have to create a type guard
// https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates
const isCalendarResult = (
result : ( typeof results ) [ number ]
) : result is EventResult < NewCalendarEventType > = > {
return result . type . includes ( "_calendar" ) ;
} ;
2023-07-06 21:39:33 +00:00
// References can be any type: calendar/video
2022-06-17 18:34:41 +00:00
const referencesToCreate = results . map ( ( result ) = > {
2022-09-05 19:13:49 +00:00
let createdEventObj : createdEventSchema | null = null ;
if ( typeof result ? . createdEvent === "string" ) {
createdEventObj = createdEventSchema . parse ( JSON . parse ( result . createdEvent ) ) ;
}
2023-07-06 21:39:33 +00:00
const isCalendarType = isCalendarResult ( result ) ;
if ( isCalendarType ) {
2023-04-03 17:13:57 +00:00
evt . iCalUID = result . iCalUID || undefined ;
}
2021-10-25 13:05:21 +00:00
return {
type : result . type ,
2022-09-05 19:13:49 +00:00
uid : createdEventObj ? createdEventObj.id : result.createdEvent?.id?.toString ( ) ? ? "" ,
meetingId : createdEventObj ? createdEventObj.id : result.createdEvent?.id?.toString ( ) ,
meetingPassword : createdEventObj ? createdEventObj.password : result.createdEvent?.password ,
meetingUrl : createdEventObj ? createdEventObj.onlineMeetingUrl : result.createdEvent?.url ,
2023-07-06 21:39:33 +00:00
externalCalendarId : isCalendarType ? evt.destinationCalendar?.externalId : undefined ,
credentialId : isCalendarType ? evt.destinationCalendar?.credentialId : result.credentialId ,
2022-08-08 19:38:02 +00:00
} ;
} ) ;
return {
results ,
referencesToCreate ,
} ;
}
public async updateLocation ( event : CalendarEvent , booking : PartialBooking ) : Promise < CreateUpdateResult > {
const evt = processLocation ( event ) ;
const isDedicated = evt . location ? isDedicatedIntegration ( evt . location ) : null ;
const results : Array < EventResult < Exclude < Event , AdditionalInformation > >> = [ ] ;
// If and only if event type is a dedicated meeting, create a dedicated video meeting.
if ( isDedicated ) {
const result = await this . createVideoEvent ( evt ) ;
if ( result . createdEvent ) {
evt . videoCallData = result . createdEvent ;
}
results . push ( result ) ;
}
// Update the calendar event with the proper video call data
2022-08-12 20:46:40 +00:00
const calendarReference = booking . references . find ( ( reference ) = > reference . type . includes ( "_calendar" ) ) ;
if ( calendarReference ) {
results . push ( . . . ( await this . updateAllCalendarEvents ( evt , booking ) ) ) ;
}
2022-08-08 19:38:02 +00:00
const referencesToCreate = results . map ( ( result ) = > {
return {
type : result . type ,
uid : result.createdEvent?.id?.toString ( ) ? ? "" ,
meetingId : result.createdEvent?.id?.toString ( ) ,
meetingPassword : result.createdEvent?.password ,
meetingUrl : result.createdEvent?.url ,
2022-05-16 20:20:09 +00:00
externalCalendarId : evt.destinationCalendar?.externalId ,
2023-07-06 21:39:33 +00:00
credentialId : result.credentialId ? ? evt . destinationCalendar ? . credentialId ,
2021-10-25 13:05:21 +00:00
} ;
2021-07-24 20:24:00 +00:00
} ) ;
return {
results ,
referencesToCreate ,
} ;
2021-07-15 01:19:30 +00:00
}
2021-07-24 20:30:14 +00:00
/ * *
* Takes a calendarEvent and a rescheduleUid and updates the event that has the
* given uid using the data delivered in the given CalendarEvent .
*
* @param event
* /
2022-07-12 13:16:34 +00:00
public async reschedule (
2022-04-14 21:25:24 +00:00
event : CalendarEvent ,
rescheduleUid : string ,
2023-03-14 04:19:05 +00:00
newBookingId? : number
2022-04-14 21:25:24 +00:00
) : Promise < CreateUpdateResult > {
2023-03-14 04:19:05 +00:00
const originalEvt = processLocation ( event ) ;
const evt = cloneDeep ( originalEvt ) ;
2021-11-09 16:27:33 +00:00
if ( ! rescheduleUid ) {
throw new Error ( "You called eventManager.update without an `rescheduleUid`. This should never happen." ) ;
2021-10-25 13:05:21 +00:00
}
2021-07-25 12:19:49 +00:00
2021-07-24 20:24:00 +00:00
// Get details of existing booking.
const booking = await prisma . booking . findFirst ( {
where : {
2021-11-09 16:27:33 +00:00
uid : rescheduleUid ,
2021-07-24 20:24:00 +00:00
} ,
select : {
id : true ,
2022-07-18 15:37:47 +00:00
userId : true ,
2023-03-14 04:19:05 +00:00
attendees : true ,
2021-07-24 20:24:00 +00:00
references : {
2022-03-24 23:29:32 +00:00
// NOTE: id field removed from select as we don't require for deletingMany
// but was giving error on recreate for reschedule, probably because promise.all() didn't finished
2021-07-24 20:24:00 +00:00
select : {
type : true ,
uid : true ,
2021-09-22 22:43:10 +00:00
meetingId : true ,
meetingPassword : true ,
meetingUrl : true ,
2022-05-16 20:20:09 +00:00
externalCalendarId : true ,
2022-07-18 15:37:47 +00:00
credentialId : true ,
2021-07-24 20:24:00 +00:00
} ,
} ,
2021-12-09 15:51:37 +00:00
destinationCalendar : true ,
2022-04-14 21:25:24 +00:00
payment : true ,
2023-03-14 04:19:05 +00:00
eventType : {
select : {
seatsPerTimeSlot : true ,
seatsShowAttendees : true ,
} ,
} ,
2021-07-24 20:24:00 +00:00
} ,
} ) ;
2021-10-25 13:05:21 +00:00
if ( ! booking ) {
throw new Error ( "booking not found" ) ;
}
2021-11-26 11:03:43 +00:00
const isDedicated = evt . location ? isDedicatedIntegration ( evt . location ) : null ;
2022-06-17 18:34:41 +00:00
const results : Array < EventResult < Event > > = [ ] ;
2021-09-22 22:43:10 +00:00
// If and only if event type is a dedicated meeting, update the dedicated video meeting.
2021-08-01 21:38:38 +00:00
if ( isDedicated ) {
2021-10-25 13:05:21 +00:00
const result = await this . updateVideoEvent ( evt , booking ) ;
2022-02-10 10:44:46 +00:00
const [ updatedEvent ] = Array . isArray ( result . updatedEvent ) ? result . updatedEvent : [ result . updatedEvent ] ;
2023-03-14 04:19:05 +00:00
2022-02-10 10:44:46 +00:00
if ( updatedEvent ) {
evt . videoCallData = updatedEvent ;
evt . location = updatedEvent . url ;
2021-09-22 22:43:10 +00:00
}
results . push ( result ) ;
2021-07-15 01:19:30 +00:00
}
2021-11-26 11:03:43 +00:00
2023-03-14 04:19:05 +00:00
// There was a case that booking didn't had any reference and we don't want to throw error on function
if ( booking . references . find ( ( reference ) = > reference . type . includes ( "_calendar" ) ) ) {
// Update all calendar events.
results . push ( . . . ( await this . updateAllCalendarEvents ( evt , booking , newBookingId ) ) ) ;
}
2021-12-02 21:41:09 +00:00
2022-04-14 21:25:24 +00:00
const bookingPayment = booking ? . payment ;
// Updating all payment to new
if ( bookingPayment && newBookingId ) {
const paymentIds = bookingPayment . map ( ( payment ) = > payment . id ) ;
await prisma . payment . updateMany ( {
where : {
id : {
in : paymentIds ,
} ,
} ,
data : {
bookingId : newBookingId ,
} ,
} ) ;
}
2021-07-24 20:24:00 +00:00
return {
results ,
referencesToCreate : [ . . . booking . references ] ,
} ;
2021-07-15 01:19:30 +00:00
}
2022-07-12 13:16:34 +00:00
public async updateCalendarAttendees ( event : CalendarEvent , booking : PartialBooking ) {
2023-03-14 04:19:05 +00:00
if ( booking . references . length === 0 ) {
console . error ( "Tried to update references but there wasn't any." ) ;
return ;
}
2022-07-12 13:16:34 +00:00
await this . updateAllCalendarEvents ( event , booking ) ;
}
2021-07-15 01:19:30 +00:00
/ * *
* Creates event entries for all calendar integrations given in the credentials .
2021-07-20 18:07:59 +00:00
* When noMail is true , no mails will be sent . This is used when the event is
* a video meeting because then the mail containing the video credentials will be
* more important than the mails created for these bare calendar events .
2021-07-15 01:19:30 +00:00
*
2021-07-25 15:05:18 +00:00
* When the optional uid is set , it will be used instead of the auto generated uid .
*
2021-07-15 01:19:30 +00:00
* @param event
2021-07-20 18:07:59 +00:00
* @param noMail
2021-07-15 01:19:30 +00:00
* @private
* /
2022-06-17 18:34:41 +00:00
private async createAllCalendarEvents ( event : CalendarEvent ) {
2021-12-09 15:51:37 +00:00
/** Can I use destinationCalendar here? */
/* How can I link a DC to a cred? */
2023-01-31 21:14:19 +00:00
2022-10-15 17:02:24 +00:00
let createdEvents : EventResult < NewCalendarEventType > [ ] = [ ] ;
2021-12-09 15:51:37 +00:00
if ( event . destinationCalendar ) {
2022-07-01 20:55:27 +00:00
if ( event . destinationCalendar . credentialId ) {
2022-10-19 16:11:50 +00:00
const credential = this . calendarCredentials . find (
( c ) = > c . id === event . destinationCalendar ? . credentialId
) ;
2022-07-01 20:55:27 +00:00
if ( credential ) {
2022-11-01 16:07:28 +00:00
const createdEvent = await createEvent ( credential , event ) ;
if ( createdEvent ) {
createdEvents . push ( createdEvent ) ;
}
2022-07-01 20:55:27 +00:00
}
2022-10-15 17:02:24 +00:00
} else {
const destinationCalendarCredentials = this . calendarCredentials . filter (
( c ) = > c . type === event . destinationCalendar ? . integration
) ;
createdEvents = createdEvents . concat (
await Promise . all ( destinationCalendarCredentials . map ( async ( c ) = > await createEvent ( c , event ) ) )
) ;
2022-07-01 20:55:27 +00:00
}
2022-10-15 17:02:24 +00:00
} else {
/ * *
* Not ideal but , if we don ' t find a destination calendar ,
* fallback to the first connected calendar
* /
2022-11-01 16:07:28 +00:00
const [ credential ] = this . calendarCredentials . filter ( ( cred ) = > cred . type === "calendar" ) ;
if ( credential ) {
const createdEvent = await createEvent ( credential , event ) ;
if ( createdEvent ) {
createdEvents . push ( createdEvent ) ;
}
2022-10-15 17:02:24 +00:00
}
2021-12-09 15:51:37 +00:00
}
2022-10-15 17:02:24 +00:00
// Taking care of non-traditional calendar integrations
createdEvents = createdEvents . concat (
await Promise . all (
this . calendarCredentials
. filter ( ( cred ) = > cred . type . includes ( "other_calendar" ) )
. map ( async ( cred ) = > await createEvent ( cred , event ) )
)
) ;
return createdEvents ;
2021-07-15 01:19:30 +00:00
}
2021-07-24 20:30:14 +00:00
/ * *
* Checks which video integration is needed for the event ' s location and returns
* credentials for that - if existing .
* @param event
* @private
* /
2021-10-07 16:12:39 +00:00
2022-10-31 22:06:03 +00:00
private getVideoCredential ( event : CalendarEvent ) : CredentialWithAppName | undefined {
2021-10-25 13:05:21 +00:00
if ( ! event . location ) {
return undefined ;
}
2022-05-02 20:39:35 +00:00
/** @fixme potential bug since Google Meet are saved as `integrations:google:meet` and there are no `google:meet` type in our DB */
2021-07-15 01:19:30 +00:00
const integrationName = event . location . replace ( "integrations:" , "" ) ;
2022-07-06 14:43:57 +00:00
let videoCredential = this . videoCredentials
// Whenever a new video connection is added, latest credentials are added with the highest ID.
2023-03-14 04:19:05 +00:00
// Because you can't rely on having them in the highest first order here, ensure this by sorting in DESC order
2022-07-06 14:43:57 +00:00
. sort ( ( a , b ) = > {
return b . id - a . id ;
} )
2022-10-31 22:06:03 +00:00
. find ( ( credential : CredentialPayload ) = > credential . type . includes ( integrationName ) ) ;
2021-10-07 16:12:39 +00:00
2022-06-04 17:23:56 +00:00
/ * *
* This might happen if someone tries to use a location with a missing credential , so we fallback to Cal Video .
* @todo remove location from event types that has missing credentials
* * /
2022-10-19 16:11:50 +00:00
if ( ! videoCredential ) videoCredential = { . . . FAKE_DAILY_CREDENTIAL , appName : "FAKE" } ;
2022-06-04 17:23:56 +00:00
return videoCredential ;
2021-07-15 01:19:30 +00:00
}
/ * *
* Creates a video event entry for the selected integration location .
*
2021-07-25 15:05:18 +00:00
* When optional uid is set , it will be used instead of the auto generated uid .
*
2021-07-15 01:19:30 +00:00
* @param event
* @private
* /
feat: Enable Apps for Teams & Orgs [CAL-1782] (#9337)
* Initial commit
* Adding feature flag
* Add schema relation for teams and credentials
* feat: Orgs Schema Changing `scopedMembers` to `orgUsers` (#9209)
* Change scopedMembers to orgMembers
* Change to orgUsers
* Create getUserAdminTeams function & tRPC endpoint
* Get user admin teams on app store page
* Create UserAdminTeams type
* Add user query to getUserAdminTeams
* Letting duplicate slugs for teams to support orgs
* Covering null on unique clauses
* Add dropdown to install button on app store
* Supporting having the orgId in the session cookie
* On app page, only show dropdown if there are teams
* Add teamId to OAuth state
* Create team credential for OAuth flow
* Create team credential for GCal
* Add create user or team credential for Stripe
* Create webex credentials for users or teams
* Fix type error on useAddAppMutation
* Hubspot create credential on user or team
* Zoho create create credential for user or team
* Zoom create credentials on user or team
* Salesforce create credential on user or teams
* OAuth create credentials for user or teams
* Revert Outlook changes
* Revert GCal changes
* Default app instal, create credential on user or team
* Add teamId to credential creation
* Disable installing for teams for calendars
* Include teams when querying installed apps
* Render team credentials on installed page
* Uninstall team apps
* Type fix on app card
* Add input to include user in teams query
* Add dropdown to install app page for user or team
* Type fixes on category page
* Install app from eventType page to user or team
* Render user and team apps on event type app page
* feat: organization event type filter (#9253)
Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
* Missing changes to support orgs schema changes
* Render user and team apps on event type app page
* Add credentialOwner to eventTypeAppCard types
* Type fixes
* Create hook to check if app is enabled
* Clean up console.logs
* Fix useIsAppEnabled by returning not an array
* Convert event type apps to useIsAppEnabled
* Abstract credential owner type
* Remove console.logs
* On installed app page, show apps if only team credential is installed
* Clean up commented lines
* Handle installing app to just an team event from event type page
* Fix early return when creating team app credential
* Zoom add state to callback
* Get team location credentials and save credential id to location
* feat: Onboarding process to create an organization (#9184)
* Desktop first banner, mobile pending
* Removing dead code and img
* WIP
* Adds Email verification template+translations for organizations (#9202)
* First step done
* Merge branch 'feat/organizations-onboarding' of github.com:calcom/cal.com into feat/organizations-onboarding
* Step 2 done, avatar not working
* Covering null on unique clauses
* Onboarding admins step
* Last step to create teams
* Moving change password handler, improving verifying code flow
* Clearing error before submitting
* Reverting email testing api changes
* Reverting having the banner for now
* Consistent exported components
* Remove unneeded files from banner
* Removing uneeded code
* Fixing avatar selector
* Using meta component for head/descr
* Missing i18n strings
* Feedback
* Making an org avatar (temp)
* Check for subteams slug clashes with usernames
* Fixing create teams onsuccess
* feedback
* Making sure we check requestedSlug now
---------
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
* Type fix
* Grab team location credentials
* Add isInstalled to eventType apps query
* feat: [CAL-1816] Organization subdomain support (#9345)
* Desktop first banner, mobile pending
* Removing dead code and img
* WIP
* Adds Email verification template+translations for organizations (#9202)
* First step done
* Merge branch 'feat/organizations-onboarding' of github.com:calcom/cal.com into feat/organizations-onboarding
* Step 2 done, avatar not working
* Covering null on unique clauses
* Onboarding admins step
* Last step to create teams
* Moving change password handler, improving verifying code flow
* Clearing error before submitting
* Reverting email testing api changes
* Reverting having the banner for now
* Consistent exported components
* Remove unneeded files from banner
* Removing uneeded code
* Fixing avatar selector
* Using meta component for head/descr
* Missing i18n strings
* Feedback
* Making an org avatar (temp)
* Check for subteams slug clashes with usernames
* Fixing create teams onsuccess
* Covering users and subteams, excluding non-org users
* Unpublished teams shows correctly
* Create subdomain in Vercel
* feedback
* Renaming Vercel env vars
* Vercel domain check before creation
* Supporting cal-staging.com
* Change to have vercel detect it
* vercel domain check data message error
* Remove check domain
* Making sure we check requestedSlug now
* Feedback and unneeded code
* Reverting unneeded changes
* Unneeded changes
---------
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
* Vercel subdomain creation in PROD only
* Enable payment apps for team credentials
* Fix for team-user apps for event types
* Fix layout and add teamId to app card
* Disable apps on managed event types
* Add managed event type fields to event type apps
* Include organizations in query
* Change createAppCredential to createOAuthAppCredential
* Show app installed on teams
* Making sure we let localhost still work
* UI show installed for which team
* Type fixes
* For team events move use host location to top
* Add around to appStore
* New team event types organizer default conf app
* Fix app card bug
* Clean up
* Search for teamId or userId when deleting credential
* Type fixes
* Type fixes
* Type fixes
* Type fixes
* Address feedback
* Feedback
* Type check fixes
* feat: Organization branding in side menu (#9279)
* Desktop first banner, mobile pending
* Removing dead code and img
* WIP
* Adds Email verification template+translations for organizations (#9202)
* First step done
* Merge branch 'feat/organizations-onboarding' of github.com:calcom/cal.com into feat/organizations-onboarding
* Step 2 done, avatar not working
* Covering null on unique clauses
* Onboarding admins step
* Last step to create teams
* Moving change password handler, improving verifying code flow
* Clearing error before submitting
* Reverting email testing api changes
* Reverting having the banner for now
* Consistent exported components
* Remove unneeded files from banner
* Removing uneeded code
* Fixing avatar selector
* Org branding provider used in shell sidebar
* Using meta component for head/descr
* Missing i18n strings
* Feedback
* Making an org avatar (temp)
* Using org avatar (temp)
* Not showing org logo if not set
* User onboarding with org branding (slug)
* Check for subteams slug clashes with usernames
* Fixing create teams onsuccess
* feedback
* Feedback
* Org public profile
* Public profiles for team event types
* Added setup profile alert
* Using org avatar on subteams avatar
* Making sure we show the set up profile on org only
* Profile username availability rely on org hook
* Update apps/web/pages/team/[slug].tsx
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
* Update apps/web/pages/team/[slug].tsx
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
---------
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
* feat: Organization support for event types page (#9449)
* Desktop first banner, mobile pending
* Removing dead code and img
* WIP
* Adds Email verification template+translations for organizations (#9202)
* First step done
* Merge branch 'feat/organizations-onboarding' of github.com:calcom/cal.com into feat/organizations-onboarding
* Step 2 done, avatar not working
* Covering null on unique clauses
* Onboarding admins step
* Last step to create teams
* Moving change password handler, improving verifying code flow
* Clearing error before submitting
* Reverting email testing api changes
* Reverting having the banner for now
* Consistent exported components
* Remove unneeded files from banner
* Removing uneeded code
* Fixing avatar selector
* Org branding provider used in shell sidebar
* Using meta component for head/descr
* Missing i18n strings
* Feedback
* Making an org avatar (temp)
* Using org avatar (temp)
* Not showing org logo if not set
* User onboarding with org branding (slug)
* Check for subteams slug clashes with usernames
* Fixing create teams onsuccess
* feedback
* Feedback
* Org public profile
* Public profiles for team event types
* Added setup profile alert
* Using org avatar on subteams avatar
* Processing orgs and children as profile options
* Reverting change not belonging to this PR
* Making sure we show the set up profile on org only
* Removing console.log
* Comparing memberships to choose the highest one
---------
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
* Type errors
* Refactor and type fixes
* Update orgDomains.ts
* Feedback
* Reverting
* NIT
* Address feedback
* fix issue getting org slug from domain
* Improving orgDomains util
* Host comes with port
* Update useRouterQuery.ts
* Fix app card bug
* Fix schema
* Type fixes
* Revert changes to location apps
* Remove console.log
* Fix app store test
* Handle install app dropdown
* Add CalendarApp to `getCalendar`
* Add PaymentApp type fix
* Payment type fix
* Type fixes
* Match with main
* Change type to account for team
* Fix app count for team events
* Type fixes
* More type fixes
* Type fix?
* Fix the type fix
* Remove UserAdminTeams empty array union
* Type fix
* Type fix
* Type fix
* Uses type predicates
* Use teamId. Fixes installation for teams after user installation
* Fix Team Events not working
* Get embed for org events working
* Fix rewrites
* Address feedback
* Type fix
* Fixes
* Add useAppContextWithSchema in useIsAppEnabled
* Type fix for apps using useIsAppEnabled
* Integrations.handler change credentialIds to userCredentialIds
* Remove apps endpoint
* Add LockedIcon and disabled props to event type app context
* Type fixes
* Type fix
* Type fixes
* Show team installed apps for members
* Type fix
* Reverting findFirst
* Revert findFirst
* Avoid a possible 500
* Fix missing tanslation
* Avoid possible 500
* Undo default app for teams
* Type fix
* Fix test
* Update package.json
* feat: Fix invite bug - added tests (#9945)
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
* chore: Button Component Tidy up (#9888)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
* feat: Make Team Private
## What does this PR do?
Fixes https://github.com/calcom/cal.com/issues/8974
1) When user is admin
<img width="1440" alt="Screenshot 2023-07-03 at 6 45 50 PM" src="https://github.com/calcom/cal.com/assets/53316345/ce15158f-d278-4f1a-ba2e-8b63e4274793">
2) When user is not admin and team is private
<img width="1440" alt="Screenshot 2023-07-03 at 6 47 15 PM" src="https://github.com/calcom/cal.com/assets/53316345/ce23560e-690a-4c42-a76d-49691260aa4d">
3)
<img width="1440" alt="Screenshot 2023-07-03 at 6 51 56 PM" src="https://github.com/calcom/cal.com/assets/53316345/13af38f8-5618-4dae-b359-b24dc91e4eb4">
## Type of change
<!-- Please delete bullets that are not relevant. -->
- New feature (non-breaking change which adds functionality)
## How should this be tested?
1) go to Team members page and turn on switch Make Team Private.
Now after making the team private only admin would be able to see all the members list in the settings. There will not be a button to Book a team member instead on the team page like before.
## Mandatory Tasks
- [ ] Make sure you have self-reviewed the code. A decent size PR without self-review might be rejected.
---------
Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
Co-authored-by: Leo Giovanetti <hello@leog.me>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: Alan <alannnc@gmail.com>
Co-authored-by: zomars <zomars@me.com>
Co-authored-by: Efraín Rochín <roae.85@gmail.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
2023-07-06 16:48:39 +00:00
private async createVideoEvent ( event : CalendarEvent ) {
2021-07-15 01:19:30 +00:00
const credential = this . getVideoCredential ( event ) ;
2021-10-26 16:17:24 +00:00
if ( credential ) {
2021-10-25 13:05:21 +00:00
return createMeeting ( credential , event ) ;
2021-07-15 01:19:30 +00:00
} else {
2022-04-26 11:31:57 +00:00
return Promise . reject (
` No suitable credentials given for the requested integration name: ${ event . location } `
) ;
2021-07-15 01:19:30 +00:00
}
}
2021-07-20 18:07:59 +00:00
/ * *
* Updates the event entries for all calendar integrations given in the credentials .
* When noMail is true , no mails will be sent . This is used when the event is
* a video meeting because then the mail containing the video credentials will be
* more important than the mails created for these bare calendar events .
*
* @param event
* @param booking
* @private
* /
2022-10-19 16:11:50 +00:00
private async updateAllCalendarEvents (
2021-07-15 01:19:30 +00:00
event : CalendarEvent ,
2023-03-14 04:19:05 +00:00
booking : PartialBooking ,
newBookingId? : number
2022-06-17 18:34:41 +00:00
) : Promise < Array < EventResult < NewCalendarEventType > >> {
2022-07-18 15:37:47 +00:00
let calendarReference : PartialReference | undefined = undefined ,
credential ;
try {
2023-03-14 04:19:05 +00:00
// If a newBookingId is given, update that calendar event
let newBooking ;
if ( newBookingId ) {
newBooking = await prisma . booking . findUnique ( {
where : {
id : newBookingId ,
} ,
select : {
references : true ,
} ,
} ) ;
}
2023-03-22 14:23:09 +00:00
calendarReference = newBooking ? . references . length
? newBooking . references . find ( ( reference ) = > reference . type . includes ( "_calendar" ) )
: booking . references . find ( ( reference ) = > reference . type . includes ( "_calendar" ) ) ;
2023-03-14 04:19:05 +00:00
2022-11-05 18:58:35 +00:00
if ( ! calendarReference ) {
2023-02-27 20:45:40 +00:00
return [ ] ;
2022-11-05 18:58:35 +00:00
}
2022-07-18 15:37:47 +00:00
const { uid : bookingRefUid , externalCalendarId : bookingExternalCalendarId } = calendarReference ;
2023-05-17 12:57:12 +00:00
let calenderExternalId : string | null = null ;
if ( bookingExternalCalendarId ) {
calenderExternalId = bookingExternalCalendarId ;
2022-11-05 18:58:35 +00:00
}
2022-07-18 15:37:47 +00:00
2022-10-19 16:11:50 +00:00
let result = [ ] ;
2022-07-18 15:37:47 +00:00
if ( calendarReference . credentialId ) {
credential = this . calendarCredentials . filter (
( credential ) = > credential . id === calendarReference ? . credentialId
) [ 0 ] ;
2023-05-17 12:57:12 +00:00
result . push ( updateEvent ( credential , event , bookingRefUid , calenderExternalId ) ) ;
2022-07-18 15:37:47 +00:00
} else {
const credentials = this . calendarCredentials . filter (
( credential ) = > credential . type === calendarReference ? . type
) ;
for ( const credential of credentials ) {
2023-05-17 12:57:12 +00:00
result . push ( updateEvent ( credential , event , bookingRefUid , calenderExternalId ) ) ;
2022-07-18 15:37:47 +00:00
}
}
2023-03-14 04:19:05 +00:00
// If we are merging two calendar events we should delete the old calendar event
if ( newBookingId ) {
const oldCalendarEvent = booking . references . find ( ( reference ) = > reference . type . includes ( "_calendar" ) ) ;
if ( oldCalendarEvent ? . credentialId ) {
const calendarCredential = await prisma . credential . findUnique ( {
where : {
id : oldCalendarEvent.credentialId ,
} ,
} ) ;
2023-04-05 14:55:57 +00:00
const calendar = await getCalendar ( calendarCredential ) ;
2023-03-14 04:19:05 +00:00
await calendar ? . deleteEvent ( oldCalendarEvent . uid , event , oldCalendarEvent . externalCalendarId ) ;
}
}
2022-10-19 16:11:50 +00:00
// Taking care of non-traditional calendar integrations
result = result . concat (
this . calendarCredentials
. filter ( ( cred ) = > cred . type . includes ( "other_calendar" ) )
. map ( async ( cred ) = > {
const calendarReference = booking . references . find ( ( ref ) = > ref . type === cred . type ) ;
if ( ! calendarReference )
2022-11-05 18:58:35 +00:00
if ( ! calendarReference ) {
return {
appName : cred.appName ,
type : cred . type ,
success : false ,
uid : "" ,
originalEvent : event ,
2023-07-06 21:39:33 +00:00
credentialId : cred.id ,
2022-11-05 18:58:35 +00:00
} ;
}
2022-10-19 16:11:50 +00:00
const { externalCalendarId : bookingExternalCalendarId , meetingId : bookingRefUid } =
calendarReference ;
return await updateEvent ( cred , event , bookingRefUid ? ? null , bookingExternalCalendarId ? ? null ) ;
} )
) ;
2022-07-18 15:37:47 +00:00
return Promise . all ( result ) ;
} catch ( error ) {
let message = ` Tried to 'updateAllCalendarEvents' but there was no '{thing}' for ' ${ credential ? . type } ', userId: ' ${ credential ? . userId } ', bookingId: ' ${ booking ? . id } ' ` ;
2022-11-05 18:58:35 +00:00
if ( error instanceof Error ) {
message = message . replace ( "{thing}" , error . message ) ;
}
2022-07-18 15:37:47 +00:00
console . error ( message ) ;
return Promise . resolve ( [
{
2022-10-19 16:11:50 +00:00
appName : "none" ,
2022-07-18 15:37:47 +00:00
type : calendarReference ? . type || "calendar" ,
2022-06-08 18:23:48 +00:00
success : false ,
uid : "" ,
originalEvent : event ,
2023-07-06 21:39:33 +00:00
credentialId : 0 ,
2022-07-18 15:37:47 +00:00
} ,
] ) ;
}
2021-07-15 01:19:30 +00:00
}
2021-07-20 18:07:59 +00:00
/ * *
* Updates a single video event .
*
* @param event
* @param booking
* @private
* /
feat: Enable Apps for Teams & Orgs [CAL-1782] (#9337)
* Initial commit
* Adding feature flag
* Add schema relation for teams and credentials
* feat: Orgs Schema Changing `scopedMembers` to `orgUsers` (#9209)
* Change scopedMembers to orgMembers
* Change to orgUsers
* Create getUserAdminTeams function & tRPC endpoint
* Get user admin teams on app store page
* Create UserAdminTeams type
* Add user query to getUserAdminTeams
* Letting duplicate slugs for teams to support orgs
* Covering null on unique clauses
* Add dropdown to install button on app store
* Supporting having the orgId in the session cookie
* On app page, only show dropdown if there are teams
* Add teamId to OAuth state
* Create team credential for OAuth flow
* Create team credential for GCal
* Add create user or team credential for Stripe
* Create webex credentials for users or teams
* Fix type error on useAddAppMutation
* Hubspot create credential on user or team
* Zoho create create credential for user or team
* Zoom create credentials on user or team
* Salesforce create credential on user or teams
* OAuth create credentials for user or teams
* Revert Outlook changes
* Revert GCal changes
* Default app instal, create credential on user or team
* Add teamId to credential creation
* Disable installing for teams for calendars
* Include teams when querying installed apps
* Render team credentials on installed page
* Uninstall team apps
* Type fix on app card
* Add input to include user in teams query
* Add dropdown to install app page for user or team
* Type fixes on category page
* Install app from eventType page to user or team
* Render user and team apps on event type app page
* feat: organization event type filter (#9253)
Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
* Missing changes to support orgs schema changes
* Render user and team apps on event type app page
* Add credentialOwner to eventTypeAppCard types
* Type fixes
* Create hook to check if app is enabled
* Clean up console.logs
* Fix useIsAppEnabled by returning not an array
* Convert event type apps to useIsAppEnabled
* Abstract credential owner type
* Remove console.logs
* On installed app page, show apps if only team credential is installed
* Clean up commented lines
* Handle installing app to just an team event from event type page
* Fix early return when creating team app credential
* Zoom add state to callback
* Get team location credentials and save credential id to location
* feat: Onboarding process to create an organization (#9184)
* Desktop first banner, mobile pending
* Removing dead code and img
* WIP
* Adds Email verification template+translations for organizations (#9202)
* First step done
* Merge branch 'feat/organizations-onboarding' of github.com:calcom/cal.com into feat/organizations-onboarding
* Step 2 done, avatar not working
* Covering null on unique clauses
* Onboarding admins step
* Last step to create teams
* Moving change password handler, improving verifying code flow
* Clearing error before submitting
* Reverting email testing api changes
* Reverting having the banner for now
* Consistent exported components
* Remove unneeded files from banner
* Removing uneeded code
* Fixing avatar selector
* Using meta component for head/descr
* Missing i18n strings
* Feedback
* Making an org avatar (temp)
* Check for subteams slug clashes with usernames
* Fixing create teams onsuccess
* feedback
* Making sure we check requestedSlug now
---------
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
* Type fix
* Grab team location credentials
* Add isInstalled to eventType apps query
* feat: [CAL-1816] Organization subdomain support (#9345)
* Desktop first banner, mobile pending
* Removing dead code and img
* WIP
* Adds Email verification template+translations for organizations (#9202)
* First step done
* Merge branch 'feat/organizations-onboarding' of github.com:calcom/cal.com into feat/organizations-onboarding
* Step 2 done, avatar not working
* Covering null on unique clauses
* Onboarding admins step
* Last step to create teams
* Moving change password handler, improving verifying code flow
* Clearing error before submitting
* Reverting email testing api changes
* Reverting having the banner for now
* Consistent exported components
* Remove unneeded files from banner
* Removing uneeded code
* Fixing avatar selector
* Using meta component for head/descr
* Missing i18n strings
* Feedback
* Making an org avatar (temp)
* Check for subteams slug clashes with usernames
* Fixing create teams onsuccess
* Covering users and subteams, excluding non-org users
* Unpublished teams shows correctly
* Create subdomain in Vercel
* feedback
* Renaming Vercel env vars
* Vercel domain check before creation
* Supporting cal-staging.com
* Change to have vercel detect it
* vercel domain check data message error
* Remove check domain
* Making sure we check requestedSlug now
* Feedback and unneeded code
* Reverting unneeded changes
* Unneeded changes
---------
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
* Vercel subdomain creation in PROD only
* Enable payment apps for team credentials
* Fix for team-user apps for event types
* Fix layout and add teamId to app card
* Disable apps on managed event types
* Add managed event type fields to event type apps
* Include organizations in query
* Change createAppCredential to createOAuthAppCredential
* Show app installed on teams
* Making sure we let localhost still work
* UI show installed for which team
* Type fixes
* For team events move use host location to top
* Add around to appStore
* New team event types organizer default conf app
* Fix app card bug
* Clean up
* Search for teamId or userId when deleting credential
* Type fixes
* Type fixes
* Type fixes
* Type fixes
* Address feedback
* Feedback
* Type check fixes
* feat: Organization branding in side menu (#9279)
* Desktop first banner, mobile pending
* Removing dead code and img
* WIP
* Adds Email verification template+translations for organizations (#9202)
* First step done
* Merge branch 'feat/organizations-onboarding' of github.com:calcom/cal.com into feat/organizations-onboarding
* Step 2 done, avatar not working
* Covering null on unique clauses
* Onboarding admins step
* Last step to create teams
* Moving change password handler, improving verifying code flow
* Clearing error before submitting
* Reverting email testing api changes
* Reverting having the banner for now
* Consistent exported components
* Remove unneeded files from banner
* Removing uneeded code
* Fixing avatar selector
* Org branding provider used in shell sidebar
* Using meta component for head/descr
* Missing i18n strings
* Feedback
* Making an org avatar (temp)
* Using org avatar (temp)
* Not showing org logo if not set
* User onboarding with org branding (slug)
* Check for subteams slug clashes with usernames
* Fixing create teams onsuccess
* feedback
* Feedback
* Org public profile
* Public profiles for team event types
* Added setup profile alert
* Using org avatar on subteams avatar
* Making sure we show the set up profile on org only
* Profile username availability rely on org hook
* Update apps/web/pages/team/[slug].tsx
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
* Update apps/web/pages/team/[slug].tsx
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
---------
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
* feat: Organization support for event types page (#9449)
* Desktop first banner, mobile pending
* Removing dead code and img
* WIP
* Adds Email verification template+translations for organizations (#9202)
* First step done
* Merge branch 'feat/organizations-onboarding' of github.com:calcom/cal.com into feat/organizations-onboarding
* Step 2 done, avatar not working
* Covering null on unique clauses
* Onboarding admins step
* Last step to create teams
* Moving change password handler, improving verifying code flow
* Clearing error before submitting
* Reverting email testing api changes
* Reverting having the banner for now
* Consistent exported components
* Remove unneeded files from banner
* Removing uneeded code
* Fixing avatar selector
* Org branding provider used in shell sidebar
* Using meta component for head/descr
* Missing i18n strings
* Feedback
* Making an org avatar (temp)
* Using org avatar (temp)
* Not showing org logo if not set
* User onboarding with org branding (slug)
* Check for subteams slug clashes with usernames
* Fixing create teams onsuccess
* feedback
* Feedback
* Org public profile
* Public profiles for team event types
* Added setup profile alert
* Using org avatar on subteams avatar
* Processing orgs and children as profile options
* Reverting change not belonging to this PR
* Making sure we show the set up profile on org only
* Removing console.log
* Comparing memberships to choose the highest one
---------
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
* Type errors
* Refactor and type fixes
* Update orgDomains.ts
* Feedback
* Reverting
* NIT
* Address feedback
* fix issue getting org slug from domain
* Improving orgDomains util
* Host comes with port
* Update useRouterQuery.ts
* Fix app card bug
* Fix schema
* Type fixes
* Revert changes to location apps
* Remove console.log
* Fix app store test
* Handle install app dropdown
* Add CalendarApp to `getCalendar`
* Add PaymentApp type fix
* Payment type fix
* Type fixes
* Match with main
* Change type to account for team
* Fix app count for team events
* Type fixes
* More type fixes
* Type fix?
* Fix the type fix
* Remove UserAdminTeams empty array union
* Type fix
* Type fix
* Type fix
* Uses type predicates
* Use teamId. Fixes installation for teams after user installation
* Fix Team Events not working
* Get embed for org events working
* Fix rewrites
* Address feedback
* Type fix
* Fixes
* Add useAppContextWithSchema in useIsAppEnabled
* Type fix for apps using useIsAppEnabled
* Integrations.handler change credentialIds to userCredentialIds
* Remove apps endpoint
* Add LockedIcon and disabled props to event type app context
* Type fixes
* Type fix
* Type fixes
* Show team installed apps for members
* Type fix
* Reverting findFirst
* Revert findFirst
* Avoid a possible 500
* Fix missing tanslation
* Avoid possible 500
* Undo default app for teams
* Type fix
* Fix test
* Update package.json
* feat: Fix invite bug - added tests (#9945)
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
* chore: Button Component Tidy up (#9888)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
* feat: Make Team Private
## What does this PR do?
Fixes https://github.com/calcom/cal.com/issues/8974
1) When user is admin
<img width="1440" alt="Screenshot 2023-07-03 at 6 45 50 PM" src="https://github.com/calcom/cal.com/assets/53316345/ce15158f-d278-4f1a-ba2e-8b63e4274793">
2) When user is not admin and team is private
<img width="1440" alt="Screenshot 2023-07-03 at 6 47 15 PM" src="https://github.com/calcom/cal.com/assets/53316345/ce23560e-690a-4c42-a76d-49691260aa4d">
3)
<img width="1440" alt="Screenshot 2023-07-03 at 6 51 56 PM" src="https://github.com/calcom/cal.com/assets/53316345/13af38f8-5618-4dae-b359-b24dc91e4eb4">
## Type of change
<!-- Please delete bullets that are not relevant. -->
- New feature (non-breaking change which adds functionality)
## How should this be tested?
1) go to Team members page and turn on switch Make Team Private.
Now after making the team private only admin would be able to see all the members list in the settings. There will not be a button to Book a team member instead on the team page like before.
## Mandatory Tasks
- [ ] Make sure you have self-reviewed the code. A decent size PR without self-review might be rejected.
---------
Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
Co-authored-by: Leo Giovanetti <hello@leog.me>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: Alan <alannnc@gmail.com>
Co-authored-by: zomars <zomars@me.com>
Co-authored-by: Efraín Rochín <roae.85@gmail.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
2023-07-06 16:48:39 +00:00
private async updateVideoEvent ( event : CalendarEvent , booking : PartialBooking ) {
2021-07-15 01:19:30 +00:00
const credential = this . getVideoCredential ( event ) ;
2021-10-26 16:17:24 +00:00
if ( credential ) {
2021-10-25 13:05:21 +00:00
const bookingRef = booking ? booking . references . filter ( ( ref ) = > ref . type === credential . type ) [ 0 ] : null ;
2021-11-26 11:03:43 +00:00
return updateMeeting ( credential , event , bookingRef ) ;
2021-07-15 01:19:30 +00:00
} else {
2022-04-26 11:31:57 +00:00
return Promise . reject (
` No suitable credentials given for the requested integration name: ${ event . location } `
) ;
2021-07-15 01:19:30 +00:00
}
}
2022-04-14 21:25:24 +00:00
/ * *
* Update event to set a cancelled event placeholder on users calendar
* remove if virtual calendar is already done and user availability its read from there
* and not only in their calendars
* @param event
* @param booking
* @public
* /
public async updateAndSetCancelledPlaceholder ( event : CalendarEvent , booking : PartialBooking ) {
await this . updateAllCalendarEvents ( event , booking ) ;
}
2023-03-14 04:19:05 +00:00
public async rescheduleBookingWithSeats (
originalBooking : Booking ,
newTimeSlotBooking? : Booking ,
owner? : boolean
) {
// Get originalBooking
// If originalBooking has only one attendee we should do normal reschedule
// Change current event attendees in everyone calendar
}
2021-07-15 01:19:30 +00:00
}