diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 2580bf4eab353b..707b6fb803e25f 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -33,7 +33,7 @@ jobs: with: filters: | has-files-requiring-all-checks: - - "!(**.md|.github/CODEOWNERS)" + - "!(**.md|.github/CODEOWNERS|docs/**|apps/web/public/static/locales/**/common.json)" - name: Get Latest Commit SHA id: get_sha run: | diff --git a/apps/api/v1/lib/validations/booking.ts b/apps/api/v1/lib/validations/booking.ts index 33b61dacb34bb8..f85cc195c1b8a9 100644 --- a/apps/api/v1/lib/validations/booking.ts +++ b/apps/api/v1/lib/validations/booking.ts @@ -73,6 +73,7 @@ export const schemaBookingReadPublic = Booking.extend({ attendees: z .array( _AttendeeModel.pick({ + id: true, email: true, name: true, timeZone: true, diff --git a/apps/api/v1/package.json b/apps/api/v1/package.json index 9df6ad3643b3d7..ac2dcb032cb7a4 100644 --- a/apps/api/v1/package.json +++ b/apps/api/v1/package.json @@ -33,7 +33,7 @@ "@sentry/nextjs": "^8.8.0", "bcryptjs": "^2.4.3", "memory-cache": "^0.2.0", - "next": "^13.5.4", + "next": "^13.5.6", "next-api-middleware": "^1.0.1", "next-axiom": "^0.17.0", "next-swagger-doc": "^0.3.6", diff --git a/apps/api/v2/package.json b/apps/api/v2/package.json index 45cc6fb1e5dc81..fd614d0666bbe6 100644 --- a/apps/api/v2/package.json +++ b/apps/api/v2/package.json @@ -28,7 +28,7 @@ "dependencies": { "@calcom/platform-constants": "*", "@calcom/platform-enums": "*", - "@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.44", + "@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.45", "@calcom/platform-libraries-0.0.2": "npm:@calcom/platform-libraries@0.0.2", "@calcom/platform-types": "*", "@calcom/platform-utils": "*", diff --git a/apps/api/v2/src/modules/conferencing/controllers/conferencing.controller.ts b/apps/api/v2/src/modules/conferencing/controllers/conferencing.controller.ts index 14f0e42f2caae8..97fb9e52d5df25 100644 --- a/apps/api/v2/src/modules/conferencing/controllers/conferencing.controller.ts +++ b/apps/api/v2/src/modules/conferencing/controllers/conferencing.controller.ts @@ -30,7 +30,7 @@ import { CONFERENCING_APPS, GOOGLE_MEET, SUCCESS_STATUS } from "@calcom/platform path: "/v2/conferencing", version: API_VERSIONS_VALUES, }) -@DocsTags("Platform / Conferencing") +@DocsTags("Conferencing") export class ConferencingController { private readonly logger = new Logger("Platform Gcal Provider"); diff --git a/apps/api/v2/swagger/documentation.json b/apps/api/v2/swagger/documentation.json index 984d0b685f8081..1c3f7824a5b5bf 100644 --- a/apps/api/v2/swagger/documentation.json +++ b/apps/api/v2/swagger/documentation.json @@ -63,121 +63,6 @@ ] } }, - "/v2/conferencing/{app}/connect": { - "post": { - "operationId": "ConferencingController_connect", - "summary": "connect your conferencing application", - "parameters": [ - { - "name": "app", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConferencingAppOutputResponseDto" - } - } - } - } - }, - "tags": [ - "Platform / Conferencing" - ] - } - }, - "/v2/conferencing": { - "get": { - "operationId": "ConferencingController_listConferencingApps", - "summary": "list your conferencing applications", - "parameters": [], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConferencingAppsOutputResponseDto" - } - } - } - } - }, - "tags": [ - "Platform / Conferencing" - ] - } - }, - "/v2/conferencing/{app}/default": { - "post": { - "operationId": "ConferencingController_default", - "summary": "set your default conferencing application", - "parameters": [ - { - "name": "app", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SetDefaultConferencingAppOutputResponseDto" - } - } - } - } - }, - "tags": [ - "Platform / Conferencing" - ] - } - }, - "/v2/conferencing/{app}/disconnect": { - "delete": { - "operationId": "ConferencingController_disconnect", - "summary": "disconnect your conferencing application", - "parameters": [ - { - "name": "app", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConferencingAppOutputResponseDto" - } - } - } - } - }, - "tags": [ - "Platform / Conferencing" - ] - } - }, "/v2/gcal/oauth/auth-url": { "get": { "operationId": "GcalController_redirect", @@ -3657,6 +3542,121 @@ ] } }, + "/v2/conferencing/{app}/connect": { + "post": { + "operationId": "ConferencingController_connect", + "summary": "Connect your conferencing application", + "parameters": [ + { + "name": "app", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConferencingAppOutputResponseDto" + } + } + } + } + }, + "tags": [ + "Conferencing" + ] + } + }, + "/v2/conferencing": { + "get": { + "operationId": "ConferencingController_listConferencingApps", + "summary": "List your conferencing applications", + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConferencingAppsOutputResponseDto" + } + } + } + } + }, + "tags": [ + "Conferencing" + ] + } + }, + "/v2/conferencing/{app}/default": { + "post": { + "operationId": "ConferencingController_default", + "summary": "Set your default conferencing application", + "parameters": [ + { + "name": "app", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetDefaultConferencingAppOutputResponseDto" + } + } + } + } + }, + "tags": [ + "Conferencing" + ] + } + }, + "/v2/conferencing/{app}/disconnect": { + "delete": { + "operationId": "ConferencingController_disconnect", + "summary": "Disconnect your conferencing application", + "parameters": [ + { + "name": "app", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConferencingAppOutputResponseDto" + } + } + } + } + }, + "tags": [ + "Conferencing" + ] + } + }, "/v2/destination-calendars": { "put": { "operationId": "DestinationCalendarsController_updateDestinationCalendars", @@ -11149,7 +11149,9 @@ "RECORDING_READY", "INSTANT_MEETING", "RECORDING_TRANSCRIPTION_GENERATED", - "OOO_CREATED" + "OOO_CREATED", + "AFTER_HOSTS_CAL_VIDEO_NO_SHOW", + "AFTER_GUESTS_CAL_VIDEO_NO_SHOW" ] }, "active": { @@ -11223,7 +11225,9 @@ "RECORDING_READY", "INSTANT_MEETING", "RECORDING_TRANSCRIPTION_GENERATED", - "OOO_CREATED" + "OOO_CREATED", + "AFTER_HOSTS_CAL_VIDEO_NO_SHOW", + "AFTER_GUESTS_CAL_VIDEO_NO_SHOW" ] }, "active": { @@ -13126,7 +13130,7 @@ "type": { "type": "string", "example": "google_video", - "description": "type of conferencing app" + "description": "Type of conferencing app" }, "userId": { "type": "number", diff --git a/apps/storybook/package.json b/apps/storybook/package.json index d08e90f29757f9..13c9914f7f0d3b 100644 --- a/apps/storybook/package.json +++ b/apps/storybook/package.json @@ -24,7 +24,7 @@ "@storybook/blocks": "^7.6.3", "@storybook/nextjs": "^7.6.3", "@storybook/preview-api": "^7.6.3", - "next": "^13.5.4", + "next": "^13.5.6", "react": "^18.2.0", "react-dom": "^18.2.0", "storybook-addon-rtl-direction": "^0.0.19" diff --git a/apps/swagger/package.json b/apps/swagger/package.json index 594cc8064af0fe..da1d0342a9b8ed 100644 --- a/apps/swagger/package.json +++ b/apps/swagger/package.json @@ -14,7 +14,7 @@ "dependencies": { "highlight.js": "^11.6.0", "isarray": "2.0.5", - "next": "^13.5.4", + "next": "^13.5.6", "openapi-snippet": "^0.13.0", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/apps/web/app/future/apps/[slug]/[...pages]/page.tsx b/apps/web/app/future/apps/[slug]/[...pages]/page.tsx index 94e8f8858fbb5c..70e08d657c0700 100644 --- a/apps/web/app/future/apps/[slug]/[...pages]/page.tsx +++ b/apps/web/app/future/apps/[slug]/[...pages]/page.tsx @@ -1,5 +1,5 @@ import { withAppDirSsr } from "app/WithAppDirSsr"; -import { PageProps } from "app/_types"; +import type { PageProps } from "app/_types"; import { _generateMetadata } from "app/_utils"; import { WithLayout } from "app/layoutHOC"; import type { GetServerSidePropsResult } from "next"; diff --git a/apps/web/app/future/settings/(settings)/my-account/appearance/page.tsx b/apps/web/app/settings/(settings-layout)/my-account/appearance/page.tsx similarity index 100% rename from apps/web/app/future/settings/(settings)/my-account/appearance/page.tsx rename to apps/web/app/settings/(settings-layout)/my-account/appearance/page.tsx diff --git a/apps/web/app/future/settings/(settings)/my-account/calendars/page.tsx b/apps/web/app/settings/(settings-layout)/my-account/calendars/page.tsx similarity index 100% rename from apps/web/app/future/settings/(settings)/my-account/calendars/page.tsx rename to apps/web/app/settings/(settings-layout)/my-account/calendars/page.tsx diff --git a/apps/web/app/future/settings/(settings)/my-account/conferencing/page.tsx b/apps/web/app/settings/(settings-layout)/my-account/conferencing/page.tsx similarity index 100% rename from apps/web/app/future/settings/(settings)/my-account/conferencing/page.tsx rename to apps/web/app/settings/(settings-layout)/my-account/conferencing/page.tsx diff --git a/apps/web/app/future/settings/(settings)/my-account/general/page.tsx b/apps/web/app/settings/(settings-layout)/my-account/general/page.tsx similarity index 78% rename from apps/web/app/future/settings/(settings)/my-account/general/page.tsx rename to apps/web/app/settings/(settings-layout)/my-account/general/page.tsx index c6ef48a09bc118..a53fd802ef1637 100644 --- a/apps/web/app/future/settings/(settings)/my-account/general/page.tsx +++ b/apps/web/app/settings/(settings-layout)/my-account/general/page.tsx @@ -1,5 +1,6 @@ import { _generateMetadata } from "app/_utils"; import { getFixedT } from "app/_utils"; +import { revalidatePath } from "next/cache"; import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-session-for-app-dir"; import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader"; @@ -16,9 +17,14 @@ const Page = async () => { const session = await getServerSessionForAppDir(); const t = await getFixedT(session?.user.locale || "en"); + const revalidatePage = async () => { + "use server"; + revalidatePath("settings/my-account/general"); + }; + return ( - + ); }; diff --git a/apps/web/app/future/settings/(settings)/my-account/out-of-office/page.tsx b/apps/web/app/settings/(settings-layout)/my-account/out-of-office/page.tsx similarity index 100% rename from apps/web/app/future/settings/(settings)/my-account/out-of-office/page.tsx rename to apps/web/app/settings/(settings-layout)/my-account/out-of-office/page.tsx diff --git a/apps/web/app/future/settings/(settings)/my-account/profile/page.tsx b/apps/web/app/settings/(settings-layout)/my-account/profile/page.tsx similarity index 100% rename from apps/web/app/future/settings/(settings)/my-account/profile/page.tsx rename to apps/web/app/settings/(settings-layout)/my-account/profile/page.tsx diff --git a/apps/web/components/PageWrapper.tsx b/apps/web/components/PageWrapper.tsx index 8f74a2fd798a1e..05c5ddeedd6d8c 100644 --- a/apps/web/components/PageWrapper.tsx +++ b/apps/web/components/PageWrapper.tsx @@ -1,3 +1,5 @@ +"use client"; + import { DefaultSeo } from "next-seo"; import { Inter } from "next/font/google"; import localFont from "next/font/local"; diff --git a/apps/web/components/dialog/EditLocationDialog.tsx b/apps/web/components/dialog/EditLocationDialog.tsx index 279dc5202a4ee5..6272e4c0a15b64 100644 --- a/apps/web/components/dialog/EditLocationDialog.tsx +++ b/apps/web/components/dialog/EditLocationDialog.tsx @@ -232,7 +232,7 @@ export const EditLocationDialog = (props: ISetLocationDialog) => {

{t("current_location")}:

-

+

{getHumanReadableLocationValue(booking.location, t)}

slugify(s)), slug: z.string().transform((s) => slugify(s)), @@ -23,17 +25,12 @@ const paramsSchema = z.object({ // 1. Check if team exists, to show 404 // 2. If rescheduling, get the booking details export const getServerSideProps = async (context: GetServerSidePropsContext) => { - const session = await getServerSession(context); - const { slug: teamSlug, type: meetingSlug } = paramsSchema.parse(context.params); - const { - rescheduleUid, - duration: queryDuration, - isInstantMeeting: queryIsInstantMeeting, - email, - } = context.query; - const { ssrInit } = await import("@server/lib/ssr"); + 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 ssr = await ssrInit(context); - const { currentOrgDomain, isValidOrgDomain } = orgDomainConfig(context.req, context.params?.orgSlug); + const { currentOrgDomain, isValidOrgDomain } = orgDomainConfig(req, params?.orgSlug); const isOrgContext = currentOrgDomain && isValidOrgDomain; if (!isOrgContext) { diff --git a/apps/web/lib/video/[uid]/getServerSideProps.ts b/apps/web/lib/video/[uid]/getServerSideProps.ts index 181f3b7925cdef..2b0581983dbd5c 100644 --- a/apps/web/lib/video/[uid]/getServerSideProps.ts +++ b/apps/web/lib/video/[uid]/getServerSideProps.ts @@ -3,7 +3,7 @@ import type { GetServerSidePropsContext } from "next"; import { generateGuestMeetingTokenFromOwnerMeetingToken, - setEnableRecordingUIForOrganizer, + setEnableRecordingUIAndUserIdForOrganizer, } from "@calcom/app-store/dailyvideo/lib/VideoApiAdapter"; import { getServerSession } from "@calcom/features/auth/lib/getServerSession"; import { getCalVideoReference } from "@calcom/features/get-cal-video-reference"; @@ -81,18 +81,20 @@ export async function getServerSideProps(context: GetServerSidePropsContext) { // set meetingPassword for guests if (session?.user.id !== bookingObj.user?.id) { const guestMeetingPassword = await generateGuestMeetingTokenFromOwnerMeetingToken( - oldVideoReference.meetingPassword + oldVideoReference.meetingPassword, + session?.user.id ); bookingObj.references.forEach((bookRef) => { bookRef.meetingPassword = guestMeetingPassword; }); } - // Only for backward compatibility for organizer + // Only for backward compatibility and setting user id in particpants for organizer else { - const meetingPassword = await setEnableRecordingUIForOrganizer( + const meetingPassword = await setEnableRecordingUIAndUserIdForOrganizer( oldVideoReference.id, - oldVideoReference.meetingPassword + oldVideoReference.meetingPassword, + session?.user.id ); if (!!meetingPassword) { bookingObj.references.forEach((bookRef) => { diff --git a/apps/web/modules/settings/my-account/general-view.tsx b/apps/web/modules/settings/my-account/general-view.tsx index da82bbecc858e3..2902ee8a5fcd94 100644 --- a/apps/web/modules/settings/my-account/general-view.tsx +++ b/apps/web/modules/settings/my-account/general-view.tsx @@ -68,9 +68,14 @@ interface GeneralViewProps { localeProp: string; user: RouterOutputs["viewer"]["me"]; travelSchedules: RouterOutputs["viewer"]["getTravelSchedules"]; + revalidatePage: GeneralQueryViewProps["revalidatePage"]; } -const GeneralQueryView = () => { +type GeneralQueryViewProps = { + revalidatePage: () => Promise; +}; + +const GeneralQueryView = ({ revalidatePage }: GeneralQueryViewProps) => { const { t } = useLocale(); const { data: user, isPending } = trpc.viewer.me.useQuery(); @@ -82,10 +87,17 @@ const GeneralQueryView = () => { if (!user) { throw new Error(t("something_went_wrong")); } - return ; + return ( + + ); }; -const GeneralView = ({ localeProp, user, travelSchedules }: GeneralViewProps) => { +const GeneralView = ({ localeProp, user, travelSchedules, revalidatePage }: GeneralViewProps) => { const utils = trpc.useContext(); const { t, @@ -105,6 +117,7 @@ const GeneralView = ({ localeProp, user, travelSchedules }: GeneralViewProps) => if (res.locale) { window.calNewLocale = res.locale; } + await revalidatePage(); }, onError: () => { showToast(t("error_updating_settings"), "error"); @@ -177,7 +190,7 @@ const GeneralView = ({ localeProp, user, travelSchedules }: GeneralViewProps) =>
{ + handleSubmit={async (values) => { setIsUpdateBtnLoading(true); mutation.mutate({ ...values, diff --git a/apps/web/modules/settings/platform/oauth-clients/[clientId]/edit/edit-webhooks-view.tsx b/apps/web/modules/settings/platform/oauth-clients/[clientId]/edit/edit-webhooks-view.tsx index 0d4ae3714a7386..35583707afdec4 100644 --- a/apps/web/modules/settings/platform/oauth-clients/[clientId]/edit/edit-webhooks-view.tsx +++ b/apps/web/modules/settings/platform/oauth-clients/[clientId]/edit/edit-webhooks-view.tsx @@ -69,6 +69,14 @@ export default function EditOAuthClientWebhooks() { value: WebhookTriggerEvents.RECORDING_TRANSCRIPTION_GENERATED, label: "recording_transcription_generated", }, + { + value: WebhookTriggerEvents.AFTER_HOSTS_CAL_VIDEO_NO_SHOW, + label: "after_hosts_cal_video_no_show", + }, + { + value: WebhookTriggerEvents.AFTER_GUESTS_CAL_VIDEO_NO_SHOW, + label: "after_guests_cal_video_no_show", + }, ]} onSubmit={async (data) => { try { diff --git a/apps/web/next.config.js b/apps/web/next.config.js index ce61936e164672..d60a4a2a1fe33f 100644 --- a/apps/web/next.config.js +++ b/apps/web/next.config.js @@ -178,6 +178,7 @@ const nextConfig = { serverComponentsExternalPackages: ["next-i18next"], optimizePackageImports: ["@calcom/ui"], instrumentationHook: true, + serverActions: true, }, i18n: { ...i18n, diff --git a/apps/web/package.json b/apps/web/package.json index 4438fd41aca8c7..90f0a858ed0a4c 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,6 +1,6 @@ { "name": "@calcom/web", - "version": "4.5.10", + "version": "4.5.11", "private": true, "scripts": { "analyze": "ANALYZE=true next build", @@ -8,6 +8,7 @@ "analyze:browser": "BUNDLE_ANALYZE=browser next build", "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next", "dev": "next dev", + "dev:cron": "ts-node cron-tester.ts", "dev-https": "NODE_TLS_REJECT_UNAUTHORIZED=0 next dev --experimental-https", "dx": "yarn dev", "test-codegen": "yarn playwright codegen http://localhost:3000", @@ -79,6 +80,7 @@ "bcp-47-match": "^2.0.3", "bcryptjs": "^2.4.3", "classnames": "^2.3.1", + "dompurify": "^3.1.7", "dotenv-cli": "^6.0.0", "entities": "^4.4.0", "eslint-config-next": "^13.2.1", @@ -97,7 +99,7 @@ "memory-cache": "^0.2.0", "micro": "^10.0.1", "mime-types": "^2.1.35", - "next": "^13.5.4", + "next": "^13.5.6", "next-auth": "^4.22.1", "next-axiom": "^0.17.0", "next-collect": "^0.2.1", @@ -122,7 +124,6 @@ "react-multi-email": "^0.5.3", "react-phone-input-2": "^2.15.1", "react-phone-number-input": "^3.2.7", - "react-query": "^3.39.3", "react-schemaorg": "^2.0.0", "react-select": "^5.7.0", "react-timezone-select": "^1.4.0", @@ -152,6 +153,7 @@ "@types/async": "^3.2.15", "@types/bcryptjs": "^2.4.2", "@types/detect-port": "^1.3.2", + "@types/dompurify": "^3.0.5", "@types/glidejs__glide": "^3.4.2", "@types/lodash": "^4.14.182", "@types/markdown-it": "^12.2.3", @@ -171,6 +173,8 @@ "@types/uuid": "8.3.1", "autoprefixer": "^10.4.12", "copy-webpack-plugin": "^11.0.0", + "cron": "^3.1.7", + "deasync": "^0.1.30", "detect-port": "^1.3.0", "env-cmd": "^10.1.0", "module-alias": "^2.2.2", diff --git a/apps/web/pages/org/[orgSlug]/[user]/[type]/embed.tsx b/apps/web/pages/org/[orgSlug]/[user]/[type]/embed.tsx index 11cb6812ef0424..a3752b2a3b8888 100644 --- a/apps/web/pages/org/[orgSlug]/[user]/[type]/embed.tsx +++ b/apps/web/pages/org/[orgSlug]/[user]/[type]/embed.tsx @@ -1,5 +1,3 @@ -"use client"; - import withEmbedSsr from "@lib/withEmbedSsr"; import { getServerSideProps as _getServerSideProps } from "."; diff --git a/apps/web/pages/org/[orgSlug]/[user]/[type]/index.tsx b/apps/web/pages/org/[orgSlug]/[user]/[type]/index.tsx index 67bf2539d06d07..1b876a36c1c7b3 100644 --- a/apps/web/pages/org/[orgSlug]/[user]/[type]/index.tsx +++ b/apps/web/pages/org/[orgSlug]/[user]/[type]/index.tsx @@ -1,5 +1,3 @@ -"use client"; - import PageWrapper from "@components/PageWrapper"; import type { PageProps as TeamTypePageProps } from "~/team/type-view"; diff --git a/apps/web/pages/settings/my-account/appearance.tsx b/apps/web/pages/settings/my-account/appearance.tsx deleted file mode 100644 index 9fbe4f4adffde1..00000000000000 --- a/apps/web/pages/settings/my-account/appearance.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { getLayout } from "@calcom/features/settings/layouts/SettingsLayout"; -import { useLocale } from "@calcom/lib/hooks/useLocale"; -import { Meta } from "@calcom/ui"; - -import PageWrapper from "@components/PageWrapper"; - -import AppearancePage from "~/settings/my-account/appearance-view"; - -const Page = () => { - const { t } = useLocale(); - - return ( - <> - - - - ); -}; - -Page.getLayout = getLayout; -Page.PageWrapper = PageWrapper; - -export default Page; diff --git a/apps/web/pages/settings/my-account/calendars.tsx b/apps/web/pages/settings/my-account/calendars.tsx deleted file mode 100644 index 2dfa7cb2959d39..00000000000000 --- a/apps/web/pages/settings/my-account/calendars.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { getLayout } from "@calcom/features/settings/layouts/SettingsLayout"; -import { useLocale } from "@calcom/lib/hooks/useLocale"; -import { Meta } from "@calcom/ui"; - -import PageWrapper from "@components/PageWrapper"; -import { CalendarListContainer } from "@components/apps/CalendarListContainer"; - -import AddCalendarButton from "~/settings/my-account/components/AddCalendarButton"; - -const Page = () => { - const { t } = useLocale(); - - return ( - <> - } - borderInShellHeader={false} - /> -
- -
- - ); -}; - -Page.getLayout = getLayout; -Page.PageWrapper = PageWrapper; - -export default Page; diff --git a/apps/web/pages/settings/my-account/conferencing.tsx b/apps/web/pages/settings/my-account/conferencing.tsx deleted file mode 100644 index d4f749cff66fd5..00000000000000 --- a/apps/web/pages/settings/my-account/conferencing.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { getLayout } from "@calcom/features/settings/layouts/SettingsLayout"; -import { useLocale } from "@calcom/lib/hooks/useLocale"; -import { Button, Meta } from "@calcom/ui"; - -import PageWrapper from "@components/PageWrapper"; - -import ConferencingView from "~/settings/my-account/conferencing-view"; - -const Page = () => { - const { t } = useLocale(); - - const AddConferencingButton = () => { - return ( - - ); - }; - - return ( - <> - } - borderInShellHeader={true} - /> - - - ); -}; - -Page.getLayout = getLayout; -Page.PageWrapper = PageWrapper; - -export default Page; diff --git a/apps/web/pages/settings/my-account/general.tsx b/apps/web/pages/settings/my-account/general.tsx deleted file mode 100644 index 37eb99532c5e46..00000000000000 --- a/apps/web/pages/settings/my-account/general.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { getLayout } from "@calcom/features/settings/layouts/SettingsLayout"; -import { useLocale } from "@calcom/lib/hooks/useLocale"; -import { Meta } from "@calcom/ui"; - -import PageWrapper from "@components/PageWrapper"; - -import GeneralQueryView from "~/settings/my-account/general-view"; - -const Page = () => { - const { t } = useLocale(); - - return ( - <> - - - - ); -}; - -Page.getLayout = getLayout; -Page.PageWrapper = PageWrapper; - -export default Page; diff --git a/apps/web/pages/settings/my-account/out-of-office/index.tsx b/apps/web/pages/settings/my-account/out-of-office/index.tsx deleted file mode 100644 index 89dbb3fdb69c1c..00000000000000 --- a/apps/web/pages/settings/my-account/out-of-office/index.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { getLayout } from "@calcom/features/settings/layouts/SettingsLayout"; -import CreateNewOutOfOfficeEntryButton from "@calcom/features/settings/outOfOffice/CreateNewOutOfOfficeEntryButton"; -import { OutOfOfficeEntriesList } from "@calcom/features/settings/outOfOffice/OutOfOfficeEntriesList"; -import { useLocale } from "@calcom/lib/hooks/useLocale"; -import { trpc } from "@calcom/trpc/react"; -import { Meta, SkeletonText } from "@calcom/ui"; - -import PageWrapper from "@components/PageWrapper"; - -const Page = () => { - const { t } = useLocale(); - - const { isPending } = trpc.viewer.outOfOfficeReasonList.useQuery(); - - return ( - <> - : } - /> - - - ); -}; - -Page.getLayout = getLayout; -Page.PageWrapper = PageWrapper; - -export default Page; diff --git a/apps/web/pages/settings/my-account/profile.tsx b/apps/web/pages/settings/my-account/profile.tsx deleted file mode 100644 index 9539cec4b4b72e..00000000000000 --- a/apps/web/pages/settings/my-account/profile.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { getLayout } from "@calcom/features/settings/layouts/SettingsLayout"; -import { APP_NAME } from "@calcom/lib/constants"; -import { useLocale } from "@calcom/lib/hooks/useLocale"; -import { Meta } from "@calcom/ui"; - -import PageWrapper from "@components/PageWrapper"; - -import ProfileView from "~/settings/my-account/profile-view"; - -const Page = () => { - const { t } = useLocale(); - return ( - <> - - - - ); -}; - -Page.getLayout = getLayout; -Page.PageWrapper = PageWrapper; - -export default Page; diff --git a/apps/web/playwright/availability.e2e.ts b/apps/web/playwright/availability.e2e.ts index 961426022bf857..df923e5c66ed91 100644 --- a/apps/web/playwright/availability.e2e.ts +++ b/apps/web/playwright/availability.e2e.ts @@ -179,7 +179,7 @@ test.describe("Availablity", () => { .locator("svg") .click(); - await page.locator("[id=timeZone-lg-viewport]").fill("bras"); + await page.locator("[id=timeZone-lg-viewport]").fill("Braz"); await page.getByTestId("select-option-America/Sao_Paulo").click(); await submitAndWaitForResponse(page, "/api/trpc/availability/schedule.update?batch=1"); await page.getByTestId("add-override").click(); diff --git a/apps/web/public/static/locales/ar/common.json b/apps/web/public/static/locales/ar/common.json index e1a817bcef2e79..b4eaac0376c273 100644 --- a/apps/web/public/static/locales/ar/common.json +++ b/apps/web/public/static/locales/ar/common.json @@ -1227,6 +1227,8 @@ "number_provided": "سيتم توفير رقم الهاتف", "before_event_trigger": "قبل بدء الحدث", "event_cancelled_trigger": "عند إلغاء هذا الحدث", + "after_hosts_cal_video_no_show": "بعد عدم انضمام المضيفين إلى فيديو Cal", + "after_guests_cal_video_no_show": "بعد عدم انضمام الضيوف إلى فيديو Cal", "new_event_trigger": "متى تم حجز الحدث الجديد", "email_host_action": "إرسال رسالة إلكترونية إلى المضيف", "email_attendee_action": "إرسال رسالة إلكترونية إلى الحضور", @@ -1643,6 +1645,9 @@ "email_address_action": "إرسال بريد إلكتروني إلى عنوان بريد إلكتروني محدد", "after_event_trigger": "بعد انتهاء الحدث", "how_long_after": "كم من الوقت بعد انتهاء الحدث؟", + "how_long_after_hosts_no_show": "كم من الوقت بعد عدم ظهور المضيفين في اجتماع فيديو Cal؟", + "how_long_after_guests_no_show": "كم من الوقت بعد عدم ظهور الضيوف في اجتماع فيديو Cal؟", + "how_long_after_user_no_show_minutes": "كم من الوقت بعد عدم ظهور المستخدمين في اجتماع فيديو Cal؟", "no_available_slots": "لا توجد فترات زمنية متاحة", "time_available": "الوقت المتاح", "cant_find_the_right_conferencing_app_visit_our_app_store": "لا يمكنك العثور على تطبيق المؤتمرات المناسب؟ قم بزيارة <1>متجر التطبيقات الخاص بنا.", @@ -1668,6 +1673,7 @@ "billing_frequency": "تواتر إصدار الفواتير", "monthly": "شهريًا", "yearly": "سنويًا", + "weekly": "أسبوعيًا", "checkout": "الدفع", "your_team_disbanded_successfully": "تم حل فريقك بنجاح", "your_org_disbanded_successfully": "تم حل منظمتك بنجاح", @@ -2602,6 +2608,7 @@ "disable_email": "تعطيل البريد الإلكتروني", "grant_admin_api": "منح وصول API للمسؤول", "revoke_admin_api": "إلغاء وصول API للمسؤول", + "add_calendar_label": "إضافة تقويم {{calendar}}", "apple_connect_atom_label": "ربط تقويم Apple", "apple_connect_atom_already_connected_label": "تم ربط تقويم Apple", "apple_connect_atom_loading_label": "جارٍ التحقق من تقويم Apple", @@ -2633,6 +2640,15 @@ "month_to_date": "منذ بداية الشهر", "year_to_date": "منذ بداية السنة", "custom_range": "نطاق مخصص", + "salesforce_create_record_as": "عند الحجز، أضف الأحداث والمشاركين الجدد كالتالي:", + "salesforce_lead": "عميل محتمل", + "salesforce_contact_under_account": "جهة اتصال تحت حساب", + "salesforce_skip_entry_creation": "تخطي إنشاء سجل {{entry}} إذا لم يكن موجودًا في Salesforce", + "salesforce_if_account_does_not_exist": "إذا لم تكن جهة الاتصال موجودة تحت حساب، قم بإنشاء عميل محتمل جديد من المشارك", + "salesforce_create_new_contact_under_account": "إنشاء جهة اتصال جديدة تحت حساب بناءً على نطاق البريد الإلكتروني للمشارك وجهات الاتصال الموجودة", "mass_assign_attributes": "تعيين السمات بشكل جماعي", + "salesforce_book_directly_with_attendee_owner": "إذا كان المشارك موجودًا في Salesforce، احجز مباشرة مع المالك", + "salesforce_check_owner_of": "الكيان الذي يجب التحقق من مالكه للحجز مباشرة", + "account": "حساب", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ أضف السلاسل الجديدة أعلاه هنا ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/az/common.json b/apps/web/public/static/locales/az/common.json index d84109c8d04414..6ad3fd39324a69 100644 --- a/apps/web/public/static/locales/az/common.json +++ b/apps/web/public/static/locales/az/common.json @@ -1227,6 +1227,8 @@ "number_provided": "Telefon nömrəsi təmin ediləcək", "before_event_trigger": "tədbir başlamazdan əvvəl", "event_cancelled_trigger": "tədbir ləğv edildikdə", + "after_hosts_cal_video_no_show": "Ev sahibləri Cal video görüşünə qoşulmadıqdan sonra", + "after_guests_cal_video_no_show": "Qonaqlar Cal video görüşünə qoşulmadıqdan sonra", "new_event_trigger": "yeni tədbir sifariş edildikdə", "email_host_action": "ev sahibinə e-poçt göndərin", "email_attendee_action": "iştirakçılara e-poçt göndərin", @@ -1643,6 +1645,9 @@ "email_address_action": "müəyyən bir e-poçt ünvanına e-poçt göndərin", "after_event_trigger": "hadisə bitdikdən sonra", "how_long_after": "Hadisə bitdikdən nə qədər sonra?", + "how_long_after_hosts_no_show": "Ev sahibləri Cal video görüşünə gəlmədikdən nə qədər sonra?", + "how_long_after_guests_no_show": "Qonaqlar Cal video görüşünə gəlmədikdən nə qədər sonra?", + "how_long_after_user_no_show_minutes": "İstifadəçilər Cal video görüşünə gəlmədikdən nə qədər sonra?", "no_available_slots": "Mövcud vaxtlar yoxdur", "time_available": "Mövcud vaxt", "cant_find_the_right_conferencing_app_visit_our_app_store": "Düzgün konfrans tətbiqini tapa bilmirsiniz? <1>Tətbiq Mağazamızı ziyarət edin.", @@ -1668,6 +1673,7 @@ "billing_frequency": "Ödəniş tezliyi", "monthly": "Aylıq", "yearly": "İllik", + "weekly": "Həftəlik", "checkout": "Ödəniş", "your_team_disbanded_successfully": "Komandanız uğurla dağıldı", "your_org_disbanded_successfully": "Təşkilatınız uğurla dağıldı", @@ -2602,6 +2608,7 @@ "disable_email": "E-poçtu deaktiv et", "grant_admin_api": "Admin API Girişini Ver", "revoke_admin_api": "Admin API Girişini Ləğv et", + "add_calendar_label": "{{calendar}} Təqvimini əlavə et", "apple_connect_atom_label": "Apple Təqvimi Bağla", "apple_connect_atom_already_connected_label": "Apple Təqvimi Bağlıdır", "apple_connect_atom_loading_label": "Apple Təqvimi Yoxlanılır", @@ -2633,6 +2640,15 @@ "month_to_date": "bu ayın tarixinə qədər", "year_to_date": "bu ilin tarixinə qədər", "custom_range": "xüsusi aralıq", + "salesforce_create_record_as": "Rezervasiya zamanı tədbirləri əlavə edin və yeni iştirakçıları belə qeyd edin:", + "salesforce_lead": "Potensial müştəri", + "salesforce_contact_under_account": "Hesab altında əlaqə", + "salesforce_skip_entry_creation": "Əgər {{entry}} Salesforce-da mövcud deyilsə, qeyd yaratmağı keçin", + "salesforce_if_account_does_not_exist": "Əgər əlaqə hesab altında mövcud deyilsə, iştirakçıdan yeni potensial müştəri yaradın", + "salesforce_create_new_contact_under_account": "İştirakçının email domeni və mövcud əlaqələr əsasında hesab altında yeni əlaqə yaradın", "mass_assign_attributes": "Atributları kütləvi təyin et", + "salesforce_book_directly_with_attendee_owner": "Əgər iştirakçı Salesforce-da mövcuddursa, birbaşa sahib ilə rezervasiya edin", + "salesforce_check_owner_of": "Birbaşa rezervasiya etmək üçün sahibini yoxlayacaq obyekt", + "account": "Hesab", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Yeni sətirləri bura əlavə edin ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/cs/common.json b/apps/web/public/static/locales/cs/common.json index 76f7341a98ee77..c76113d44984af 100644 --- a/apps/web/public/static/locales/cs/common.json +++ b/apps/web/public/static/locales/cs/common.json @@ -1227,6 +1227,8 @@ "number_provided": "Bude uvedeno telefonní číslo", "before_event_trigger": "před zahájením události", "event_cancelled_trigger": "při zrušení události", + "after_hosts_cal_video_no_show": "Po tom, co se hostitelé nepřipojí k cal video", + "after_guests_cal_video_no_show": "Po tom, co se hosté nepřipojí k cal video", "new_event_trigger": "při rezervaci nové události", "email_host_action": "odeslání e-mailu hostiteli", "email_attendee_action": "odeslat e-mail účastníkům", @@ -1643,6 +1645,9 @@ "email_address_action": "odeslat e-mail na specifickou e-mailovou adresu", "after_event_trigger": "po ukončení události", "how_long_after": "Jak dlouho po ukončení události?", + "how_long_after_hosts_no_show": "Jak dlouho po tom, co se hostitelé neobjeví na cal video schůzce?", + "how_long_after_guests_no_show": "Jak dlouho po tom, co se hosté neobjeví na cal video schůzce?", + "how_long_after_user_no_show_minutes": "Jak dlouho po tom, co se uživatelé neobjeví na cal video schůzce?", "no_available_slots": "Žádné dostupné sloty", "time_available": "Dostupný čas", "cant_find_the_right_conferencing_app_visit_our_app_store": "Nemůžete najít správnou konferenční aplikaci? Navštivte náš <1>App Store.", @@ -1668,6 +1673,7 @@ "billing_frequency": "Četnost fakturací", "monthly": "Měsíčně", "yearly": "Ročně", + "weekly": "Týdně", "checkout": "Platba", "your_team_disbanded_successfully": "Váš tým byl úspěšně rozpuštěn", "your_org_disbanded_successfully": "Vaše organizace byla rozpuštěna", @@ -2602,6 +2608,7 @@ "disable_email": "Zakázat e-mail", "grant_admin_api": "Udělit přístup k Admin API", "revoke_admin_api": "Odebrat přístup k Admin API", + "add_calendar_label": "Přidat kalendář {{calendar}}", "apple_connect_atom_label": "Připojit Apple Kalendář", "apple_connect_atom_already_connected_label": "Připojený Apple Kalendář", "apple_connect_atom_loading_label": "Kontrola Apple Kalendáře", @@ -2633,6 +2640,15 @@ "month_to_date": "od začátku měsíce", "year_to_date": "od začátku roku", "custom_range": "vlastní rozsah", + "salesforce_create_record_as": "Při rezervaci přidejte události a nové účastníky jako:", + "salesforce_lead": "Lead", + "salesforce_contact_under_account": "Kontakt pod účtem", + "salesforce_skip_entry_creation": "Přeskočit vytvoření záznamu {{entry}}, pokud neexistuje v Salesforce", + "salesforce_if_account_does_not_exist": "Pokud kontakt neexistuje pod účtem, vytvořte nový lead z účastníka", + "salesforce_create_new_contact_under_account": "Vytvořte nový kontakt pod účtem na základě e-mailové domény účastníka a existujících kontaktů", "mass_assign_attributes": "Hromadné přiřazení atributů", + "salesforce_book_directly_with_attendee_owner": "Pokud účastník existuje v Salesforce, rezervujte přímo s vlastníkem", + "salesforce_check_owner_of": "Entita ke kontrole vlastníka pro přímou rezervaci", + "account": "Účet", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Přidejte své nové řetězce nahoru ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/da/common.json b/apps/web/public/static/locales/da/common.json index eb7248c6d49464..9b210d73e34fd6 100644 --- a/apps/web/public/static/locales/da/common.json +++ b/apps/web/public/static/locales/da/common.json @@ -1227,6 +1227,8 @@ "number_provided": "Telefonnummer vil blive angivet", "before_event_trigger": "før begivenheden starter", "event_cancelled_trigger": "når begivenheden er aflyst", + "after_hosts_cal_video_no_show": "Efter værter ikke deltager i cal video", + "after_guests_cal_video_no_show": "Efter gæster ikke deltager i cal video", "new_event_trigger": "når ny begivenhed er booket", "email_host_action": "send e-mail til vært", "email_attendee_action": "send e-mail til deltagere", @@ -1643,6 +1645,9 @@ "email_address_action": "send e-mail til en specifik e-mailadresse", "after_event_trigger": "efter begivenheden slutter", "how_long_after": "Hvor længe efter begivenheden slutter?", + "how_long_after_hosts_no_show": "Hvor lang tid efter værter ikke dukker op til cal video møde?", + "how_long_after_guests_no_show": "Hvor lang tid efter gæster ikke dukker op til cal video møde?", + "how_long_after_user_no_show_minutes": "Hvor lang tid efter brugerne ikke dukker op til cal video møde?", "no_available_slots": "Ingen ledige tidsrum", "time_available": "Tid tilgængelig", "cant_find_the_right_conferencing_app_visit_our_app_store": "Kan du ikke finde den rigtige konferenceapp? Besøg vores <1>App Store.", @@ -1668,6 +1673,7 @@ "billing_frequency": "Faktureringsfrekvens", "monthly": "Månedligt", "yearly": "Årligt", + "weekly": "Ugentligt", "checkout": "Checkout", "your_team_disbanded_successfully": "Dit team er blevet opløst", "your_org_disbanded_successfully": "Din organisation er blevet opløst med succes", @@ -2602,6 +2608,7 @@ "disable_email": "Deaktiver email", "grant_admin_api": "Giv Admin API-adgang", "revoke_admin_api": "Tilbagekald Admin API-adgang", + "add_calendar_label": "Tilføj {{calendar}} kalender", "apple_connect_atom_label": "Forbind Apple Calendar", "apple_connect_atom_already_connected_label": "Forbundet Apple Kalender", "apple_connect_atom_loading_label": "Kontrollerer Apple Kalender", @@ -2633,6 +2640,15 @@ "month_to_date": "måned til dato", "year_to_date": "år til dato", "custom_range": "tilpasset interval", + "salesforce_create_record_as": "Ved booking, tilføj begivenheder og nye deltagere som:", + "salesforce_lead": "Lead", + "salesforce_contact_under_account": "Kontakt under en konto", + "salesforce_skip_entry_creation": "Spring oprettelse af {{entry}}-post over, hvis de ikke findes i Salesforce", + "salesforce_if_account_does_not_exist": "Hvis kontakten ikke findes under en konto, opret nyt lead fra deltager", + "salesforce_create_new_contact_under_account": "Opret en ny kontakt under en konto baseret på deltagerens e-maildomæne og eksisterende kontakter", "mass_assign_attributes": "Masse tildel attributter", + "salesforce_book_directly_with_attendee_owner": "Hvis deltageren findes i Salesforce, book direkte med ejeren", + "salesforce_check_owner_of": "Enhed til at tjekke ejeren af for at booke direkte", + "account": "Konto", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Tilføj dine nye strenge ovenfor her ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/de/common.json b/apps/web/public/static/locales/de/common.json index 10142123702567..a63a8ad8de930d 100644 --- a/apps/web/public/static/locales/de/common.json +++ b/apps/web/public/static/locales/de/common.json @@ -1227,6 +1227,8 @@ "number_provided": "Telefonnummer wird angegeben", "before_event_trigger": "vor Beginn des Termins", "event_cancelled_trigger": "wenn der Termin abgesagt wird", + "after_hosts_cal_video_no_show": "Nachdem Gastgeber nicht zum Cal-Video erscheinen", + "after_guests_cal_video_no_show": "Nachdem Gäste nicht zum Cal-Video erscheinen", "new_event_trigger": "wenn ein neuer Termin gebucht wird", "email_host_action": "E-Mail an den Veranstalter senden", "email_attendee_action": "E-Mail an Teilnehmende senden", @@ -1643,6 +1645,9 @@ "email_address_action": "eine E-Mail an eine bestimmte E-Mail-Adresse senden", "after_event_trigger": "nach Ende des Termins", "how_long_after": "Wie lange nach Ende des Termins?", + "how_long_after_hosts_no_show": "Wie lange nachdem Gastgeber nicht zum Cal-Video-Meeting erscheinen?", + "how_long_after_guests_no_show": "Wie lange nachdem Gäste nicht zum Cal-Video-Meeting erscheinen?", + "how_long_after_user_no_show_minutes": "Wie viele Minuten nachdem die Teilnehmer nicht zum Cal-Video-Meeting erscheinen?", "no_available_slots": "Keine verfügbaren Plätze", "time_available": "Zeit verfügbar", "cant_find_the_right_conferencing_app_visit_our_app_store": "Können Sie die richtige Konferenz-App nicht finden? Besuchen Sie unseren <1>App Store.", @@ -1668,6 +1673,7 @@ "billing_frequency": "Rechnungshäufigkeit", "monthly": "Monatlich", "yearly": "Jährlich", + "weekly": "Wöchentlich", "checkout": "Kasse", "your_team_disbanded_successfully": "Ihr Team wurde erfolgreich aufgelöst", "your_org_disbanded_successfully": "Ihre Organization wurde erfolgreich aufgelöst", @@ -2602,6 +2608,7 @@ "disable_email": "E-Mail deaktivieren", "grant_admin_api": "Admin-API-Zugriff gewähren", "revoke_admin_api": "Admin-API-Zugriff widerrufen", + "add_calendar_label": "{{calendar}}-Kalender hinzufügen", "apple_connect_atom_label": "Apple Kalender verbinden", "apple_connect_atom_already_connected_label": "Apple Kalender verbunden", "apple_connect_atom_loading_label": "Apple Kalender wird überprüft", @@ -2633,6 +2640,15 @@ "month_to_date": "aktueller Monat", "year_to_date": "aktuelles Jahr", "custom_range": "benutzerdefinierter Zeitraum", + "salesforce_create_record_as": "Bei der Buchung Ereignisse und neue Teilnehmer hinzufügen als:", + "salesforce_lead": "Lead", + "salesforce_contact_under_account": "Kontakt unter einem Account", + "salesforce_skip_entry_creation": "Überspringen Sie die Erstellung eines {{entry}}-Datensatzes, wenn dieser nicht in Salesforce existiert", + "salesforce_if_account_does_not_exist": "Wenn der Kontakt nicht unter einem Account existiert, erstellen Sie einen neuen Lead aus dem Teilnehmer", + "salesforce_create_new_contact_under_account": "Erstellen Sie einen neuen Kontakt unter einem Account basierend auf der E-Mail-Domain des Teilnehmers und bestehenden Kontakten", "mass_assign_attributes": "Attribute massenweise zuweisen", + "salesforce_book_directly_with_attendee_owner": "Wenn der Teilnehmer in Salesforce existiert, buchen Sie direkt beim Besitzer", + "salesforce_check_owner_of": "Entität, deren Besitzer für die direkte Buchung überprüft werden soll", + "account": "Account", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Fügen Sie Ihre neuen Code-Zeilen über dieser hinzu ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/en/common.json b/apps/web/public/static/locales/en/common.json index 6eb5d6e481f962..f22c2c06d4df87 100644 --- a/apps/web/public/static/locales/en/common.json +++ b/apps/web/public/static/locales/en/common.json @@ -1227,6 +1227,8 @@ "number_provided": "Phone number will be provided", "before_event_trigger": "before event starts", "event_cancelled_trigger": "when event is canceled", + "after_hosts_cal_video_no_show": "After hosts don't join cal video", + "after_guests_cal_video_no_show": "After guests don't join cal video", "new_event_trigger": "when new event is booked", "email_host_action": "send email to host", "email_attendee_action": "send email to attendees", @@ -1643,6 +1645,9 @@ "email_address_action": "send email to a specific email address", "after_event_trigger": "after event ends", "how_long_after": "How long after event ends?", + "how_long_after_hosts_no_show": "How long after hosts don't show up on cal video meeting?", + "how_long_after_guests_no_show": "How long after guests don't show up on cal video meeting?", + "how_long_after_user_no_show_minutes": "How long after the users don't show up on cal video meeting?", "no_available_slots": "No Available slots", "time_available": "Time available", "cant_find_the_right_conferencing_app_visit_our_app_store": "Can't find the right conferencing app? Visit our <1>App Store.", @@ -2639,6 +2644,15 @@ "month_to_date": "month to date", "year_to_date": "year to date", "custom_range": "custom range", + "salesforce_create_record_as": "On booking, add events on and new attendees as:", + "salesforce_lead": "Lead", + "salesforce_contact_under_account": "Contact under an account", + "salesforce_skip_entry_creation": "Skip creating {{entry}} record if they do not exist in Salesforce", + "salesforce_if_account_does_not_exist": "If the contact does not exist under an account, create new lead from attendee", + "salesforce_create_new_contact_under_account": "Create a new contact under an account based on email domain of attendee and existing contacts", "mass_assign_attributes": "Mass assign attributes", + "salesforce_book_directly_with_attendee_owner": "If attendee exists in Salesforce, book directly with the owner", + "salesforce_check_owner_of": "Entity to check owner of to book directly", + "account": "Account", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/es-419/common.json b/apps/web/public/static/locales/es-419/common.json index 2b538d697ce907..4f4a09613e6ebe 100644 --- a/apps/web/public/static/locales/es-419/common.json +++ b/apps/web/public/static/locales/es-419/common.json @@ -1227,6 +1227,8 @@ "number_provided": "Se proporcionará el número de teléfono", "before_event_trigger": "antes de que comience el evento", "event_cancelled_trigger": "cuando el evento está cancelado", + "after_hosts_cal_video_no_show": "Después de que los anfitriones no se unan al video de Cal", + "after_guests_cal_video_no_show": "Después de que los invitados no se unan al video de Cal", "new_event_trigger": "cuando se reserva un nuevo evento", "email_host_action": "enviar correo electrónico al anfitrión", "email_attendee_action": "enviar correo electrónico a los asistentes", @@ -1643,6 +1645,9 @@ "email_address_action": "enviar correo electrónico a una dirección específica", "after_event_trigger": "después de que termine el evento", "how_long_after": "¿Cuánto tiempo después de que termine el evento?", + "how_long_after_hosts_no_show": "¿Cuánto tiempo después de que los anfitriones no se presenten en la reunión de video de Cal?", + "how_long_after_guests_no_show": "¿Cuánto tiempo después de que los invitados no se presenten en la reunión de video de Cal?", + "how_long_after_user_no_show_minutes": "¿Cuánto tiempo después de que los usuarios no se presenten en la reunión de video de Cal?", "no_available_slots": "No hay espacios disponibles", "time_available": "Tiempo disponible", "cant_find_the_right_conferencing_app_visit_our_app_store": "¿No puedes encontrar la aplicación de conferencias adecuada? Visita nuestra <1>Tienda de Aplicaciones.", @@ -1668,6 +1673,7 @@ "billing_frequency": "Frecuencia de facturación", "monthly": "Mensual", "yearly": "Anual", + "weekly": "Semanal", "checkout": "Pagar", "your_team_disbanded_successfully": "Tu equipo se ha disuelto con éxito", "your_org_disbanded_successfully": "Tu organización se ha disuelto con éxito", @@ -2602,6 +2608,7 @@ "disable_email": "Desactivar correo electrónico", "grant_admin_api": "Conceder acceso a la API de administrador", "revoke_admin_api": "Revocar acceso a la API de administrador", + "add_calendar_label": "Agregar calendario de {{calendar}}", "apple_connect_atom_label": "Conectar Calendario de Apple", "apple_connect_atom_already_connected_label": "Calendario de Apple conectado", "apple_connect_atom_loading_label": "Verificando Calendario de Apple", @@ -2633,6 +2640,15 @@ "month_to_date": "mes hasta la fecha", "year_to_date": "año hasta la fecha", "custom_range": "rango personalizado", + "salesforce_create_record_as": "Al reservar, agregar eventos y nuevos asistentes como:", + "salesforce_lead": "Cliente potencial", + "salesforce_contact_under_account": "Contacto bajo una cuenta", + "salesforce_skip_entry_creation": "Omitir la creación del registro de {{entry}} si no existe en Salesforce", + "salesforce_if_account_does_not_exist": "Si el contacto no existe bajo una cuenta, crear un nuevo cliente potencial a partir del asistente", + "salesforce_create_new_contact_under_account": "Crear un nuevo contacto bajo una cuenta basado en el dominio de correo electrónico del asistente y los contactos existentes", "mass_assign_attributes": "Asignar atributos en masa", + "salesforce_book_directly_with_attendee_owner": "Si el asistente existe en Salesforce, reservar directamente con el propietario", + "salesforce_check_owner_of": "Entidad de la cual verificar el propietario para reservar directamente", + "account": "Cuenta", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Agrega tus nuevas cadenas arriba de esta línea ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/es/common.json b/apps/web/public/static/locales/es/common.json index 2aa2d493a5a19a..bf0947a8a2ea20 100644 --- a/apps/web/public/static/locales/es/common.json +++ b/apps/web/public/static/locales/es/common.json @@ -1227,6 +1227,8 @@ "number_provided": "Se proporcionará el número de teléfono", "before_event_trigger": "antes del inicio del evento", "event_cancelled_trigger": "cuando se cancela el evento", + "after_hosts_cal_video_no_show": "Después de que los anfitriones no se unan al video de Cal", + "after_guests_cal_video_no_show": "Después de que los invitados no se unan al video de Cal", "new_event_trigger": "cuando se reserva un nuevo evento", "email_host_action": "enviar correo electrónico al anfitrión", "email_attendee_action": "enviar correo electrónico a los asistentes", @@ -1334,7 +1336,7 @@ "new_seat_title": "Alguien se ha añadido a un evento", "variable": "Variable", "event_name_variable": "Nombre del evento", - "attendee_name_variable": "Nombre del asistente", + "attendee_name_variable": "Nombre completo del asistente", "event_date_variable": "Fecha del evento", "event_time_variable": "Hora del evento", "organizer_name_variable": "Nombre del organizador", @@ -1490,7 +1492,7 @@ "location_info": "Ubicación del evento", "additional_notes_variable": "Notas Adicionales", "additional_notes_info": "Notas adicionales de la reserva", - "attendee_name_info": "Nombre de la persona que reserva", + "attendee_name_info": "Nombre completo de la persona que reserva", "organizer_name_info": "Nombre del organizador", "to": "Para", "workflow_turned_on_successfully": "El flujo de trabajo {{workflowName}} se ha activado {{offOn}} con éxito", @@ -1643,6 +1645,9 @@ "email_address_action": "enviar un correo electrónico a una dirección específica", "after_event_trigger": "después de que el evento termine", "how_long_after": "¿Cuánto tiempo después de que termine el evento?", + "how_long_after_hosts_no_show": "¿Cuánto tiempo después de que los anfitriones no se presenten en la reunión de video de Cal?", + "how_long_after_guests_no_show": "¿Cuánto tiempo después de que los invitados no se presenten en la reunión de video de Cal?", + "how_long_after_user_no_show_minutes": "¿Cuánto tiempo después de que los usuarios no se presenten en la reunión de video de Cal?", "no_available_slots": "No hay espacios disponibles", "time_available": "Tiempo disponible", "cant_find_the_right_conferencing_app_visit_our_app_store": "¿No encuentra la aplicación de conferencias adecuada? Visite nuestra <1>Tienda de aplicaciones.", @@ -1668,6 +1673,7 @@ "billing_frequency": "Frecuencia de facturación", "monthly": "Mensual", "yearly": "Anual", + "weekly": "Semanal", "checkout": "Proceder al pago", "your_team_disbanded_successfully": "Su equipo se ha disuelto con éxito", "your_org_disbanded_successfully": "Su organización se ha disuelto con éxito", @@ -2209,7 +2215,7 @@ "no_other_teams_found_description": "No hay otros equipos en esta organización.", "attendee_first_name_variable": "Nombre del asistente", "attendee_last_name_variable": "Apellido del asistente", - "attendee_first_name_info": "Nombre de la persona que reserva", + "attendee_first_name_info": "Primer nombre de la persona que reserva", "attendee_last_name_info": "Apellido de la persona que reserva", "your_monthly_digest": "Su resumen mensual", "member_name": "Nombre del miembro", @@ -2602,6 +2608,7 @@ "disable_email": "Desactivar correo electrónico", "grant_admin_api": "Conceder acceso a la API de administrador", "revoke_admin_api": "Revocar acceso a la API de administrador", + "add_calendar_label": "Agregar calendario de {{calendar}}", "apple_connect_atom_label": "Conectar Calendario de Apple", "apple_connect_atom_already_connected_label": "Calendario de Apple conectado", "apple_connect_atom_loading_label": "Comprobando Calendario de Apple", @@ -2633,6 +2640,15 @@ "month_to_date": "mes hasta la fecha", "year_to_date": "año hasta la fecha", "custom_range": "rango personalizado", + "salesforce_create_record_as": "Al reservar, agregar eventos y nuevos asistentes como:", + "salesforce_lead": "Cliente potencial", + "salesforce_contact_under_account": "Contacto bajo una cuenta", + "salesforce_skip_entry_creation": "Omitir la creación del registro de {{entry}} si no existe en Salesforce", + "salesforce_if_account_does_not_exist": "Si el contacto no existe bajo una cuenta, crear un nuevo cliente potencial a partir del asistente", + "salesforce_create_new_contact_under_account": "Crear un nuevo contacto bajo una cuenta basado en el dominio de correo electrónico del asistente y los contactos existentes", "mass_assign_attributes": "Asignar atributos en masa", + "salesforce_book_directly_with_attendee_owner": "Si el asistente existe en Salesforce, reservar directamente con el propietario", + "salesforce_check_owner_of": "Entidad de la que verificar el propietario para reservar directamente", + "account": "Cuenta", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Agregue sus nuevas cadenas arriba ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/et/common.json b/apps/web/public/static/locales/et/common.json index ba0de637aa59e5..dd7143f9fe2286 100644 --- a/apps/web/public/static/locales/et/common.json +++ b/apps/web/public/static/locales/et/common.json @@ -1227,6 +1227,8 @@ "number_provided": "Telefoninumber antakse", "before_event_trigger": "enne ürituse algust", "event_cancelled_trigger": "Kui sündmus tühistatakse", + "after_hosts_cal_video_no_show": "Pärast seda, kui võõrustajad ei liitu Cal videokõnega", + "after_guests_cal_video_no_show": "Pärast seda, kui külalised ei liitu Cal videokõnega", "new_event_trigger": "kui uus sündmus on broneeritud", "email_host_action": "saada e-kiri hostile", "email_attendee_action": "saada osalejatele e-kiri", @@ -1643,6 +1645,9 @@ "email_address_action": "saada e-kiri kindlale e-posti aadressile", "after_event_trigger": "pärast sündmuse lõppu", "how_long_after": "Kui kaua pärast ürituse lõppu?", + "how_long_after_hosts_no_show": "Kui kaua pärast seda, kui võõrustajad ei ilmu Cal videokoosolekule?", + "how_long_after_guests_no_show": "Kui kaua pärast seda, kui külalised ei ilmu Cal videokoosolekule?", + "how_long_after_user_no_show_minutes": "Kui mitu minutit pärast seda, kui kasutajad ei ilmu Cal videokoosolekule?", "no_available_slots": "Saadaolevaid teenindusaegu pole", "time_available": "Aeg saadaval", "cant_find_the_right_conferencing_app_visit_our_app_store": "Ei leia õiget konverentsirakendust? Külastage meie <1>Rakenduste Poodi.", @@ -1668,6 +1673,7 @@ "billing_frequency": "Arveldussagedus", "monthly": "Igakuine", "yearly": "Iga-aastane", + "weekly": "Iganädalane", "checkout": "Kassasse", "your_team_disbanded_successfully": "Teie meeskond on edukalt laiali saadetud", "your_org_disbanded_successfully": "Teie organisatsioon on edukalt laiali saadetud", @@ -2602,6 +2608,7 @@ "disable_email": "Keela e-post", "grant_admin_api": "Anna Admin API juurdepääs", "revoke_admin_api": "Tühista Admin API juurdepääs", + "add_calendar_label": "Lisa {{calendar}} kalender", "apple_connect_atom_label": "Ühenda Apple Kalender", "apple_connect_atom_already_connected_label": "Apple Kalender ühendatud", "apple_connect_atom_loading_label": "Kontrollin Apple Kalendrit", @@ -2633,6 +2640,15 @@ "month_to_date": "kuu algusest tänaseni", "year_to_date": "aasta algusest tänaseni", "custom_range": "kohandatud vahemik", + "salesforce_create_record_as": "Broneeringu korral lisa sündmused ja uued osalejad kui:", + "salesforce_lead": "Müügivihje", + "salesforce_contact_under_account": "Kontakt konto all", + "salesforce_skip_entry_creation": "Jäta {{entry}} kirje loomata, kui seda Salesforce'is ei eksisteeri", + "salesforce_if_account_does_not_exist": "Kui kontakti ei eksisteeri konto all, loo osaleja andmetest uus müügivihje", + "salesforce_create_new_contact_under_account": "Loo uus kontakt konto alla, põhinedes osaleja e-posti domeenile ja olemasolevatele kontaktidele", "mass_assign_attributes": "Massiline atribuutide määramine", + "salesforce_book_directly_with_attendee_owner": "Kui osaleja eksisteerib Salesforce'is, broneeri otse omanikuga", + "salesforce_check_owner_of": "Üksus, mille omanikku kontrollida otsebroneerimiseks", + "account": "Konto", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/fr/common.json b/apps/web/public/static/locales/fr/common.json index 29d23c348450fb..3a6ed3902841ee 100644 --- a/apps/web/public/static/locales/fr/common.json +++ b/apps/web/public/static/locales/fr/common.json @@ -1227,6 +1227,8 @@ "number_provided": "Un numéro de téléphone sera fourni", "before_event_trigger": "avant le début de l'événement", "event_cancelled_trigger": "lorsque l'événement est annulé", + "after_hosts_cal_video_no_show": "Après que les hôtes ne rejoignent pas la vidéo Cal", + "after_guests_cal_video_no_show": "Après que les invités ne rejoignent pas la vidéo Cal", "new_event_trigger": "lorsqu'un nouvel événement est réservé", "email_host_action": "envoyer un e-mail à l'hôte", "email_attendee_action": "envoyer un e-mail aux participants", @@ -1643,6 +1645,9 @@ "email_address_action": "envoyer un e-mail à une adresse e-mail spécifique", "after_event_trigger": "après la fin de l'événement", "how_long_after": "Combien de temps après la fin de l'événement ?", + "how_long_after_hosts_no_show": "Combien de temps après que les hôtes ne se présentent pas à la réunion vidéo Cal ?", + "how_long_after_guests_no_show": "Combien de temps après que les invités ne se présentent pas à la réunion vidéo Cal ?", + "how_long_after_user_no_show_minutes": "Combien de minutes après que les utilisateurs ne se présentent pas à la réunion vidéo Cal ?", "no_available_slots": "Aucun créneau disponible", "time_available": "Disponibilités", "cant_find_the_right_conferencing_app_visit_our_app_store": "Vous ne trouvez pas l'application de visioconférence adaptée ? Visitez notre <1>App Store.", @@ -1668,6 +1673,7 @@ "billing_frequency": "Fréquence de facturation", "monthly": "Mensuellement", "yearly": "Annuellement", + "weekly": "Hebdomadaire", "checkout": "Paiement", "your_team_disbanded_successfully": "Votre équipe a bien été dissoute", "your_org_disbanded_successfully": "Votre organisation a bien été dissoute", @@ -2602,6 +2608,7 @@ "disable_email": "Désactiver l'e-mail", "grant_admin_api": "Accorder l'accès à l'API d'administration", "revoke_admin_api": "Révoquer l'accès à l'API d'administration", + "add_calendar_label": "Ajouter le calendrier {{calendar}}", "apple_connect_atom_label": "Connecter le calendrier Apple", "apple_connect_atom_already_connected_label": "Calendrier Apple connecté", "apple_connect_atom_loading_label": "Vérification du calendrier Apple", @@ -2633,6 +2640,15 @@ "month_to_date": "mois en cours", "year_to_date": "année en cours", "custom_range": "période personnalisée", + "salesforce_create_record_as": "Lors de la réservation, ajouter les événements et les nouveaux participants en tant que :", + "salesforce_lead": "Prospect", + "salesforce_contact_under_account": "Contact sous un compte", + "salesforce_skip_entry_creation": "Ne pas créer d'enregistrement {{entry}} s'il n'existe pas dans Salesforce", + "salesforce_if_account_does_not_exist": "Si le contact n'existe pas sous un compte, créer un nouveau prospect à partir du participant", + "salesforce_create_new_contact_under_account": "Créer un nouveau contact sous un compte basé sur le domaine e-mail du participant et les contacts existants", "mass_assign_attributes": "Attribuer des attributs en masse", + "salesforce_book_directly_with_attendee_owner": "Si le participant existe dans Salesforce, réserver directement avec le propriétaire", + "salesforce_check_owner_of": "Entité dont il faut vérifier le propriétaire pour réserver directement", + "account": "Compte", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Ajoutez vos nouvelles chaînes ci-dessus ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/he/common.json b/apps/web/public/static/locales/he/common.json index 599c4e9da9b3aa..0bcc19cefbe902 100644 --- a/apps/web/public/static/locales/he/common.json +++ b/apps/web/public/static/locales/he/common.json @@ -1227,6 +1227,8 @@ "number_provided": "מספר הטלפון יסופק", "before_event_trigger": "לפני שהאירוע מתחיל", "event_cancelled_trigger": "כאשר אירוע מבוטל", + "after_hosts_cal_video_no_show": "לאחר שהמארחים לא מצטרפים לשיחת הווידאו ב-Cal", + "after_guests_cal_video_no_show": "לאחר שהאורחים לא מצטרפים לשיחת הווידאו ב-Cal", "new_event_trigger": "כאשר אירוע חדש מוזמן", "email_host_action": "שלח מייל למארח", "email_attendee_action": "שליחת דוא\"ל למשתתפים", @@ -1643,6 +1645,9 @@ "email_address_action": "לשלוח דוא״ל לכתובת מסוימת", "after_event_trigger": "לאחר סיום האירוע", "how_long_after": "כמה זמן לאחר סיום האירוע?", + "how_long_after_hosts_no_show": "כמה זמן לאחר שהמארחים לא מופיעים בשיחת הווידאו ב-Cal?", + "how_long_after_guests_no_show": "כמה זמן לאחר שהאורחים לא מופיעים בשיחת הווידאו ב-Cal?", + "how_long_after_user_no_show_minutes": "כמה זמן לאחר שהמשתמשים לא מופיעים בשיחת הווידאו ב-Cal?", "no_available_slots": "אין חלונות זמן זמינים", "time_available": "זמן זמין", "cant_find_the_right_conferencing_app_visit_our_app_store": "לא מוצאים את אפליקציית הווידאו המתאימה? בקרו ב<1>חנות האפליקציות שלנו.", @@ -1668,6 +1673,7 @@ "billing_frequency": "תדירות חיוב", "monthly": "אחת לחודש", "yearly": "אחת לשנה", + "weekly": "שבועי", "checkout": "תשלום", "your_team_disbanded_successfully": "פיזור הצוות שלך בוצע בהצלחה", "your_org_disbanded_successfully": "פירוק הארגון שלך בוצע בהצלחה", @@ -2602,6 +2608,7 @@ "disable_email": "השבת דוא\"ל", "grant_admin_api": "הענק גישת API למנהל", "revoke_admin_api": "בטל גישת API למנהל", + "add_calendar_label": "הוסף לוח שנה {{calendar}}", "apple_connect_atom_label": "חבר לוח שנה של Apple", "apple_connect_atom_already_connected_label": "לוח שנה של Apple מחובר", "apple_connect_atom_loading_label": "בודק לוח שנה של Apple", @@ -2633,6 +2640,15 @@ "month_to_date": "מתחילת החודש", "year_to_date": "מתחילת השנה", "custom_range": "טווח מותאם אישית", + "salesforce_create_record_as": "בעת הזמנה, הוסף אירועים וחדשים משתתפים כ:", + "salesforce_lead": "ליד", + "salesforce_contact_under_account": "איש קשר תחת חשבון", + "salesforce_skip_entry_creation": "דלג על יצירת רשומת {{entry}} אם הם לא קיימים ב-Salesforce", + "salesforce_if_account_does_not_exist": "אם איש הקשר לא קיים תחת חשבון, צור ליד חדש מהמשתתף", + "salesforce_create_new_contact_under_account": "צור איש קשר חדש תחת חשבון בהתבסס על דומיין האימייל של המשתתף ואנשי קשר קיימים", "mass_assign_attributes": "הקצאת מאפיינים באופן גורף", + "salesforce_book_directly_with_attendee_owner": "אם המשתתף קיים ב-Salesforce, הזמן ישירות עם הבעלים", + "salesforce_check_owner_of": "ישות לבדוק את הבעלים שלה כדי להזמין ישירות", + "account": "חשבון", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/hu/common.json b/apps/web/public/static/locales/hu/common.json index a1f53aae72e924..0221211114c588 100644 --- a/apps/web/public/static/locales/hu/common.json +++ b/apps/web/public/static/locales/hu/common.json @@ -1227,6 +1227,8 @@ "number_provided": "A telefonszámot megadjuk", "before_event_trigger": "az esemény kezdete előtt", "event_cancelled_trigger": "amikor az esemény le lett mondva", + "after_hosts_cal_video_no_show": "Miután a házigazdák nem csatlakoznak a cal videóhoz", + "after_guests_cal_video_no_show": "Miután a vendégek nem csatlakoznak a cal videóhoz", "new_event_trigger": "új esemény lefoglalásakor", "email_host_action": "küldjön e-mailt a házigazdának", "email_attendee_action": "küldjön e-mailt a résztvevőknek", @@ -1643,6 +1645,9 @@ "email_address_action": "küldjön e-mailt egy adott e-mail címre", "after_event_trigger": "az esemény befejezése után", "how_long_after": "Mennyi idővel az esemény vége után?", + "how_long_after_hosts_no_show": "Mennyi idő után, ha a házigazdák nem jelennek meg a cal videó találkozón?", + "how_long_after_guests_no_show": "Mennyi idő után, ha a vendégek nem jelennek meg a cal videó találkozón?", + "how_long_after_user_no_show_minutes": "Mennyi idő után, ha a felhasználók nem jelennek meg a cal videó találkozón?", "no_available_slots": "Nincsenek elérhető helyek", "time_available": "Rendelkezésre álló idő", "cant_find_the_right_conferencing_app_visit_our_app_store": "Nem találja a megfelelő konferencia alkalmazást? Látogasson el az <1>App Store-unkba.", @@ -1668,6 +1673,7 @@ "billing_frequency": "Számlázási gyakoriság", "monthly": "Havi", "yearly": "Évi", + "weekly": "Heti", "checkout": "Pénztár", "your_team_disbanded_successfully": "Csapatát sikeresen feloszlattuk", "your_org_disbanded_successfully": "Szervezetét sikeresen feloszlattuk", @@ -2602,6 +2608,7 @@ "disable_email": "E-mail letiltása", "grant_admin_api": "Admin API hozzáférés engedélyezése", "revoke_admin_api": "Admin API hozzáférés visszavonása", + "add_calendar_label": "{{calendar}} naptár hozzáadása", "apple_connect_atom_label": "Apple Naptár csatlakoztatása", "apple_connect_atom_already_connected_label": "Apple Naptár csatlakoztatva", "apple_connect_atom_loading_label": "Apple Naptár ellenőrzése", @@ -2633,6 +2640,15 @@ "month_to_date": "hónap elejétől", "year_to_date": "év elejétől", "custom_range": "egyéni tartomány", + "salesforce_create_record_as": "Foglaláskor adja hozzá az eseményeket és az új résztvevőket mint:", + "salesforce_lead": "Érdeklődő", + "salesforce_contact_under_account": "Kapcsolat egy fiók alatt", + "salesforce_skip_entry_creation": "Hagyja ki a(z) {{entry}} rekord létrehozását, ha nem létezik a Salesforce-ban", + "salesforce_if_account_does_not_exist": "Ha a kapcsolat nem létezik egy fiók alatt, hozzon létre új érdeklődőt a résztvevőből", + "salesforce_create_new_contact_under_account": "Hozzon létre új kapcsolatot egy fiók alatt a résztvevő e-mail domainje és meglévő kapcsolatok alapján", "mass_assign_attributes": "Attribútumok tömeges hozzárendelése", + "salesforce_book_directly_with_attendee_owner": "Ha a résztvevő létezik a Salesforce-ban, foglaljon közvetlenül a tulajdonossal", + "salesforce_check_owner_of": "Entitás, amelynek tulajdonosát ellenőrizni kell a közvetlen foglaláshoz", + "account": "Fiók", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Adja hozzá az új karakterláncokat fent ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/it/common.json b/apps/web/public/static/locales/it/common.json index 4bad8936eb7892..b7d1781c6a1e9a 100644 --- a/apps/web/public/static/locales/it/common.json +++ b/apps/web/public/static/locales/it/common.json @@ -1227,6 +1227,8 @@ "number_provided": "Verrà fornito il numero di telefono", "before_event_trigger": "prima dell'inizio dell'evento", "event_cancelled_trigger": "quando l'evento viene cancellato", + "after_hosts_cal_video_no_show": "Dopo che gli host non si uniscono al video di Cal", + "after_guests_cal_video_no_show": "Dopo che gli ospiti non si uniscono al video di Cal", "new_event_trigger": "quando viene prenotato un nuovo evento", "email_host_action": "invia e-mail all'organizzatore", "email_attendee_action": "invia e-mail ai partecipanti", @@ -1643,6 +1645,9 @@ "email_address_action": "invia e-mail a un indirizzo e-mail specifico", "after_event_trigger": "dopo la fine dell'evento", "how_long_after": "Quanto tempo dopo la fine dell'evento?", + "how_long_after_hosts_no_show": "Quanto tempo dopo che gli host non si presentano alla riunione video di Cal?", + "how_long_after_guests_no_show": "Quanto tempo dopo che gli ospiti non si presentano alla riunione video di Cal?", + "how_long_after_user_no_show_minutes": "Quanto tempo dopo che gli utenti non si presentano alla riunione video di Cal?", "no_available_slots": "Nessuna fascia oraria disponibile", "time_available": "Tempo disponibile", "cant_find_the_right_conferencing_app_visit_our_app_store": "Non riesci a trovare l'app di conferenza giusta? Visita il nostro <1>App Store.", @@ -1668,6 +1673,7 @@ "billing_frequency": "Frequenza di fatturazione", "monthly": "Mensile", "yearly": "Annuale", + "weekly": "Settimanale", "checkout": "Pagamento", "your_team_disbanded_successfully": "Il tuo team è stato sciolto correttamente", "your_org_disbanded_successfully": "La tua organizzazione è stata sciolta", @@ -2602,6 +2608,7 @@ "disable_email": "Disabilita email", "grant_admin_api": "Concedi accesso API amministratore", "revoke_admin_api": "Revoca accesso API amministratore", + "add_calendar_label": "Aggiungi il calendario {{calendar}}", "apple_connect_atom_label": "Connetti Calendario Apple", "apple_connect_atom_already_connected_label": "Calendario Apple connesso", "apple_connect_atom_loading_label": "Verifica Calendario Apple", @@ -2633,6 +2640,15 @@ "month_to_date": "mese corrente", "year_to_date": "anno corrente", "custom_range": "intervallo personalizzato", + "salesforce_create_record_as": "Al momento della prenotazione, aggiungi eventi e nuovi partecipanti come:", + "salesforce_lead": "Lead", + "salesforce_contact_under_account": "Contatto sotto un account", + "salesforce_skip_entry_creation": "Salta la creazione del record {{entry}} se non esistono in Salesforce", + "salesforce_if_account_does_not_exist": "Se il contatto non esiste sotto un account, crea un nuovo lead dal partecipante", + "salesforce_create_new_contact_under_account": "Crea un nuovo contatto sotto un account basato sul dominio email del partecipante e contatti esistenti", "mass_assign_attributes": "Assegna attributi in massa", + "salesforce_book_directly_with_attendee_owner": "Se il partecipante esiste in Salesforce, prenota direttamente con il proprietario", + "salesforce_check_owner_of": "Entità per verificare il proprietario per prenotare direttamente", + "account": "Account", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Aggiungi le tue nuove stringhe qui sopra ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/ja/common.json b/apps/web/public/static/locales/ja/common.json index 5c046ce22db791..2c9dd04bfc4b98 100644 --- a/apps/web/public/static/locales/ja/common.json +++ b/apps/web/public/static/locales/ja/common.json @@ -1227,6 +1227,8 @@ "number_provided": "電話番号が提供されます", "before_event_trigger": "イベント開始前に", "event_cancelled_trigger": "イベントキャンセル時", + "after_hosts_cal_video_no_show": "ホストがCalビデオに参加しない場合", + "after_guests_cal_video_no_show": "ゲストがCalビデオに参加しない場合", "new_event_trigger": "新しいイベント予約時に", "email_host_action": "ホストにメールを送信", "email_attendee_action": "出席者にメールを送る", @@ -1643,6 +1645,9 @@ "email_address_action": "特定のメールアドレスにメールを送信する", "after_event_trigger": "イベントの終了後", "how_long_after": "イベント終了後のどのくらい後にしますか?", + "how_long_after_hosts_no_show": "ホストがCalビデオ会議に現れない場合、どのくらい後に?", + "how_long_after_guests_no_show": "ゲストがCalビデオ会議に現れない場合、どのくらい後に?", + "how_long_after_user_no_show_minutes": "ユーザーがCalビデオ会議に現れない場合、何分後に?", "no_available_slots": "利用可能な時間帯がありません", "time_available": "利用可能な時間帯", "cant_find_the_right_conferencing_app_visit_our_app_store": "適切な会議アプリが見つかりませんか?<1>アプリストアをご覧ください。", @@ -1668,6 +1673,7 @@ "billing_frequency": "請求の頻度", "monthly": "毎月", "yearly": "毎年", + "weekly": "毎週", "checkout": "チェックアウト", "your_team_disbanded_successfully": "チームは正常に解散されました", "your_org_disbanded_successfully": "組織は正常に解散されました", @@ -2602,6 +2608,7 @@ "disable_email": "メールを無効にする", "grant_admin_api": "管理者APIアクセスを許可", "revoke_admin_api": "管理者APIアクセスを取り消し", + "add_calendar_label": "{{calendar}}カレンダーを追加", "apple_connect_atom_label": "Appleカレンダーを接続", "apple_connect_atom_already_connected_label": "接続済みのAppleカレンダー", "apple_connect_atom_loading_label": "Appleカレンダーを確認中", @@ -2633,6 +2640,15 @@ "month_to_date": "月初から今日まで", "year_to_date": "年初から今日まで", "custom_range": "カスタム範囲", + "salesforce_create_record_as": "予約時にイベントを追加し、新しい参加者を次のように追加します:", + "salesforce_lead": "リード", + "salesforce_contact_under_account": "アカウント下の連絡先", + "salesforce_skip_entry_creation": "{{entry}} レコードがSalesforceに存在しない場合、作成をスキップする", + "salesforce_if_account_does_not_exist": "連絡先がアカウントに存在しない場合、参加者から新しいリードを作成する", + "salesforce_create_new_contact_under_account": "参加者のメールドメインと既存の連絡先に基づいて、新しい連絡先をアカウント下に作成する", "mass_assign_attributes": "属性の一括割り当て", + "salesforce_book_directly_with_attendee_owner": "参加者がSalesforceに存在する場合、所有者と直接予約する", + "salesforce_check_owner_of": "直接予約するために所有者を確認するエンティティ", + "account": "アカウント", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ この上に新しい文字列を追加してください ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/km/common.json b/apps/web/public/static/locales/km/common.json index 97d674f27b0d87..d907d3a35d032e 100644 --- a/apps/web/public/static/locales/km/common.json +++ b/apps/web/public/static/locales/km/common.json @@ -1227,6 +1227,8 @@ "number_provided": "លេខទូរស័ព្ទនឹងត្រូវបានផ្តល់", "before_event_trigger": "មុនព្រឹត្តិការណ៍ចាប់ផ្តើម", "event_cancelled_trigger": "ពេលព្រឹត្តិការណ៍ត្រូវបានលុបចោល", + "after_hosts_cal_video_no_show": "បន្ទាប់ពីម្ចាស់ផ្ទះមិនចូលរួមវីដេអូ cal", + "after_guests_cal_video_no_show": "បន្ទាប់ពីភ្ញៀវមិនចូលរួមវីដេអូ cal", "new_event_trigger": "ពេលមានការកក់ព្រឹត្តិការណ៍ថ្មី", "email_host_action": "ផ្ញើអ៊ីមែលទៅម្ចាស់", "email_attendee_action": "ផ្ញើអ៊ីមែលទៅអ្នកចូលរួម", @@ -1643,6 +1645,9 @@ "email_address_action": "ផ្ញើអ៊ីមែលទៅអាសយដ្ឋានអ៊ីមែលជាក់លាក់", "after_event_trigger": "បន្ទាប់ពីព្រឹត្តិការណ៍បញ្ចប់", "how_long_after": "បន្ទាប់ពីព្រឹត្តិការណ៍បញ្ចប់យូរប៉ុណ្ណា?", + "how_long_after_hosts_no_show": "តើបន្ទាប់ពីម្ចាស់ផ្ទះមិនបង្ហាញខ្លួនក្នុងកិច្ចប្រជុំវីដេអូ cal រយៈពេលប៉ុន្មាន?", + "how_long_after_guests_no_show": "តើបន្ទាប់ពីភ្ញៀវមិនបង្ហាញខ្លួនក្នុងកិច្ចប្រជុំវីដេអូ cal រយៈពេលប៉ុន្មាន?", + "how_long_after_user_no_show_minutes": "តើបន្ទាប់ពីអ្នកប្រើមិនបង្ហាញខ្លួនក្នុងកិច្ចប្រជុំវីដេអូ cal រយៈពេលប៉ុន្មាននាទី?", "no_available_slots": "គ្មានពេលទំនេរ", "time_available": "ពេលវេលាទំនេរ", "cant_find_the_right_conferencing_app_visit_our_app_store": "រកមិនឃើញកម្មវិធីសន្និសីទត្រឹមត្រូវ? ចូលទៅកាន់ <1>App Store របស់យើង។", @@ -1668,6 +1673,7 @@ "billing_frequency": "ប្រេកង់វិក្កយបត្រ", "monthly": "ប្រចាំខែ", "yearly": "ប្រចាំឆ្នាំ", + "weekly": "ប្រចាំសប្តាហ៍", "checkout": "បញ្ជាក់ការទិញ", "your_team_disbanded_successfully": "ក្រុមរបស់អ្នកត្រូវបានរំលាយដោយជោគជ័យ", "your_org_disbanded_successfully": "អង្គការរបស់អ្នកត្រូវបានរំលាយដោយជោគជ័យ", @@ -2602,6 +2608,7 @@ "disable_email": "បិទអ៊ីមែល", "grant_admin_api": "ផ្តល់សិទ្ធិ API រដ្ឋបាល", "revoke_admin_api": "ដកសិទ្ធិ API រដ្ឋបាល", + "add_calendar_label": "បន្ថែមប្រតិទិន {{calendar}}", "apple_connect_atom_label": "ភ្ជាប់ប្រតិទិន Apple", "apple_connect_atom_already_connected_label": "បានភ្ជាប់ប្រតិទិន Apple", "apple_connect_atom_loading_label": "កំពុងពិនិត្យប្រតិទិន Apple", @@ -2633,6 +2640,15 @@ "month_to_date": "ខែនេះ", "year_to_date": "ឆ្នាំនេះ", "custom_range": "ជួរដែលកំណត់ដោយខ្លួនឯង", + "salesforce_create_record_as": "នៅពេលកក់ សូមបន្ថែមព្រឹត្តិការណ៍និងអ្នកចូលរួមថ្មីជា៖", + "salesforce_lead": "អ្នកដឹកនាំ", + "salesforce_contact_under_account": "ទំនាក់ទំនងក្រោមគណនី", + "salesforce_skip_entry_creation": "រំលងការបង្កើតកំណត់ត្រា {{entry}} ប្រសិនបើពួកគេមិនមាននៅក្នុង Salesforce", + "salesforce_if_account_does_not_exist": "ប្រសិនបើទំនាក់ទំនងមិនមានក្រោមគណនី សូមបង្កើតអ្នកដឹកនាំថ្មីពីអ្នកចូលរួម", + "salesforce_create_new_contact_under_account": "បង្កើតទំនាក់ទំនងថ្មីក្រោមគណនីដោយផ្អែកលើដែនអ៊ីមែលរបស់អ្នកចូលរួម និងទំនាក់ទំនងដែលមានស្រាប់", "mass_assign_attributes": "ផ្ដល់គុណលក្ខណៈជាសាធារណៈ", + "salesforce_book_directly_with_attendee_owner": "ប្រសិនបើអ្នកចូលរួមមាននៅក្នុង Salesforce សូមកក់ដោយផ្ទាល់ជាមួយម្ចាស់", + "salesforce_check_owner_of": "អង្គភាពត្រូវពិនិត្យម្ចាស់ដើម្បីកក់ដោយផ្ទាល់", + "account": "គណនី", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ បន្ថែមខ្សែអក្សរថ្មីរបស់អ្នកនៅខាងលើនេះ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/ko/common.json b/apps/web/public/static/locales/ko/common.json index 26196acb64dbd0..a4bf26d8c8a95d 100644 --- a/apps/web/public/static/locales/ko/common.json +++ b/apps/web/public/static/locales/ko/common.json @@ -1227,6 +1227,8 @@ "number_provided": "전화 번호는 제공됩니다", "before_event_trigger": "이벤트 시작 전", "event_cancelled_trigger": "이벤트 취소 시", + "after_hosts_cal_video_no_show": "호스트가 Cal 비디오에 참여하지 않은 후", + "after_guests_cal_video_no_show": "게스트가 Cal 비디오에 참여하지 않은 후", "new_event_trigger": "새 이벤트 예약 시", "email_host_action": "호스트에게 이메일 발송", "email_attendee_action": "참석자들에게 이메일 전송", @@ -1643,6 +1645,9 @@ "email_address_action": "특정 이메일 주소로 이메일 발송", "after_event_trigger": "이벤트 종료 후", "how_long_after": "이벤트 종료 후 얼마나 경과해야 합니까?", + "how_long_after_hosts_no_show": "호스트가 Cal 비디오 회의에 나타나지 않은 후 얼마나 시간이 지나야 하나요?", + "how_long_after_guests_no_show": "게스트가 Cal 비디오 회의에 나타나지 않은 후 얼마나 시간이 지나야 하나요?", + "how_long_after_user_no_show_minutes": "사용자가 Cal 비디오 회의에 나타나지 않은 후 얼마나 시간이 지나야 하나요?", "no_available_slots": "사용 가능한 슬롯 없음", "time_available": "시간 사용 가능", "cant_find_the_right_conferencing_app_visit_our_app_store": "적절한 화상 회의 앱을 찾을 수 없나요? <1>앱 스토어를 방문하세요.", @@ -1668,6 +1673,7 @@ "billing_frequency": "청구 횟수", "monthly": "월간", "yearly": "연간", + "weekly": "주간", "checkout": "체크아웃", "your_team_disbanded_successfully": "귀하의 팀이 성공적으로 해산되었습니다", "your_org_disbanded_successfully": "귀하의 조직이 성공적으로 해산되었습니다", @@ -2602,6 +2608,7 @@ "disable_email": "이메일 비활성화", "grant_admin_api": "관리자 API 액세스 부여", "revoke_admin_api": "관리자 API 액세스 취소", + "add_calendar_label": "{{calendar}} 캘린더 추가", "apple_connect_atom_label": "Apple Calendar 연결", "apple_connect_atom_already_connected_label": "Apple Calendar 연결됨", "apple_connect_atom_loading_label": "Apple 캘린더 확인 중", @@ -2633,6 +2640,15 @@ "month_to_date": "이번 달 현재까지", "year_to_date": "올해 현재까지", "custom_range": "사용자 지정 범위", + "salesforce_create_record_as": "예약 시, 이벤트를 추가하고 새로운 참석자를 다음으로 추가합니다:", + "salesforce_lead": "리드", + "salesforce_contact_under_account": "계정 내 연락처", + "salesforce_skip_entry_creation": "{{entry}} 기록이 Salesforce에 존재하지 않으면 생성을 건너뜁니다", + "salesforce_if_account_does_not_exist": "연락처가 계정에 존재하지 않으면, 참석자로부터 새로운 리드를 생성합니다", + "salesforce_create_new_contact_under_account": "참석자의 이메일 도메인과 기존 연락처를 기반으로 계정 내에 새로운 연락처를 생성합니다", "mass_assign_attributes": "속성 일괄 할당", + "salesforce_book_directly_with_attendee_owner": "참석자가 Salesforce에 존재하면, 소유자와 직접 예약합니다", + "salesforce_check_owner_of": "직접 예약하기 위해 소유자를 확인할 엔터티", + "account": "계정", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ 여기에 새 문자열을 추가하세요 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/nl/common.json b/apps/web/public/static/locales/nl/common.json index 562b7db50cceee..06b933fa05c847 100644 --- a/apps/web/public/static/locales/nl/common.json +++ b/apps/web/public/static/locales/nl/common.json @@ -1227,6 +1227,8 @@ "number_provided": "Telefoonnummer wordt verstrekt", "before_event_trigger": "voordat de gebeurtenis begint", "event_cancelled_trigger": "wanneer de gebeurtenis is geannuleerd", + "after_hosts_cal_video_no_show": "Nadat hosts niet deelnemen aan cal video", + "after_guests_cal_video_no_show": "Nadat gasten niet deelnemen aan cal video", "new_event_trigger": "wanneer een nieuwe gebeurtenis is geboekt", "email_host_action": "e-mail naar organisator versturen", "email_attendee_action": "e-mail naar deelnemers versturen", @@ -1643,6 +1645,9 @@ "email_address_action": "e-mail versturen naar een specifiek e-mailadres", "after_event_trigger": "na afloop van gebeurtenis", "how_long_after": "Hoelang na afloop van de gebeurtenis?", + "how_long_after_hosts_no_show": "Hoe lang nadat hosts niet verschijnen bij een cal videovergadering?", + "how_long_after_guests_no_show": "Hoe lang nadat gasten niet verschijnen bij een cal videovergadering?", + "how_long_after_user_no_show_minutes": "Hoe lang nadat gebruikers niet verschijnen bij een cal videovergadering?", "no_available_slots": "Geen beschikbare tijdvakken", "time_available": "Tijd beschikbaar", "cant_find_the_right_conferencing_app_visit_our_app_store": "Kun je de juiste conferentie-app niet vinden? Bezoek onze <1>App Store.", @@ -1668,6 +1673,7 @@ "billing_frequency": "Factureringsfrequentie", "monthly": "Maandelijks", "yearly": "Jaarlijks", + "weekly": "Wekelijks", "checkout": "Kassa", "your_team_disbanded_successfully": "Uw team is ontbonden", "your_org_disbanded_successfully": "Uw organisatie is ontbonden", @@ -2602,6 +2608,7 @@ "disable_email": "E-mail uitschakelen", "grant_admin_api": "Geef Admin API-toegang", "revoke_admin_api": "Admin API-toegang intrekken", + "add_calendar_label": "Voeg {{calendar}} kalender toe", "apple_connect_atom_label": "Apple Agenda verbinden", "apple_connect_atom_already_connected_label": "Verbonden Apple Agenda", "apple_connect_atom_loading_label": "Apple Agenda controleren", @@ -2633,6 +2640,15 @@ "month_to_date": "maand tot nu toe", "year_to_date": "jaar tot nu toe", "custom_range": "aangepast bereik", + "salesforce_create_record_as": "Bij boeking, voeg evenementen toe en nieuwe deelnemers als:", + "salesforce_lead": "Lead", + "salesforce_contact_under_account": "Contact onder een account", + "salesforce_skip_entry_creation": "Sla het aanmaken van {{entry}} record over als deze niet in Salesforce bestaat", + "salesforce_if_account_does_not_exist": "Als de contactpersoon niet onder een account bestaat, maak een nieuwe lead van de deelnemer", + "salesforce_create_new_contact_under_account": "Maak een nieuw contact onder een account op basis van het e-maildomein van de deelnemer en bestaande contacten", "mass_assign_attributes": "Attribuuttoewijzing in bulk", + "salesforce_book_directly_with_attendee_owner": "Als de deelnemer in Salesforce bestaat, boek direct met de eigenaar", + "salesforce_check_owner_of": "Entiteit om eigenaar van te controleren voor directe boeking", + "account": "Account", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Voeg uw nieuwe strings hierboven toe ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/no/common.json b/apps/web/public/static/locales/no/common.json index be4eba6bae03e7..368e793b738dee 100644 --- a/apps/web/public/static/locales/no/common.json +++ b/apps/web/public/static/locales/no/common.json @@ -1227,6 +1227,8 @@ "number_provided": "Telefonnummer vil bli oppgitt", "before_event_trigger": "før hendelsen starter", "event_cancelled_trigger": "når arrangementet er avlyst", + "after_hosts_cal_video_no_show": "Etter at verter ikke blir med på cal video", + "after_guests_cal_video_no_show": "Etter at gjester ikke blir med på cal video", "new_event_trigger": "når en ny hendelse er booket", "email_host_action": "send e-post til vert", "email_attendee_action": "send e-post til deltakere", @@ -1643,6 +1645,9 @@ "email_address_action": "sende e-post til en bestemt e-postadresse", "after_event_trigger": "etter at hendelsen er ferdig", "how_long_after": "Hvor lenge etter at hendelsen er ferdig?", + "how_long_after_hosts_no_show": "Hvor lenge etter at verter ikke dukker opp på cal videomøte?", + "how_long_after_guests_no_show": "Hvor lenge etter at gjester ikke dukker opp på cal videomøte?", + "how_long_after_user_no_show_minutes": "Hvor lenge etter at brukerne ikke dukker opp på cal videomøte?", "no_available_slots": "Ingen Tilgjengelige tidsluker", "time_available": "Tilgjengelig tid", "cant_find_the_right_conferencing_app_visit_our_app_store": "Kan du ikke finne riktig konferanseapp? Besøk vår <1>App Store.", @@ -1668,6 +1673,7 @@ "billing_frequency": "Betalingsfrekvens", "monthly": "Månedlig", "yearly": "Årlig", + "weekly": "Ukentlig", "checkout": "Betaling", "your_team_disbanded_successfully": "Teamet ditt har blitt oppløst", "your_org_disbanded_successfully": "Organisasjonen din har blitt oppløst", @@ -2602,6 +2608,7 @@ "disable_email": "Deaktiver e-post", "grant_admin_api": "Gi Admin API-tilgang", "revoke_admin_api": "Trekk tilbake Admin API-tilgang", + "add_calendar_label": "Legg til {{calendar}}-kalender", "apple_connect_atom_label": "Koble til Apple Calendar", "apple_connect_atom_already_connected_label": "Tilkoblet Apple-kalender", "apple_connect_atom_loading_label": "Sjekker Apple-kalender", @@ -2633,6 +2640,15 @@ "month_to_date": "måned til dags dato", "year_to_date": "år til dags dato", "custom_range": "tilpasset periode", + "salesforce_create_record_as": "Ved booking, legg til hendelser og nye deltakere som:", + "salesforce_lead": "Lead", + "salesforce_contact_under_account": "Kontakt under en konto", + "salesforce_skip_entry_creation": "Hopp over å opprette {{entry}}-post hvis de ikke finnes i Salesforce", + "salesforce_if_account_does_not_exist": "Hvis kontakten ikke finnes under en konto, opprett ny lead fra deltaker", + "salesforce_create_new_contact_under_account": "Opprett en ny kontakt under en konto basert på e-postdomenet til deltaker og eksisterende kontakter", "mass_assign_attributes": "Masseopptildel attributter", + "salesforce_book_directly_with_attendee_owner": "Hvis deltaker finnes i Salesforce, book direkte med eieren", + "salesforce_check_owner_of": "Enhet for å sjekke eier av for å booke direkte", + "account": "Konto", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Legg til dine nye strenger over her ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/pl/common.json b/apps/web/public/static/locales/pl/common.json index 9be056c103fac9..3471684c2fea1e 100644 --- a/apps/web/public/static/locales/pl/common.json +++ b/apps/web/public/static/locales/pl/common.json @@ -1227,6 +1227,8 @@ "number_provided": "Numer telefonu zostanie podany.", "before_event_trigger": "przed rozpoczęciem wydarzenia", "event_cancelled_trigger": "gdy wydarzenie zostanie anulowane", + "after_hosts_cal_video_no_show": "Po tym, jak gospodarze nie dołączą do wideo na Cal", + "after_guests_cal_video_no_show": "Po tym, jak goście nie dołączą do wideo na Cal", "new_event_trigger": "gdy nowe wydarzenie zostanie zarezerwowane", "email_host_action": "wyślij wiadomość e-mail do hosta", "email_attendee_action": "wyślij wiadomość e-mail do uczestników", @@ -1643,6 +1645,9 @@ "email_address_action": "wyślij wiadomość e-mail na określony adres e-mail", "after_event_trigger": "po zakończeniu wydarzenia", "how_long_after": "Jak długo po zakończeniu wydarzenia?", + "how_long_after_hosts_no_show": "Jak długo po tym, jak gospodarze nie pojawią się na spotkaniu wideo na Cal?", + "how_long_after_guests_no_show": "Jak długo po tym, jak goście nie pojawią się na spotkaniu wideo na Cal?", + "how_long_after_user_no_show_minutes": "Jak długo po tym, jak użytkownicy nie pojawią się na spotkaniu wideo na Cal?", "no_available_slots": "Brak dostępnych przedziałów", "time_available": "Dostępny czas", "cant_find_the_right_conferencing_app_visit_our_app_store": "Nie możesz znaleźć odpowiedniej aplikacji do wideokonferencji? Odwiedź nasz <1>Sklep z Aplikacjami.", @@ -1668,6 +1673,7 @@ "billing_frequency": "Częstotliwość rozliczania", "monthly": "Co miesiąc", "yearly": "Co rok", + "weekly": "Tygodniowo", "checkout": "Do kasy", "your_team_disbanded_successfully": "Twój zespół został rozwiązany.", "your_org_disbanded_successfully": "Twoja organizacja została rozwiązana.", @@ -2602,6 +2608,7 @@ "disable_email": "Wyłącz e-mail", "grant_admin_api": "Przyznaj dostęp do Admin API", "revoke_admin_api": "Cofnij dostęp do Admin API", + "add_calendar_label": "Dodaj kalendarz {{calendar}}", "apple_connect_atom_label": "Połącz z Kalendarzem Apple", "apple_connect_atom_already_connected_label": "Połączono z Kalendarzem Apple", "apple_connect_atom_loading_label": "Sprawdzanie Kalendarza Apple", @@ -2633,6 +2640,15 @@ "month_to_date": "od początku miesiąca", "year_to_date": "od początku roku", "custom_range": "zakres niestandardowy", + "salesforce_create_record_as": "Podczas rezerwacji dodaj wydarzenia i nowych uczestników jako:", + "salesforce_lead": "Lead", + "salesforce_contact_under_account": "Kontakt w ramach konta", + "salesforce_skip_entry_creation": "Pomiń tworzenie rekordu {{entry}}, jeśli nie istnieje w Salesforce", + "salesforce_if_account_does_not_exist": "Jeśli kontakt nie istnieje w ramach konta, utwórz nowy lead z uczestnika", + "salesforce_create_new_contact_under_account": "Utwórz nowy kontakt w ramach konta na podstawie domeny e-mail uczestnika i istniejących kontaktów", "mass_assign_attributes": "Masowe przypisywanie atrybutów", + "salesforce_book_directly_with_attendee_owner": "Jeśli uczestnik istnieje w Salesforce, zarezerwuj bezpośrednio z właścicielem", + "salesforce_check_owner_of": "Podmiot do sprawdzenia właściciela w celu bezpośredniej rezerwacji", + "account": "Konto", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Dodaj nowe ciągi powyżej ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/pt-BR/common.json b/apps/web/public/static/locales/pt-BR/common.json index e9c2cfb078d26e..e4f102e62f8721 100644 --- a/apps/web/public/static/locales/pt-BR/common.json +++ b/apps/web/public/static/locales/pt-BR/common.json @@ -1227,6 +1227,8 @@ "number_provided": "O número de telefone será fornecido", "before_event_trigger": "antes do início do evento", "event_cancelled_trigger": "quando o evento for cancelado", + "after_hosts_cal_video_no_show": "Após os anfitriões não entrarem no vídeo do Cal", + "after_guests_cal_video_no_show": "Após os convidados não entrarem no vídeo do Cal", "new_event_trigger": "quando um novo evento for reservado", "email_host_action": "enviar e-mail para a(o) anfitriã(o)", "email_attendee_action": "enviar e-mail aos participantes", @@ -1643,6 +1645,9 @@ "email_address_action": "enviar e-mail para um endereço de e-mail específico", "after_event_trigger": "após o término do evento", "how_long_after": "Quanto tempo após o término do evento?", + "how_long_after_hosts_no_show": "Quanto tempo após os anfitriões não aparecerem na reunião de vídeo do Cal?", + "how_long_after_guests_no_show": "Quanto tempo após os convidados não aparecerem na reunião de vídeo do Cal?", + "how_long_after_user_no_show_minutes": "Quanto tempo após os usuários não aparecerem na reunião de vídeo do Cal?", "no_available_slots": "Não há espaços disponíveis", "time_available": "Tempo disponível", "cant_find_the_right_conferencing_app_visit_our_app_store": "Não consegue encontrar o aplicativo de conferência certo? Visite nossa <1>App Store.", @@ -1668,6 +1673,7 @@ "billing_frequency": "Frequência de cobrança", "monthly": "Mensal", "yearly": "Anual", + "weekly": "Semanal", "checkout": "Finalizar compra", "your_team_disbanded_successfully": "Sua equipe foi desfeita com êxito", "your_org_disbanded_successfully": "Sua organização foi desfeita com êxito", @@ -2602,6 +2608,7 @@ "disable_email": "Desativar e-mail", "grant_admin_api": "Conceder acesso à API de administrador", "revoke_admin_api": "Revogar acesso à API de administrador", + "add_calendar_label": "Adicionar calendário {{calendar}}", "apple_connect_atom_label": "Conectar Calendário Apple", "apple_connect_atom_already_connected_label": "Calendário Apple conectado", "apple_connect_atom_loading_label": "Verificando Calendário Apple", @@ -2633,6 +2640,15 @@ "month_to_date": "mês até a data", "year_to_date": "ano até a data", "custom_range": "intervalo personalizado", + "salesforce_create_record_as": "Ao agendar, adicione eventos e novos participantes como:", + "salesforce_lead": "Lead", + "salesforce_contact_under_account": "Contato em uma conta", + "salesforce_skip_entry_creation": "Pular a criação do registro de {{entry}} se não existir no Salesforce", + "salesforce_if_account_does_not_exist": "Se o contato não existir em uma conta, criar novo lead a partir do participante", + "salesforce_create_new_contact_under_account": "Criar um novo contato em uma conta com base no domínio de e-mail do participante e contatos existentes", "mass_assign_attributes": "Atribuir atributos em massa", + "salesforce_book_directly_with_attendee_owner": "Se o participante existir no Salesforce, agendar diretamente com o proprietário", + "salesforce_check_owner_of": "Entidade para verificar o proprietário para agendar diretamente", + "account": "Conta", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Adicione suas novas strings aqui em cima ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/pt/common.json b/apps/web/public/static/locales/pt/common.json index 8599f329100c0d..5d5e7411323c56 100644 --- a/apps/web/public/static/locales/pt/common.json +++ b/apps/web/public/static/locales/pt/common.json @@ -1227,6 +1227,8 @@ "number_provided": "Será fornecido um número de telefone", "before_event_trigger": "antes do evento iniciar", "event_cancelled_trigger": "quando o evento for cancelado", + "after_hosts_cal_video_no_show": "Após os anfitriões não se juntarem ao vídeo do Cal", + "after_guests_cal_video_no_show": "Após os convidados não se juntarem ao vídeo do Cal", "new_event_trigger": "quando um novo evento for reservado", "email_host_action": "enviar email ao anfitrião", "email_attendee_action": "enviar e-mail aos participantes", @@ -1643,6 +1645,9 @@ "email_address_action": "enviar e-mail para um endereço de e-mail específico", "after_event_trigger": "depois do fim do evento", "how_long_after": "Quanto tempo após o fim do evento?", + "how_long_after_hosts_no_show": "Quanto tempo após os anfitriões não aparecerem na reunião de vídeo do Cal?", + "how_long_after_guests_no_show": "Quanto tempo após os convidados não aparecerem na reunião de vídeo do Cal?", + "how_long_after_user_no_show_minutes": "Quanto tempo após os utilizadores não aparecerem na reunião de vídeo do Cal?", "no_available_slots": "Sem vagas disponíveis", "time_available": "Tempo disponível", "cant_find_the_right_conferencing_app_visit_our_app_store": "Não consegue encontrar a aplicação de conferência certa? Visite a nossa <1>App Store.", @@ -1668,6 +1673,7 @@ "billing_frequency": "Frequência da faturação", "monthly": "Mensal", "yearly": "Anual", + "weekly": "Semanal", "checkout": "Finalização da compra", "your_team_disbanded_successfully": "A sua equipa foi dissolvida com sucesso", "your_org_disbanded_successfully": "A sua organização foi dissolvida com sucesso", @@ -2602,6 +2608,7 @@ "disable_email": "Desativar email", "grant_admin_api": "Conceder acesso à API de administrador", "revoke_admin_api": "Revogar acesso à API de administrador", + "add_calendar_label": "Adicionar Calendário {{calendar}}", "apple_connect_atom_label": "Conectar Calendário Apple", "apple_connect_atom_already_connected_label": "Calendário Apple Conectado", "apple_connect_atom_loading_label": "Verificando Calendário Apple", @@ -2633,6 +2640,15 @@ "month_to_date": "mês até à data", "year_to_date": "ano até à data", "custom_range": "intervalo personalizado", + "salesforce_create_record_as": "Ao agendar, adicionar eventos em e novos participantes como:", + "salesforce_lead": "Lead", + "salesforce_contact_under_account": "Contacto sob uma conta", + "salesforce_skip_entry_creation": "Ignorar a criação do registo de {{entry}} se não existir no Salesforce", + "salesforce_if_account_does_not_exist": "Se o contacto não existir sob uma conta, criar um novo lead a partir do participante", + "salesforce_create_new_contact_under_account": "Criar um novo contacto sob uma conta com base no domínio de email do participante e contactos existentes", "mass_assign_attributes": "Atribuir atributos em massa", + "salesforce_book_directly_with_attendee_owner": "Se o participante existir no Salesforce, agendar diretamente com o proprietário", + "salesforce_check_owner_of": "Entidade para verificar o proprietário para agendar diretamente", + "account": "Conta", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/ro/common.json b/apps/web/public/static/locales/ro/common.json index 38a384f8e26d46..2a56385fa5a012 100644 --- a/apps/web/public/static/locales/ro/common.json +++ b/apps/web/public/static/locales/ro/common.json @@ -1227,6 +1227,8 @@ "number_provided": "Numărul de telefon va fi furnizat", "before_event_trigger": "înainte de începerea evenimentului", "event_cancelled_trigger": "la anularea evenimentului", + "after_hosts_cal_video_no_show": "După ce gazdele nu se alătură la cal video", + "after_guests_cal_video_no_show": "După ce invitații nu se alătură la cal video", "new_event_trigger": "când este rezervat noul eveniment", "email_host_action": "trimiteți e-mail la gazdă", "email_attendee_action": "trimiteți e-mail participanților", @@ -1643,6 +1645,9 @@ "email_address_action": "trimiteți e-mail către o anumită adresă de e-mail", "after_event_trigger": "după finalul evenimentului", "how_long_after": "La cât timp după finalul evenimentului?", + "how_long_after_hosts_no_show": "Cât timp după ce gazdele nu apar la întâlnirea video cal?", + "how_long_after_guests_no_show": "Cât timp după ce invitații nu apar la întâlnirea video cal?", + "how_long_after_user_no_show_minutes": "Cât timp după ce utilizatorii nu apar la întâlnirea video cal?", "no_available_slots": "Niciun interval disponibil", "time_available": "Oră disponibilă", "cant_find_the_right_conferencing_app_visit_our_app_store": "Nu găsești aplicația de conferință potrivită? Vizitează <1>App Store-ul nostru.", @@ -1668,6 +1673,7 @@ "billing_frequency": "Frecvența de facturare", "monthly": "Lunar", "yearly": "Anual", + "weekly": "Săptămânal", "checkout": "Finalizare cumpărături", "your_team_disbanded_successfully": "Echipa dvs. a fost desființată cu succes", "your_org_disbanded_successfully": "Organizația dvs. a fost desființată cu succes", @@ -2602,6 +2608,7 @@ "disable_email": "Dezactivați e-mailul", "grant_admin_api": "Acordați acces API de administrator", "revoke_admin_api": "Revocați accesul API de administrator", + "add_calendar_label": "Adaugă calendarul {{calendar}}", "apple_connect_atom_label": "Conectați Calendarul Apple", "apple_connect_atom_already_connected_label": "Calendarul Apple conectat", "apple_connect_atom_loading_label": "Verificare Calendar Apple", @@ -2633,6 +2640,15 @@ "month_to_date": "luna până în prezent", "year_to_date": "anul până în prezent", "custom_range": "interval personalizat", + "salesforce_create_record_as": "La rezervare, adaugă evenimentele și noii participanți ca:", + "salesforce_lead": "Lead", + "salesforce_contact_under_account": "Contact sub un cont", + "salesforce_skip_entry_creation": "Sari peste crearea înregistrării {{entry}} dacă nu există în Salesforce", + "salesforce_if_account_does_not_exist": "Dacă contactul nu există sub un cont, creează un lead nou din participant", + "salesforce_create_new_contact_under_account": "Creează un contact nou sub un cont pe baza domeniului de email al participantului și a contactelor existente", "mass_assign_attributes": "Atribuire în masă a atributelor", + "salesforce_book_directly_with_attendee_owner": "Dacă participantul există în Salesforce, rezervă direct cu proprietarul", + "salesforce_check_owner_of": "Entitatea pentru a verifica proprietarul pentru a rezerva direct", + "account": "Cont", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Adăugați stringurile noi deasupra acestui rând ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/sr/common.json b/apps/web/public/static/locales/sr/common.json index 429927ccc8dea1..9414ef8e3586c0 100644 --- a/apps/web/public/static/locales/sr/common.json +++ b/apps/web/public/static/locales/sr/common.json @@ -1227,6 +1227,8 @@ "number_provided": "Broj telefona će biti dostavljen", "before_event_trigger": "pre početka događaja", "event_cancelled_trigger": "kada je događaj otkazan", + "after_hosts_cal_video_no_show": "Nakon što se domaćini ne pojave na Cal video sastanku", + "after_guests_cal_video_no_show": "Nakon što se gosti ne pojave na Cal video sastanku", "new_event_trigger": "kada je zakazan novi događaj", "email_host_action": "pošalji imejl domaćinu", "email_attendee_action": "pošalji imejl učesnicima", @@ -1643,6 +1645,9 @@ "email_address_action": "pošalji imejl na određene imejl adrese", "after_event_trigger": "nakon što se događaj završi", "how_long_after": "Koliko vremena nakon što se događaj završi?", + "how_long_after_hosts_no_show": "Koliko dugo nakon što se domaćini ne pojave na Cal video sastanku?", + "how_long_after_guests_no_show": "Koliko dugo nakon što se gosti ne pojave na Cal video sastanku?", + "how_long_after_user_no_show_minutes": "Koliko minuta nakon što se korisnici ne pojave na Cal video sastanku?", "no_available_slots": "Nema dostupnih termina", "time_available": "Dostupno vreme", "cant_find_the_right_conferencing_app_visit_our_app_store": "Ne možete pronaći odgovarajuću aplikaciju za konferencije? Posetite naš <1>App Store.", @@ -1668,6 +1673,7 @@ "billing_frequency": "Učestalost naplate", "monthly": "Mesečno", "yearly": "Godišnje", + "weekly": "Недељно", "checkout": "Kasa", "your_team_disbanded_successfully": "Vaš tim je uspešno rasformiran", "your_org_disbanded_successfully": "Vaša organizacija je uspešno rasformirana", @@ -2602,6 +2608,7 @@ "disable_email": "Onemogući email", "grant_admin_api": "Dodeli Admin API pristup", "revoke_admin_api": "Opozovi Admin API pristup", + "add_calendar_label": "Додај {{calendar}} календар", "apple_connect_atom_label": "Poveži Apple Calendar", "apple_connect_atom_already_connected_label": "Povezan Apple Calendar", "apple_connect_atom_loading_label": "Provera Apple kalendara", @@ -2633,6 +2640,15 @@ "month_to_date": "od početka meseca do danas", "year_to_date": "od početka godine do danas", "custom_range": "prilagođeni opseg", + "salesforce_create_record_as": "Prilikom zakazivanja, dodaj događaje i nove učesnike kao:", + "salesforce_lead": "Potencijalni klijent", + "salesforce_contact_under_account": "Kontakt pod nalogom", + "salesforce_skip_entry_creation": "Preskoči kreiranje {{entry}} zapisa ako ne postoje u Salesforce-u", + "salesforce_if_account_does_not_exist": "Ako kontakt ne postoji pod nalogom, kreiraj novog potencijalnog klijenta od učesnika", + "salesforce_create_new_contact_under_account": "Kreiraj novi kontakt pod nalogom na osnovu email domena učesnika i postojećih kontakata", "mass_assign_attributes": "Masovno dodeljivanje atributa", + "salesforce_book_directly_with_attendee_owner": "Ako učesnik postoji u Salesforce-u, zakaži direktno sa vlasnikom", + "salesforce_check_owner_of": "Entitet čijeg vlasnika treba proveriti za direktno zakazivanje", + "account": "Nalog", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Dodajte svoje nove stringove iznad ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/sv/common.json b/apps/web/public/static/locales/sv/common.json index d718af853b4653..485b24266c1fd0 100644 --- a/apps/web/public/static/locales/sv/common.json +++ b/apps/web/public/static/locales/sv/common.json @@ -1227,6 +1227,8 @@ "number_provided": "Telefonnummer kommer att anges", "before_event_trigger": "innan händelsen startar", "event_cancelled_trigger": "när händelsen ställs in", + "after_hosts_cal_video_no_show": "Efter att värdarna inte ansluter till cal video", + "after_guests_cal_video_no_show": "Efter att gästerna inte ansluter till cal video", "new_event_trigger": "när ny händelse bokas", "email_host_action": "skicka e-post till värd", "email_attendee_action": "skicka e-post till deltagare", @@ -1643,6 +1645,9 @@ "email_address_action": "skicka e-post till en specifik e-postadress", "after_event_trigger": "efter händelsens slut", "how_long_after": "Hur länge efter händelsens slut?", + "how_long_after_hosts_no_show": "Hur länge efter att värdarna inte dyker upp på cal video-mötet?", + "how_long_after_guests_no_show": "Hur länge efter att gästerna inte dyker upp på cal video-mötet?", + "how_long_after_user_no_show_minutes": "Hur länge efter att användarna inte dyker upp på cal video-mötet?", "no_available_slots": "Inga tillgängliga tider", "time_available": "Tid tillgänglig", "cant_find_the_right_conferencing_app_visit_our_app_store": "Kan du inte hitta rätt konferensapp? Besök vår <1>App Store.", @@ -1668,6 +1673,7 @@ "billing_frequency": "Faktureringsfrekvens", "monthly": "Månadsvis", "yearly": "Årligen", + "weekly": "Veckovis", "checkout": "Kassa", "your_team_disbanded_successfully": "Ditt team har upplösts", "your_org_disbanded_successfully": "Din organisation är upplöst", @@ -2602,6 +2608,7 @@ "disable_email": "Inaktivera mejl", "grant_admin_api": "Ge administratörs-API-åtkomst", "revoke_admin_api": "Återkalla administratörs-API-åtkomst", + "add_calendar_label": "Lägg till {{calendar}} kalender", "apple_connect_atom_label": "Anslut Apple Calendar", "apple_connect_atom_already_connected_label": "Apple Calendar ansluten", "apple_connect_atom_loading_label": "Kontrollerar Apple Kalender", @@ -2633,6 +2640,15 @@ "month_to_date": "månad till datum", "year_to_date": "år till datum", "custom_range": "anpassat intervall", + "salesforce_create_record_as": "Vid bokning, lägg till händelser och nya deltagare som:", + "salesforce_lead": "Lead", + "salesforce_contact_under_account": "Kontakt under ett konto", + "salesforce_skip_entry_creation": "Hoppa över att skapa {{entry}}-post om den inte finns i Salesforce", + "salesforce_if_account_does_not_exist": "Om kontakten inte finns under ett konto, skapa en ny lead från deltagaren", + "salesforce_create_new_contact_under_account": "Skapa en ny kontakt under ett konto baserat på deltagarens e-postdomän och befintliga kontakter", "mass_assign_attributes": "Massuppdatera attribut", + "salesforce_book_directly_with_attendee_owner": "Om deltagaren finns i Salesforce, boka direkt med ägaren", + "salesforce_check_owner_of": "Entitet att kontrollera ägare av för att boka direkt", + "account": "Konto", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/tr/common.json b/apps/web/public/static/locales/tr/common.json index 439ea124a917a9..b1ce2314516e0d 100644 --- a/apps/web/public/static/locales/tr/common.json +++ b/apps/web/public/static/locales/tr/common.json @@ -1227,6 +1227,8 @@ "number_provided": "Telefon numarası sağlanacaktır", "before_event_trigger": "etkinlik başlamadan önce", "event_cancelled_trigger": "etkinlik iptal edildiğinde", + "after_hosts_cal_video_no_show": "Ev sahipleri Cal video toplantısına katılmadığında", + "after_guests_cal_video_no_show": "Misafirler Cal video toplantısına katılmadığında", "new_event_trigger": "yeni bir etkinlik için rezervasyon yapıldığında", "email_host_action": "organizatöre e-posta gönder", "email_attendee_action": "katılımcılara e-posta gönder", @@ -1643,6 +1645,9 @@ "email_address_action": "belirli bir e-posta adresine e-posta gönder", "after_event_trigger": "etkinlik sona erdikten sonra", "how_long_after": "Etkinlik sona erdikten ne kadar sonra?", + "how_long_after_hosts_no_show": "Ev sahipleri Cal video toplantısına katılmadığında ne kadar süre sonra?", + "how_long_after_guests_no_show": "Misafirler Cal video toplantısına katılmadığında ne kadar süre sonra?", + "how_long_after_user_no_show_minutes": "Kullanıcılar Cal video toplantısına katılmadığında kaç dakika sonra?", "no_available_slots": "Uygun yer yok", "time_available": "Uygun zaman", "cant_find_the_right_conferencing_app_visit_our_app_store": "Doğru konferans uygulamasını bulamıyor musunuz? <1>Uygulama Mağazamızı ziyaret edin.", @@ -1668,6 +1673,7 @@ "billing_frequency": "Faturalandırma Sıklığı", "monthly": "Aylık", "yearly": "Yıllık", + "weekly": "Haftalık", "checkout": "Ödeme yap", "your_team_disbanded_successfully": "Ekibiniz başarıyla dağıtıldı", "your_org_disbanded_successfully": "Kuruluşunuz başarıyla dağıtıldı", @@ -2602,6 +2608,7 @@ "disable_email": "E-postayı devre dışı bırak", "grant_admin_api": "Yönetici API Erişimi Ver", "revoke_admin_api": "Yönetici API Erişimini Kaldır", + "add_calendar_label": "{{calendar}} Takvimini Ekle", "apple_connect_atom_label": "Apple Takvimini Bağla", "apple_connect_atom_already_connected_label": "Bağlı Apple Takvimi", "apple_connect_atom_loading_label": "Apple Takvimi Kontrol Ediliyor", @@ -2633,6 +2640,15 @@ "month_to_date": "ayın başından bugüne", "year_to_date": "yılın başından bugüne", "custom_range": "özel aralık", + "salesforce_create_record_as": "Rezervasyon sırasında, etkinlikleri ekleyin ve yeni katılımcıları şu şekilde ekleyin:", + "salesforce_lead": "Potansiyel Müşteri", + "salesforce_contact_under_account": "Bir hesap altında İletişim", + "salesforce_skip_entry_creation": "{{entry}} kaydı Salesforce'ta yoksa oluşturmayı atla", + "salesforce_if_account_does_not_exist": "İletişim bir hesap altında yoksa, katılımcıdan yeni potansiyel müşteri oluştur", + "salesforce_create_new_contact_under_account": "Katılımcının e-posta alanı ve mevcut iletişimler temelinde bir hesap altında yeni bir iletişim oluştur", "mass_assign_attributes": "Özellikleri toplu olarak atama", + "salesforce_book_directly_with_attendee_owner": "Katılımcı Salesforce'ta mevcutsa, doğrudan sahibiyle rezervasyon yap", + "salesforce_check_owner_of": "Doğrudan rezervasyon yapmak için sahibini kontrol edilecek varlık", + "account": "Hesap", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Yeni dizelerinizi yukarıya ekleyin ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/uk/common.json b/apps/web/public/static/locales/uk/common.json index b63a0edee4c1f3..ba7e9ba465e62f 100644 --- a/apps/web/public/static/locales/uk/common.json +++ b/apps/web/public/static/locales/uk/common.json @@ -1227,6 +1227,8 @@ "number_provided": "Номер телефону буде надано", "before_event_trigger": "до початку заходу", "event_cancelled_trigger": "у момент скасування заходу", + "after_hosts_cal_video_no_show": "Після того, як господарі не приєдналися до відеозустрічі на Cal", + "after_guests_cal_video_no_show": "Після того, як гості не приєдналися до відеозустрічі на Cal", "new_event_trigger": "у момент бронювання нового заходу", "email_host_action": "надсилати електронний лист ведучому", "email_attendee_action": "надіслати ел. лист учасникам", @@ -1643,6 +1645,9 @@ "email_address_action": "надсилати електронний лист на вказану адресу", "after_event_trigger": "після завершення заходу", "how_long_after": "Через який час після завершення заходу?", + "how_long_after_hosts_no_show": "Скільки часу після того, як господарі не з'явилися на відеозустрічі на Cal?", + "how_long_after_guests_no_show": "Скільки часу після того, як гості не з'явилися на відеозустрічі на Cal?", + "how_long_after_user_no_show_minutes": "Скільки часу після того, як користувачі не з'явилися на відеозустрічі на Cal?", "no_available_slots": "Немає доступних вікон", "time_available": "Доступний час", "cant_find_the_right_conferencing_app_visit_our_app_store": "Не можете знайти потрібний додаток для конференцій? Відвідайте наш <1>App Store.", @@ -1668,6 +1673,7 @@ "billing_frequency": "Періодичність виставлення рахунків", "monthly": "Щомісяця", "yearly": "Щороку", + "weekly": "Щотижнево", "checkout": "Оплата", "your_team_disbanded_successfully": "Вашу команду розформовано", "your_org_disbanded_successfully": "Вашу організацію розформовано", @@ -2602,6 +2608,7 @@ "disable_email": "Вимкнути електронну пошту", "grant_admin_api": "Надати доступ до Admin API", "revoke_admin_api": "Відкликати доступ до Admin API", + "add_calendar_label": "Додати календар {{calendar}}", "apple_connect_atom_label": "Підключити Apple Calendar", "apple_connect_atom_already_connected_label": "Apple Calendar підключено", "apple_connect_atom_loading_label": "Перевірка календаря Apple", @@ -2633,6 +2640,15 @@ "month_to_date": "з початку місяця", "year_to_date": "з початку року", "custom_range": "власний діапазон", + "salesforce_create_record_as": "Під час бронювання додати події та нових учасників як:", + "salesforce_lead": "Лід", + "salesforce_contact_under_account": "Контакт під обліковим записом", + "salesforce_skip_entry_creation": "Пропустити створення запису {{entry}}, якщо вони не існують у Salesforce", + "salesforce_if_account_does_not_exist": "Якщо контакт не існує під обліковим записом, створити новий лід з учасника", + "salesforce_create_new_contact_under_account": "Створити новий контакт під обліковим записом на основі домену електронної пошти учасника та існуючих контактів", "mass_assign_attributes": "Масове призначення атрибутів", + "salesforce_book_directly_with_attendee_owner": "Якщо учасник існує в Salesforce, бронювати безпосередньо з власником", + "salesforce_check_owner_of": "Сутність для перевірки власника для прямого бронювання", + "account": "Обліковий запис", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/vi/common.json b/apps/web/public/static/locales/vi/common.json index be06f32bdd6512..c7173c67118491 100644 --- a/apps/web/public/static/locales/vi/common.json +++ b/apps/web/public/static/locales/vi/common.json @@ -1227,6 +1227,8 @@ "number_provided": "Số điện thoại sẽ được cung ứng", "before_event_trigger": "trước khi sự kiện bắt đầu", "event_cancelled_trigger": "khi sự kiện bị huỷ", + "after_hosts_cal_video_no_show": "Sau khi người tổ chức không tham gia video trên Cal", + "after_guests_cal_video_no_show": "Sau khi khách mời không tham gia video trên Cal", "new_event_trigger": "khi sự kiện mới được đặt lịch hẹn", "email_host_action": "gửi email đến chủ sự kiện", "email_attendee_action": "gửi email đến người tham gia", @@ -1643,6 +1645,9 @@ "email_address_action": "gửi email đến một địa chỉ email cụ thể", "after_event_trigger": "sau khi sự kiện kết thúc", "how_long_after": "Bao lâu sau khi sự kiện kết thúc?", + "how_long_after_hosts_no_show": "Bao lâu sau khi người tổ chức không xuất hiện trong cuộc họp video trên Cal?", + "how_long_after_guests_no_show": "Bao lâu sau khi khách mời không xuất hiện trong cuộc họp video trên Cal?", + "how_long_after_user_no_show_minutes": "Bao lâu sau khi người dùng không xuất hiện trong cuộc họp video trên Cal?", "no_available_slots": "Không còn khoảng thời gian trống", "time_available": "Thời gian trống", "cant_find_the_right_conferencing_app_visit_our_app_store": "Không tìm thấy ứng dụng hội nghị phù hợp? Ghé thăm <1>App Store của chúng tôi.", @@ -1668,6 +1673,7 @@ "billing_frequency": "Tần suất thanh toán", "monthly": "Hằng tháng", "yearly": "Hằng năm", + "weekly": "Hàng tuần", "checkout": "Thanh toán", "your_team_disbanded_successfully": "Nhóm của bạn đã được giải tán thành công", "your_org_disbanded_successfully": "Tổ chức của bạn đã được giải tán thành công", @@ -2602,6 +2608,7 @@ "disable_email": "Vô hiệu hóa email", "grant_admin_api": "Cấp quyền truy cập Admin API", "revoke_admin_api": "Thu hồi quyền truy cập Admin API", + "add_calendar_label": "Thêm lịch {{calendar}}", "apple_connect_atom_label": "Kết nối Apple Calendar", "apple_connect_atom_already_connected_label": "Apple Calendar đã được kết nối", "apple_connect_atom_loading_label": "Đang kiểm tra Lịch Apple", @@ -2633,6 +2640,15 @@ "month_to_date": "từ đầu tháng đến nay", "year_to_date": "từ đầu năm đến nay", "custom_range": "phạm vi tùy chỉnh", + "salesforce_create_record_as": "Khi đặt lịch, thêm sự kiện và người tham dự mới dưới dạng:", + "salesforce_lead": "Khách hàng tiềm năng", + "salesforce_contact_under_account": "Liên hệ dưới một tài khoản", + "salesforce_skip_entry_creation": "Bỏ qua việc tạo bản ghi {{entry}} nếu chúng không tồn tại trong Salesforce", + "salesforce_if_account_does_not_exist": "Nếu liên hệ không tồn tại dưới một tài khoản, tạo khách hàng tiềm năng mới từ người tham dự", + "salesforce_create_new_contact_under_account": "Tạo liên hệ mới dưới một tài khoản dựa trên tên miền email của người tham dự và các liên hệ hiện có", "mass_assign_attributes": "Gán thuộc tính hàng loạt", + "salesforce_book_directly_with_attendee_owner": "Nếu người tham dự tồn tại trong Salesforce, đặt lịch trực tiếp với chủ sở hữu", + "salesforce_check_owner_of": "Thực thể để kiểm tra chủ sở hữu để đặt lịch trực tiếp", + "account": "Tài khoản", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/zh-CN/common.json b/apps/web/public/static/locales/zh-CN/common.json index ec94b88e306949..f69aa8df5fc11f 100644 --- a/apps/web/public/static/locales/zh-CN/common.json +++ b/apps/web/public/static/locales/zh-CN/common.json @@ -1227,6 +1227,8 @@ "number_provided": "将提供电话号码", "before_event_trigger": "活动开始前", "event_cancelled_trigger": "活动取消后", + "after_hosts_cal_video_no_show": "主持人未加入 Cal 视频后的处理", + "after_guests_cal_video_no_show": "嘉宾未加入 Cal 视频后的处理", "new_event_trigger": "预约新活动时", "email_host_action": "向主持人发送电子邮件", "email_attendee_action": "向参与者发送电子邮件", @@ -1643,6 +1645,9 @@ "email_address_action": "将电子邮件发送到指定的电子邮件地址", "after_event_trigger": "活动结束后", "how_long_after": "活动结束后多久?", + "how_long_after_hosts_no_show": "主持人未出现在 Cal 视频会议后多长时间?", + "how_long_after_guests_no_show": "嘉宾未出现在 Cal 视频会议后多长时间?", + "how_long_after_user_no_show_minutes": "用户未出现在 Cal 视频会议后多长时间?", "no_available_slots": "没有可用的时间段", "time_available": "可用时间", "cant_find_the_right_conferencing_app_visit_our_app_store": "找不到合适的会议应用?访问我们的<1>应用商店。", @@ -1668,6 +1673,7 @@ "billing_frequency": "计费频率", "monthly": "每月", "yearly": "每年", + "weekly": "每周", "checkout": "结账", "your_team_disbanded_successfully": "您的团队已成功解散", "your_org_disbanded_successfully": "您的组织已成功解散", @@ -2602,6 +2608,7 @@ "disable_email": "禁用电子邮件", "grant_admin_api": "授予管理员API访问权限", "revoke_admin_api": "撤销管理员API访问权限", + "add_calendar_label": "添加{{calendar}}日历", "apple_connect_atom_label": "连接Apple日历", "apple_connect_atom_already_connected_label": "已连接Apple日历", "apple_connect_atom_loading_label": "检查Apple日历", @@ -2633,6 +2640,15 @@ "month_to_date": "本月至今", "year_to_date": "今年至今", "custom_range": "自定义范围", + "salesforce_create_record_as": "预订时,将事件添加到,并将新参与者添加为:", + "salesforce_lead": "潜在客户", + "salesforce_contact_under_account": "账户下的联系人", + "salesforce_skip_entry_creation": "如果{{entry}}记录在Salesforce中不存在,则跳过创建", + "salesforce_if_account_does_not_exist": "如果联系人不在某个账户下,则从参与者创建新的潜在客户", + "salesforce_create_new_contact_under_account": "根据参与者的电子邮件域和现有联系人,在账户下创建新联系人", "mass_assign_attributes": "批量分配属性", + "salesforce_book_directly_with_attendee_owner": "如果参与者在Salesforce中存在,则直接与所有者预订", + "salesforce_check_owner_of": "检查实体的所有者以直接预订", + "account": "账户", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ 在此上方添加您的新字符串 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/public/static/locales/zh-TW/common.json b/apps/web/public/static/locales/zh-TW/common.json index b775f449fc7ab3..4bac22b80aac6e 100644 --- a/apps/web/public/static/locales/zh-TW/common.json +++ b/apps/web/public/static/locales/zh-TW/common.json @@ -1227,6 +1227,8 @@ "number_provided": "將提供電話號碼", "before_event_trigger": "活動開始前", "event_cancelled_trigger": "活動取消時", + "after_hosts_cal_video_no_show": "主持人未加入 Cal 視訊後", + "after_guests_cal_video_no_show": "賓客未加入 Cal 視訊後", "new_event_trigger": "預約新活動時", "email_host_action": "傳送電子郵件給主辦者", "email_attendee_action": "傳送電子郵件給與會者", @@ -1643,6 +1645,9 @@ "email_address_action": "寄電子郵件至特定的電子郵件地址", "after_event_trigger": "活動結束過後", "how_long_after": "活動結束過後多久?", + "how_long_after_hosts_no_show": "主持人未出現在 Cal 視訊會議後多久?", + "how_long_after_guests_no_show": "賓客未出現在 Cal 視訊會議後多久?", + "how_long_after_user_no_show_minutes": "用戶未出現在 Cal 視訊會議後多久?", "no_available_slots": "沒有可預約的時段", "time_available": "開放時間", "cant_find_the_right_conferencing_app_visit_our_app_store": "找不到合適的會議應用?訪問我們的 <1>應用商店。", @@ -1668,6 +1673,7 @@ "billing_frequency": "付費頻率", "monthly": "每月", "yearly": "每年", + "weekly": "每週", "checkout": "結帳", "your_team_disbanded_successfully": "已成功解散您的團隊", "your_org_disbanded_successfully": "已成功解散組織", @@ -2602,6 +2608,7 @@ "disable_email": "禁用電子郵件", "grant_admin_api": "授予管理員 API 訪問權限", "revoke_admin_api": "撤銷管理員 API 訪問權限", + "add_calendar_label": "新增{{calendar}}行事曆", "apple_connect_atom_label": "連接 Apple 日曆", "apple_connect_atom_already_connected_label": "已連接 Apple 日曆", "apple_connect_atom_loading_label": "正在檢查 Apple 日曆", @@ -2633,6 +2640,15 @@ "month_to_date": "本月至今", "year_to_date": "本年至今", "custom_range": "自訂範圍", + "salesforce_create_record_as": "預約時,將事件和新參加者新增為:", + "salesforce_lead": "潛在客戶", + "salesforce_contact_under_account": "帳戶下的聯絡人", + "salesforce_skip_entry_creation": "如果 {{entry}} 記錄不存在於 Salesforce 中,則跳過創建", + "salesforce_if_account_does_not_exist": "如果聯絡人不存在於帳戶下,則從參加者創建新的潛在客戶", + "salesforce_create_new_contact_under_account": "根據參加者的電子郵件域和現有聯絡人,在帳戶下創建新的聯絡人", "mass_assign_attributes": "批量分配屬性", + "salesforce_book_directly_with_attendee_owner": "如果參加者存在於 Salesforce 中,則直接與擁有者預約", + "salesforce_check_owner_of": "檢查實體的擁有者以直接預約", + "account": "帳戶", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ 請在此處新增您的字串 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/apps/web/test/lib/getTimezone.test.ts b/apps/web/test/lib/getTimezone.test.ts index ff2be79b4997c5..10c025aedd0192 100644 --- a/apps/web/test/lib/getTimezone.test.ts +++ b/apps/web/test/lib/getTimezone.test.ts @@ -23,6 +23,66 @@ const cityData = [ city: "San Francisco", timezone: "America/Los_Angeles", }, + { + city: "Eastern Time - US & Canada", + timezone: "America/New_York", + }, + { + city: "Pacific Time - US & Canada", + timezone: "America/Los_Angeles", + }, + { + city: "Central Time - US & Canada", + timezone: "America/Chicago", + }, + { + city: "Mountain Time - US & Canada", + timezone: "America/Denver", + }, + { + city: "Atlantic Time - Canada", + timezone: "America/Halifax", + }, + { + city: "Eastern European Time", + timezone: "Europe/Bucharest", + }, + { + city: "Central European Time", + timezone: "Europe/Berlin", + }, + { + city: "Western European Time", + timezone: "Europe/London", + }, + { + city: "Australian Eastern Time", + timezone: "Australia/Sydney", + }, + { + city: "Japan Standard Time", + timezone: "Asia/Tokyo", + }, + { + city: "India Standard Time", + timezone: "Asia/Kolkata", + }, + { + city: "Gulf Standard Time", + timezone: "Asia/Dubai", + }, + { + city: "South Africa Standard Time", + timezone: "Africa/Johannesburg", + }, + { + city: "Brazil Time", + timezone: "America/Sao_Paulo", + }, + { + city: "Hawaii-Aleutian Standard Time", + timezone: "Pacific/Honolulu", + }, ]; const option = { @@ -49,37 +109,50 @@ describe("getTimezone", () => { it("should filter cities for a valid city name", () => { expect(filterByCities("San Francisco", cityData)).toMatchInlineSnapshot(` - [ - { - "city": "San Francisco", - "timezone": "America/Argentina/Cordoba", - }, - { - "city": "San Francisco de Macoris", - "timezone": "America/Santo_Domingo", - }, - { - "city": "San Francisco Gotera", - "timezone": "America/El_Salvador", - }, - { - "city": "San Francisco", - "timezone": "America/Los_Angeles", - }, - ] - `); + [ + { + "city": "San Francisco", + "timezone": "America/Argentina/Cordoba", + }, + { + "city": "San Francisco de Macoris", + "timezone": "America/Santo_Domingo", + }, + { + "city": "San Francisco Gotera", + "timezone": "America/El_Salvador", + }, + { + "city": "San Francisco", + "timezone": "America/Los_Angeles", + }, + ] + `); }); it("should return appropriate timezone(s) for a given city name array", () => { expect(addCitiesToDropdown(cityData)).toMatchInlineSnapshot(` - { - "America/Argentina/Cordoba": "San Francisco", - "America/El_Salvador": "San Francisco Gotera", - "America/Los_Angeles": "San Francisco", - "America/Santo_Domingo": "San Francisco de Macoris", - "America/Sao_Paulo": "Sao Francisco do Sul", - } - `); + { + "Africa/Johannesburg": "South Africa Standard Time", + "America/Argentina/Cordoba": "San Francisco", + "America/Chicago": "Central Time - US & Canada", + "America/Denver": "Mountain Time - US & Canada", + "America/El_Salvador": "San Francisco Gotera", + "America/Halifax": "Atlantic Time - Canada", + "America/Los_Angeles": "Pacific Time - US & Canada", + "America/New_York": "Eastern Time - US & Canada", + "America/Santo_Domingo": "San Francisco de Macoris", + "America/Sao_Paulo": "Brazil Time", + "Asia/Dubai": "Gulf Standard Time", + "Asia/Kolkata": "India Standard Time", + "Asia/Tokyo": "Japan Standard Time", + "Australia/Sydney": "Australian Eastern Time", + "Europe/Berlin": "Central European Time", + "Europe/Bucharest": "Eastern European Time", + "Europe/London": "Western European Time", + "Pacific/Honolulu": "Hawaii-Aleutian Standard Time", + } + `); }); it("should render city name as option label if cityData is not empty", () => { diff --git a/apps/web/test/utils/bookingScenario/bookingScenario.ts b/apps/web/test/utils/bookingScenario/bookingScenario.ts index 63625e3d99d673..bb5362bd06889b 100644 --- a/apps/web/test/utils/bookingScenario/bookingScenario.ts +++ b/apps/web/test/utils/bookingScenario/bookingScenario.ts @@ -193,6 +193,7 @@ type WhiteListedBookingProps = { // TODO: Make sure that all references start providing credentialId and then remove this intersection of optional credentialId credentialId?: number | null; })[]; + user?: { id: number }; bookingSeat?: Prisma.BookingSeatCreateInput[]; createdAt?: string; }; @@ -400,6 +401,7 @@ async function addBookingsToDb( bookings: (Prisma.BookingCreateInput & { // eslint-disable-next-line @typescript-eslint/no-explicit-any references: any[]; + user?: { id: number }; })[] ) { log.silly("TestData: Creating Bookings", JSON.stringify(bookings)); @@ -490,6 +492,16 @@ export async function addBookings(bookings: InputBooking[]) { }; } + if (booking?.user?.id) { + bookingCreate.user = { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + //@ts-ignore + connect: { + id: booking.user.id, + }, + }; + } + return bookingCreate; }) ); diff --git a/docs/api-reference/v2/openapi.json b/docs/api-reference/v2/openapi.json index ba677723b1a7d8..9d038ce06b5038 100644 --- a/docs/api-reference/v2/openapi.json +++ b/docs/api-reference/v2/openapi.json @@ -59,84 +59,6 @@ "tags": ["Platform / Cal Provider"] } }, - "/v2/conferencing": { - "get": { - "operationId": "ConferencingController_listConferencingApps", - "summary": "List your conferencing applications", - "parameters": [], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConferencingAppsOutputResponseDto" - } - } - } - } - }, - "tags": ["Platform / Conferencing"] - } - }, - "/v2/conferencing/{app}/default": { - "post": { - "operationId": "ConferencingController_default", - "summary": "Set your default conferencing application", - "parameters": [ - { - "name": "app", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SetDefaultConferencingAppOutputResponseDto" - } - } - } - } - }, - "tags": ["Platform / Conferencing"] - } - }, - "/v2/conferencing/{app}/disconnect": { - "delete": { - "operationId": "ConferencingController_disconnect", - "summary": "Disconnect your conferencing application", - "parameters": [ - { - "name": "app", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConferencingAppOutputResponseDto" - } - } - } - } - }, - "tags": ["Platform / Conferencing"] - } - }, "/v2/gcal/oauth/auth-url": { "get": { "operationId": "GcalController_redirect", @@ -3435,6 +3357,113 @@ "tags": ["Calendars"] } }, + "/v2/conferencing/{app}/connect": { + "post": { + "operationId": "ConferencingController_connect", + "summary": "Connect your conferencing application", + "parameters": [ + { + "name": "app", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConferencingAppOutputResponseDto" + } + } + } + } + }, + "tags": ["Conferencing"] + } + }, + "/v2/conferencing": { + "get": { + "operationId": "ConferencingController_listConferencingApps", + "summary": "List your conferencing applications", + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConferencingAppsOutputResponseDto" + } + } + } + } + }, + "tags": ["Conferencing"] + } + }, + "/v2/conferencing/{app}/default": { + "post": { + "operationId": "ConferencingController_default", + "summary": "Set your default conferencing application", + "parameters": [ + { + "name": "app", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetDefaultConferencingAppOutputResponseDto" + } + } + } + } + }, + "tags": ["Conferencing"] + } + }, + "/v2/conferencing/{app}/disconnect": { + "delete": { + "operationId": "ConferencingController_disconnect", + "summary": "Disconnect your conferencing application", + "parameters": [ + { + "name": "app", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConferencingAppOutputResponseDto" + } + } + } + } + }, + "tags": ["Conferencing"] + } + }, "/v2/destination-calendars": { "put": { "operationId": "DestinationCalendarsController_updateDestinationCalendars", @@ -10030,7 +10059,9 @@ "RECORDING_READY", "INSTANT_MEETING", "RECORDING_TRANSCRIPTION_GENERATED", - "OOO_CREATED" + "OOO_CREATED", + "AFTER_HOSTS_CAL_VIDEO_NO_SHOW", + "AFTER_GUESTS_CAL_VIDEO_NO_SHOW" ] }, "active": { @@ -10094,7 +10125,9 @@ "RECORDING_READY", "INSTANT_MEETING", "RECORDING_TRANSCRIPTION_GENERATED", - "OOO_CREATED" + "OOO_CREATED", + "AFTER_HOSTS_CAL_VIDEO_NO_SHOW", + "AFTER_GUESTS_CAL_VIDEO_NO_SHOW" ] }, "active": { @@ -11685,6 +11718,73 @@ } }, "required": ["status", "data"] + }, + "ConferencingAppsOutputDto": { + "type": "object", + "properties": { + "id": { + "type": "number", + "description": "Id of the conferencing app credentials" + }, + "type": { + "type": "string", + "example": "google_video", + "description": "Type of conferencing app" + }, + "userId": { + "type": "number", + "description": "Id of the user associated to the conferencing app" + }, + "invalid": { + "type": "boolean", + "nullable": true, + "example": true, + "description": "Whether if the connection is working or not." + } + }, + "required": ["id", "type", "userId"] + }, + "ConferencingAppOutputResponseDto": { + "type": "object", + "properties": { + "status": { + "type": "string", + "example": "success", + "enum": ["success", "error"] + }, + "data": { + "$ref": "#/components/schemas/ConferencingAppsOutputDto" + } + }, + "required": ["status", "data"] + }, + "ConferencingAppsOutputResponseDto": { + "type": "object", + "properties": { + "status": { + "type": "string", + "example": "success", + "enum": ["success", "error"] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ConferencingAppsOutputDto" + } + } + }, + "required": ["status", "data"] + }, + "SetDefaultConferencingAppOutputResponseDto": { + "type": "object", + "properties": { + "status": { + "type": "string", + "example": "success", + "enum": ["success", "error"] + } + }, + "required": ["status"] } } } diff --git a/docs/introduction.mdx b/docs/introduction.mdx index f3ba80e90ffe92..d4379b597f60dd 100644 --- a/docs/introduction.mdx +++ b/docs/introduction.mdx @@ -26,7 +26,7 @@ import config from "@project-config"
- +
diff --git a/docs/mint.json b/docs/mint.json index e6b7655e18cba4..acde445ba920e5 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -2,8 +2,8 @@ "$schema": "https://mintlify.com/schema.json", "name": "Cal.com Docs", "logo": { - "dark": "https://cal.com/logo-white.svg", - "light": "https://cal.com/logo.svg" + "dark": "https://cal.com/calcom-docs-light.svg", + "light": "https://cal.com/calcom-docs.svg" }, "api": { "baseUrl": "https://api.cal.com", diff --git a/i18n.lock b/i18n.lock index 9fac2ebf1e1703..c5b67e3bf571b7 100644 --- a/i18n.lock +++ b/i18n.lock @@ -1229,6 +1229,8 @@ checksums: number_provided: 3486dd81e0aace30d7d39116a512dc77 before_event_trigger: 8f4c3aa39367d1e1d22d0380ba73591c event_cancelled_trigger: b5d22f397e0f564fcf431032b75ff1af + after_hosts_cal_video_no_show: 6b190531cc1bd5f00a6d3a31188d277c + after_guests_cal_video_no_show: e5833aeb28ef1004fbeae2c91754d3e7 new_event_trigger: fbee38b5765412419941add7ff1e3fb9 email_host_action: 9566929caf21c96cedc11447e1de34ff email_attendee_action: 3ca2ca348baef93742f3a1889ffcc96b @@ -1645,6 +1647,9 @@ checksums: email_address_action: b2781c452a4f0a3f941d3219f4a6034f after_event_trigger: c6eee0242d7bf2049809c45c8f83f279 how_long_after: 5869f7636010a4c0afd608b1f369dc49 + how_long_after_hosts_no_show: a1e521c09c91f3c4e016d9900965d3e6 + how_long_after_guests_no_show: 8e1774a854eb638dd78151d6ac314215 + how_long_after_user_no_show_minutes: ea4a3bbdb562532359827cdb4cfc0998 no_available_slots: b19cb280c9094cf969fe0b016dfb8221 time_available: 01de4783c7e7134ac8946d2123674f16 cant_find_the_right_conferencing_app_visit_our_app_store: 0919dad2291f81d176b8459e61ace1f9 @@ -1670,6 +1675,7 @@ checksums: billing_frequency: 99a9a500d46797c0b3e86bc53ef56321 monthly: 818f1192e32bb855597f930d3e78806e yearly: 87f43e016c19cb25860f456549a2f431 + weekly: 9e687411dbf1248496a4ae5dd5391679 checkout: a03cbd25ad34ec762c35441d6c5a86b5 your_team_disbanded_successfully: 876e04b0db54044fd2fb05e1fa3c52e7 your_org_disbanded_successfully: cef1863bd26106d44fd1f338d3a5f479 @@ -2604,6 +2610,7 @@ checksums: disable_email: bd2f5d1abe9340d841ad01cf05646679 grant_admin_api: 57e59ff0e0a24e8134a9447ba75ac199 revoke_admin_api: 0d910a3c3874b9a199705e1e63281f19 + add_calendar_label: 484fb6585e02c2105dfda5e6cb345198 apple_connect_atom_label: ab6ea61350cc5eb812d450184115311d apple_connect_atom_already_connected_label: 4ba5d56114cca48a21e2b76adff460ab apple_connect_atom_loading_label: 50abf79580c18f4886be57161e383137 @@ -2635,5 +2642,14 @@ checksums: month_to_date: 7f7e4653c67cdaab178faa332007b1a0 year_to_date: 1de1bfcb57fc841987305d851383042a custom_range: c489facbacd8b2b232c9ea6aae568ae3 + salesforce_create_record_as: cbbfbdf5568f642bfc38dc83284c3c18 + salesforce_lead: f1dee70c3b331625a29cc93338b3078c + salesforce_contact_under_account: 7311a2c181c34ad69ff9751472d4f7f3 + salesforce_skip_entry_creation: 552cd5e07e6244febfdebe676c825a41 + salesforce_if_account_does_not_exist: ff7ce8c176eaa2ed8a7e6fe09327e830 + salesforce_create_new_contact_under_account: 929d1effb813cc09b87f79fee1cb699d mass_assign_attributes: 92df3a9cc0a1d55a616c014517c5bee5 + salesforce_book_directly_with_attendee_owner: 32527f7bc50272de1cb81401e0bf17a9 + salesforce_check_owner_of: f9e2369739fa3b659b86ed78c1937b11 + account: 01215c12fb1cdb93bd0c84c1382bef56 ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS: 18323f2f3fabb169a7cb50ff62433850 diff --git a/package.json b/package.json index 555af04a33ba8d..511415ac1307ad 100644 --- a/package.json +++ b/package.json @@ -87,6 +87,7 @@ "@snaplet/copycat": "^4.1.0", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^16.0.1", + "@types/dompurify": "^3.0.5", "@types/jsdom": "^21.1.3", "@types/jsonwebtoken": "^9.0.3", "@vitest/ui": "^2.1.1", @@ -101,6 +102,7 @@ "lint-staged": "^12.5.0", "mailhog": "^4.16.0", "next-router-mock": "^0.9.12", + "node-gyp": "^10.2.0", "node-ical": "^0.16.1", "prettier": "^2.8.6", "prismock": "^1.21.1", diff --git a/packages/app-store/_utils/CRMRoundRobinSkip.ts b/packages/app-store/_utils/CRMRoundRobinSkip.ts index 902f6dcba4cac2..bdd514c6fd6bf2 100644 --- a/packages/app-store/_utils/CRMRoundRobinSkip.ts +++ b/packages/app-store/_utils/CRMRoundRobinSkip.ts @@ -24,7 +24,7 @@ export async function getCRMContactOwnerForRRLeadSkip( if (!crm) return; - const contact = await crm.getContacts(bookerEmail, true); + const contact = await crm.getContacts({ emails: bookerEmail, forRoundRobinSkip: true }); if (!contact?.length) return; return contact[0].ownerEmail; } @@ -57,5 +57,5 @@ async function getCRMManagerWithRRLeadSkip(apps: z.infer = new (...args: Args) => I; -type CrmClass = Class; +type CrmClass = Class; const log = logger.getSubLogger({ prefix: ["CrmManager"] }); -export const getCrm = async (credential: CredentialPayload) => { +export const getCrm = async (credential: CredentialPayload, appOptions: any) => { if (!credential || !credential.key) return null; const { type: crmType } = credential; @@ -26,7 +26,7 @@ export const getCrm = async (credential: CredentialPayload) => { if (crmApp && "lib" in crmApp && "CrmService" in crmApp.lib) { const CrmService = crmApp.lib.CrmService as CrmClass; - return new CrmService(credential); + return new CrmService(credential, appOptions); } }; diff --git a/packages/app-store/apps.metadata.generated.ts b/packages/app-store/apps.metadata.generated.ts index c92d8301681a89..aa8e5ec18e872a 100644 --- a/packages/app-store/apps.metadata.generated.ts +++ b/packages/app-store/apps.metadata.generated.ts @@ -75,6 +75,7 @@ import sylapsvideo_config_json from "./sylapsvideo/config.json"; import synthflow_config_json from "./synthflow/config.json"; import { metadata as tandemvideo__metadata_ts } from "./tandemvideo/_metadata"; import telegram_config_json from "./telegram/config.json"; +import telli_config_json from "./telli/config.json"; import basic_config_json from "./templates/basic/config.json"; import booking_pages_tag_config_json from "./templates/booking-pages-tag/config.json"; import event_type_app_card_config_json from "./templates/event-type-app-card/config.json"; @@ -172,6 +173,7 @@ export const appStoreMetadata = { synthflow: synthflow_config_json, tandemvideo: tandemvideo__metadata_ts, telegram: telegram_config_json, + telli: telli_config_json, basic: basic_config_json, "booking-pages-tag": booking_pages_tag_config_json, "event-type-app-card": event_type_app_card_config_json, diff --git a/packages/app-store/apps.server.generated.ts b/packages/app-store/apps.server.generated.ts index 10d24f62ba0ecf..fb49314baefa38 100644 --- a/packages/app-store/apps.server.generated.ts +++ b/packages/app-store/apps.server.generated.ts @@ -75,6 +75,7 @@ export const apiHandlers = { synthflow: import("./synthflow/api"), tandemvideo: import("./tandemvideo/api"), telegram: import("./telegram/api"), + telli: import("./telli/api"), basic: import("./templates/basic/api"), "booking-pages-tag": import("./templates/booking-pages-tag/api"), "event-type-app-card": import("./templates/event-type-app-card/api"), diff --git a/packages/app-store/closecom/lib/CrmService.ts b/packages/app-store/closecom/lib/CrmService.ts index 86a4ddc900359d..4dd17fa4218ce2 100644 --- a/packages/app-store/closecom/lib/CrmService.ts +++ b/packages/app-store/closecom/lib/CrmService.ts @@ -121,7 +121,7 @@ export default class CloseComCRMService implements CRM { await this.closeComDeleteCustomActivity(uid); } - async getContacts(emails: string | string[]): Promise { + async getContacts({ emails }: { emails: string | string[] }): Promise { const contactsQuery = await this.closeCom.contact.search({ emails: Array.isArray(emails) ? emails : [emails], }); @@ -177,4 +177,8 @@ export default class CloseComCRMService implements CRM { return contacts; } + + getAppOptions() { + console.log("No options implemented"); + } } diff --git a/packages/app-store/dailyvideo/lib/VideoApiAdapter.ts b/packages/app-store/dailyvideo/lib/VideoApiAdapter.ts index 05ea6422479c93..4a120b65393036 100644 --- a/packages/app-store/dailyvideo/lib/VideoApiAdapter.ts +++ b/packages/app-store/dailyvideo/lib/VideoApiAdapter.ts @@ -1,6 +1,7 @@ import { z } from "zod"; -import { handleErrorsJson } from "@calcom/lib/errors"; +import { getDailyAppKeys } from "@calcom/app-store/dailyvideo/lib/getDailyAppKeys"; +import { fetcher } from "@calcom/lib/dailyApiFetcher"; import { prisma } from "@calcom/prisma"; import type { GetRecordingsResponseSchema, GetAccessLinkResponseSchema } from "@calcom/prisma/zod-utils"; import { @@ -15,7 +16,6 @@ import type { VideoApiAdapter, VideoCallData } from "@calcom/types/VideoApiAdapt import { ZSubmitBatchProcessorJobRes, ZGetTranscriptAccessLink } from "../zod"; import type { TSubmitBatchProcessorJobRes, TGetTranscriptAccessLink, batchProcessorBody } from "../zod"; -import { getDailyAppKeys } from "./getDailyAppKeys"; import { dailyReturnTypeSchema, getTranscripts, @@ -54,19 +54,6 @@ export const FAKE_DAILY_CREDENTIAL: CredentialPayload & { invalid: boolean } = { teamId: null, }; -export const fetcher = async (endpoint: string, init?: RequestInit | undefined) => { - const { api_key } = await getDailyAppKeys(); - return fetch(`https://api.daily.co/v1${endpoint}`, { - method: "GET", - headers: { - Authorization: `Bearer ${api_key}`, - "Content-Type": "application/json", - ...init?.headers, - }, - ...init, - }).then(handleErrorsJson); -}; - function postToDailyAPI(endpoint: string, body: Record) { return fetcher(endpoint, { method: "POST", @@ -111,7 +98,10 @@ async function processTranscriptsInBatches(transcriptIds: Array) { return allTranscriptsAccessLinks; } -export const generateGuestMeetingTokenFromOwnerMeetingToken = async (meetingToken: string | null) => { +export const generateGuestMeetingTokenFromOwnerMeetingToken = async ( + meetingToken: string | null, + userId?: number +) => { if (!meetingToken) return null; const token = await fetcher(`/meeting-tokens/${meetingToken}`).then(ZGetMeetingTokenResponseSchema.parse); @@ -120,6 +110,7 @@ export const generateGuestMeetingTokenFromOwnerMeetingToken = async (meetingToke room_name: token.room_name, exp: token.exp, enable_recording_ui: false, + user_id: userId, }, }).then(meetingTokenSchema.parse); @@ -127,14 +118,15 @@ export const generateGuestMeetingTokenFromOwnerMeetingToken = async (meetingToke }; // Only for backward compatibility -export const setEnableRecordingUIForOrganizer = async ( +export const setEnableRecordingUIAndUserIdForOrganizer = async ( bookingReferenceId: number, - meetingToken: string | null + meetingToken: string | null, + userId?: number ) => { if (!meetingToken) return null; const token = await fetcher(`/meeting-tokens/${meetingToken}`).then(ZGetMeetingTokenResponseSchema.parse); - if (token.enable_recording_ui === false) return null; + if (token.enable_recording_ui === false && !!token.user_id) return null; const organizerMeetingToken = await postToDailyAPI("/meeting-tokens", { properties: { @@ -142,6 +134,7 @@ export const setEnableRecordingUIForOrganizer = async ( exp: token.exp, enable_recording_ui: false, is_owner: true, + user_id: userId, }, }).then(meetingTokenSchema.parse); diff --git a/packages/app-store/dailyvideo/lib/types.ts b/packages/app-store/dailyvideo/lib/types.ts index 6596997a0dd336..6a167a5c6e6d0c 100644 --- a/packages/app-store/dailyvideo/lib/types.ts +++ b/packages/app-store/dailyvideo/lib/types.ts @@ -54,14 +54,17 @@ export const getRooms = z }) .passthrough(); -export const meetingTokenSchema = z.object({ - token: z.string(), -}); +export const meetingTokenSchema = z + .object({ + token: z.string(), + }) + .passthrough(); export const ZGetMeetingTokenResponseSchema = z .object({ room_name: z.string(), exp: z.number(), enable_recording_ui: z.boolean().optional(), + user_id: z.number().optional(), }) .passthrough(); diff --git a/packages/app-store/exchangecalendar/lib/CalendarService.ts b/packages/app-store/exchangecalendar/lib/CalendarService.ts index cf1934b8b32b17..e0dd65b07ec9a3 100644 --- a/packages/app-store/exchangecalendar/lib/CalendarService.ts +++ b/packages/app-store/exchangecalendar/lib/CalendarService.ts @@ -204,7 +204,6 @@ export default class ExchangeCalendarService implements Calendar { if (this.payload.authenticationMethod === ExchangeAuthentication.NTLM) { const xhr: XhrApi = new XhrApi({ rejectUnauthorized: false, - gzip: this.payload.useCompression, }).useNtlmAuthentication(this.payload.username, this.payload.password); service.XHRApi = xhr; } diff --git a/packages/app-store/exchangecalendar/package.json b/packages/app-store/exchangecalendar/package.json index 6def8aaa798acc..6c01a0d405edfe 100644 --- a/packages/app-store/exchangecalendar/package.json +++ b/packages/app-store/exchangecalendar/package.json @@ -8,7 +8,7 @@ "dependencies": { "@calcom/lib": "*", "@calcom/prisma": "*", - "@ewsjs/xhr": "^1.4.4", + "@ewsjs/xhr": "^3.1.2", "ews-javascript-api": "^0.11.0" }, "devDependencies": { diff --git a/packages/app-store/exchangecalendar/pages/setup/index.tsx b/packages/app-store/exchangecalendar/pages/setup/index.tsx index 6597cdc700c4b8..6acde1651d50d2 100644 --- a/packages/app-store/exchangecalendar/pages/setup/index.tsx +++ b/packages/app-store/exchangecalendar/pages/setup/index.tsx @@ -6,7 +6,7 @@ import { Toaster } from "react-hot-toast"; import z from "zod"; import { useLocale } from "@calcom/lib/hooks/useLocale"; -import { Alert, Button, EmailField, Form, PasswordField, SelectField, Switch, TextField } from "@calcom/ui"; +import { Alert, Button, EmailField, Form, PasswordField, SelectField, TextField } from "@calcom/ui"; import { ExchangeAuthentication, ExchangeVersion } from "../../enums"; @@ -36,11 +36,12 @@ export default function ExchangeSetup() { const [errorMessage, setErrorMessage] = useState(""); const form = useForm({ defaultValues: { - authenticationMethod: ExchangeAuthentication.STANDARD, + authenticationMethod: ExchangeAuthentication.NTLM, exchangeVersion: ExchangeVersion.Exchange2016, }, resolver: zodResolver(schema), }); + const authenticationMethod = form.watch("authenticationMethod"); const authenticationMethods = [ { value: ExchangeAuthentication.STANDARD, label: t("exchange_authentication_standard") }, { value: ExchangeAuthentication.NTLM, label: t("exchange_authentication_ntlm") }, @@ -115,44 +116,49 @@ export default function ExchangeSetup() { ( - { - if (authentication) { - onChange(authentication.value); - form.setValue("authenticationMethod", authentication.value); - } - }} - /> - )} - /> - ( - { - onChange(version?.value); - if (version) { - form.setValue("exchangeVersion", version.value); - } - }} - /> - )} - /> - { - form.setValue("useCompression", alt); + render={({ field: { onChange } }) => { + const ntlmAuthenticationMethod = authenticationMethods.find( + (method) => method.value === ExchangeAuthentication.NTLM + ); + return ( + { + if (authentication) { + onChange(authentication.value); + form.setValue("authenticationMethod", authentication.value); + } + }} + /> + ); }} /> + {authenticationMethod === ExchangeAuthentication.STANDARD ? ( + { + const exchangeVersion2016 = exchangeVersions.find( + (exchangeVersion) => exchangeVersion.value === ExchangeVersion.Exchange2016 + ); + return ( + { + onChange(version?.value); + if (version) { + form.setValue("exchangeVersion", version.value); + } + }} + /> + ); + }} + /> + ) : null} {errorMessage && }
diff --git a/packages/app-store/hubspot/lib/CrmService.ts b/packages/app-store/hubspot/lib/CrmService.ts index 7cbbe1f9a6dfc8..80847f08892515 100644 --- a/packages/app-store/hubspot/lib/CrmService.ts +++ b/packages/app-store/hubspot/lib/CrmService.ts @@ -198,7 +198,7 @@ export default class HubspotCalendarService implements CRM { return await this.hubspotDeleteMeeting(uid); } - async getContacts(emails: string | string[]): Promise { + async getContacts({ emails }: { emails: string | string[] }): Promise { const auth = await this.auth; await auth.getToken(); @@ -269,4 +269,8 @@ export default class HubspotCalendarService implements CRM { }; }); } + + getAppOptions() { + console.log("No options implemented"); + } } diff --git a/packages/app-store/pipedrive-crm/lib/CrmService.ts b/packages/app-store/pipedrive-crm/lib/CrmService.ts index ee5dac16a055fb..b7e88d30f650b9 100644 --- a/packages/app-store/pipedrive-crm/lib/CrmService.ts +++ b/packages/app-store/pipedrive-crm/lib/CrmService.ts @@ -78,8 +78,8 @@ export default class PipedriveCrmService implements CRM { return results.map((result) => result.result); } - async getContacts(email: string | string[]): Promise { - const emailArray = Array.isArray(email) ? email : [email]; + async getContacts({ emails }: { emails: string | string[] }): Promise { + const emailArray = Array.isArray(emails) ? emails : [emails]; const result = emailArray.map(async (attendeeEmail) => { const headers = new Headers(); @@ -230,4 +230,8 @@ export default class PipedriveCrmService implements CRM { async listCalendars(_event?: CalendarEvent): Promise { return Promise.resolve([]); } + + getAppOptions() { + console.log("No options implemented"); + } } diff --git a/packages/app-store/routing-forms/playwright/tests/basic.e2e.ts b/packages/app-store/routing-forms/playwright/tests/basic.e2e.ts index 82080314eaab17..f23e2c3461f9e0 100644 --- a/packages/app-store/routing-forms/playwright/tests/basic.e2e.ts +++ b/packages/app-store/routing-forms/playwright/tests/basic.e2e.ts @@ -34,14 +34,20 @@ async function enableContactOwnerOverride(page: Page) { async function selectFirstAttributeOption({ fromLocator }: { fromLocator: Locator }) { await selectOptionUsingLocator({ locator: fromLocator, - option: 1 + option: 1, }); } -async function selectFirstValueForAttributeValue({ fromLocator, option }: { fromLocator: Locator, option: number }) { +async function selectFirstValueForAttributeValue({ + fromLocator, + option, +}: { + fromLocator: Locator; + option: number; +}) { await selectOptionUsingLocator({ locator: fromLocator, - option + option, }); } @@ -59,7 +65,7 @@ async function addAttributeRoutingRule(page: Page) { await selectFirstValueForAttributeValue({ fromLocator: attributeValueSelector, // Select 'Value of Field Short Text' option - option: numOfOptionsInAttribute + 1 + option: numOfOptionsInAttribute + 1, }); } @@ -571,7 +577,7 @@ test.describe("Routing Forms", () => { await page.click('[data-testid="test-preview"]'); await page.fill('[data-testid="form-field-short-text"]', "large"); await page.click('[data-testid="test-routing"]'); - await page.waitForSelector('text=@example.com'); + await page.waitForSelector("text=@example.com"); await page.click('[data-testid="dialog-rejection"]'); })(); @@ -579,9 +585,8 @@ test.describe("Routing Forms", () => { await page.click('[data-testid="test-preview"]'); await page.fill('[data-testid="form-field-short-text"]', "medium"); await page.click('[data-testid="test-routing"]'); - await page.waitForSelector('text=No matching members.'); + await page.waitForSelector("text=No matching members."); await page.click('[data-testid="dialog-rejection"]'); - })(); }); }); @@ -751,15 +756,12 @@ async function selectOption({ .click(); } -export async function selectOptionUsingLocator({ - locator, - option, -}: { - locator: Locator; - option: number; -}) { +export async function selectOptionUsingLocator({ locator, option }: { locator: Locator; option: number }) { await locator.click(); - await locator.locator('[id*="react-select-"][aria-disabled]').nth(option - 1).click(); + await locator + .locator('[id*="react-select-"][aria-disabled]') + .nth(option - 1) + .click(); } async function verifyFieldOptionsInRule(options: string[], page: Page) { diff --git a/packages/app-store/salesforce/components/EventTypeAppCardInterface.tsx b/packages/app-store/salesforce/components/EventTypeAppCardInterface.tsx index 1597bc4f577fbf..ed232e6626109c 100644 --- a/packages/app-store/salesforce/components/EventTypeAppCardInterface.tsx +++ b/packages/app-store/salesforce/components/EventTypeAppCardInterface.tsx @@ -1,4 +1,5 @@ import { usePathname } from "next/navigation"; +import { useState } from "react"; import { useAppContextWithSchema } from "@calcom/app-store/EventTypeAppContext"; import AppCard from "@calcom/app-store/_components/AppCard"; @@ -7,8 +8,9 @@ import type { EventTypeAppCardComponent } from "@calcom/app-store/types"; import { WEBAPP_URL } from "@calcom/lib/constants"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { SchedulingType } from "@calcom/prisma/enums"; -import { Switch, Alert } from "@calcom/ui"; +import { Switch, Alert, Select } from "@calcom/ui"; +import { SalesforceRecordEnum } from "../lib/recordEnum"; import type { appDataSchema } from "../zod"; const EventTypeAppCard: EventTypeAppCardComponent = function EventTypeAppCard({ app, eventType }) { @@ -17,9 +19,32 @@ const EventTypeAppCard: EventTypeAppCardComponent = function EventTypeAppCard({ const { getAppData, setAppData, disabled } = useAppContextWithSchema(); const { enabled, updateEnabled } = useIsAppEnabled(app); const isRoundRobinLeadSkipEnabled = getAppData("roundRobinLeadSkip"); + const roundRobinSkipCheckRecordOn = + getAppData("roundRobinSkipCheckRecordOn") ?? SalesforceRecordEnum.CONTACT; const isSkipContactCreationEnabled = getAppData("skipContactCreation"); + const createLeadIfAccountNull = getAppData("createLeadIfAccountNull"); + const createNewContactUnderAccount = getAppData("createNewContactUnderAccount"); + const createEventOn = getAppData("createEventOn") ?? SalesforceRecordEnum.CONTACT; const { t } = useLocale(); + const recordOptions = [ + { label: t("contact"), value: SalesforceRecordEnum.CONTACT }, + { label: t("salesforce_lead"), value: SalesforceRecordEnum.LEAD }, + { label: t("salesforce_contact_under_account"), value: SalesforceRecordEnum.ACCOUNT }, + ]; + const [createEventOnSelectedOption, setCreateEventOnSelectedOption] = useState( + recordOptions.find((option) => option.value === createEventOn) ?? recordOptions[0] + ); + + const checkOwnerOptions = [ + { label: t("contact"), value: SalesforceRecordEnum.CONTACT }, + { label: t("salesforce_lead"), value: SalesforceRecordEnum.LEAD }, + { label: t("account"), value: SalesforceRecordEnum.ACCOUNT }, + ]; + const [checkOwnerSelectedOption, setCheckOwnerSelectedOption] = useState( + checkOwnerOptions.find((option) => option.value === roundRobinSkipCheckRecordOn) ?? checkOwnerOptions[0] + ); + return ( <> -
- { - setAppData("skipContactCreation", checked); - }} - /> -
- - {eventType.schedulingType === SchedulingType.ROUND_ROBIN ? ( -
- { - setAppData("roundRobinLeadSkip", checked); - if (checked) { - // temporary solution, enabled should always be already set - setAppData("enabled", checked); +
+ + { + if (e) { + setCheckOwnerSelectedOption(e); + setAppData("roundRobinSkipCheckRecordOn", e.value); + } + }} + /> +
+ ) : null} + +
+ ) : null} +
); }; diff --git a/packages/app-store/salesforce/lib/CrmService.ts b/packages/app-store/salesforce/lib/CrmService.ts index 34e78fa6714e34..034838ee97f94c 100644 --- a/packages/app-store/salesforce/lib/CrmService.ts +++ b/packages/app-store/salesforce/lib/CrmService.ts @@ -15,6 +15,7 @@ import type { CRM, Contact, CrmEvent } from "@calcom/types/CrmService"; import getAppKeysFromSlug from "../../_utils/getAppKeysFromSlug"; import type { ParseRefreshTokenResponse } from "../../_utils/oauth/parseRefreshTokenResponse"; import parseRefreshTokenResponse from "../../_utils/oauth/parseRefreshTokenResponse"; +import { SalesforceRecordEnum } from "./recordEnum"; type ExtendedTokenResponse = TokenResponse & { instance_url: string; @@ -55,11 +56,18 @@ export default class SalesforceCRMService implements CRM { private conn: Promise; private log: typeof logger; private calWarnings: string[] = []; + private appOptions: any; + private doNotCreateEvent = false; - constructor(credential: CredentialPayload) { + constructor(credential: CredentialPayload, appOptions: any) { this.integrationName = "salesforce_other_calendar"; this.conn = this.getClient(credential).then((c) => c); this.log = logger.getSubLogger({ prefix: [`[[lib] ${this.integrationName}`] }); + this.appOptions = appOptions; + } + + public getAppOptions() { + return this.appOptions; } private getClient = async (credential: CredentialPayload) => { @@ -224,7 +232,10 @@ export default class SalesforceCRMService implements CRM { }); } - async createEvent(event: CalendarEvent, contacts: Contact[]): Promise { + async createEvent(event: CalendarEvent, contacts: Contact[]): Promise { + const skipEventCreation = this.getDoNotCreateEvent(); + if (skipEventCreation) return undefined; + const sfEvent = await this.salesforceCreateEvent(event, contacts); if (sfEvent.success) { return Promise.resolve({ @@ -265,17 +276,46 @@ export default class SalesforceCRMService implements CRM { } } - async getContacts(email: string | string[], includeOwner?: boolean) { + async getContacts({ + emails, + includeOwner, + forRoundRobinSkip, + }: { + emails: string | string[]; + includeOwner?: boolean; + forRoundRobinSkip?: boolean; + }) { const conn = await this.conn; - const emails = Array.isArray(email) ? email : [email]; - const soql = `SELECT Id, Email, OwnerId FROM Contact WHERE Email IN ('${emails.join("','")}')`; + const emailArray = Array.isArray(emails) ? emails : [emails]; + const appOptions = this.getAppOptions(); + const recordToSearch = + (forRoundRobinSkip ? appOptions?.roundRobinSkipCheckRecordOn : appOptions?.createEventOn) ?? + SalesforceRecordEnum.CONTACT; + let soql: string; + if (recordToSearch === SalesforceRecordEnum.ACCOUNT) { + // For an account let's assume that the first email is the one we should be querying against + const attendeeEmail = emailArray[0]; + soql = `SELECT Id, Email, OwnerId, AccountId FROM Contact WHERE Email = '${attendeeEmail}' AND AccountId != null`; + + // If this is for a round robin skip then we need to return the account record + if (forRoundRobinSkip) { + const results = await conn.query(soql); + if (results.records.length) { + const contact = results.records[0] as { AccountId: string }; + soql = `SELECT Id, OwnerId FROM Account WHERE Id = '${contact.AccountId}'`; + } + } + // If creating events on contacts or leads + } else { + soql = `SELECT Id, Email, OwnerId FROM ${recordToSearch} WHERE Email IN ('${emailArray.join("','")}')`; + } const results = await conn.query(soql); if (!results || !results.records.length) return []; const records = results.records as ContactRecord[]; - if (includeOwner) { + if (includeOwner || forRoundRobinSkip) { const ownerIds: Set = new Set(); records.forEach((record) => { ownerIds.add(record.OwnerId); @@ -304,27 +344,160 @@ export default class SalesforceCRMService implements CRM { async createContacts(contactsToCreate: { email: string; name: string }[], organizerEmail?: string) { const conn = await this.conn; - - // See if the organizer exists in the CRM + const appOptions = this.getAppOptions(); + const createEventOn = appOptions.createEventOn ?? SalesforceRecordEnum.CONTACT; const organizerId = organizerEmail ? await this.getSalesforceUserIdFromEmail(organizerEmail) : undefined; - const createdContacts = await Promise.all( - contactsToCreate.map(async (attendee) => { - const [FirstName, LastName] = attendee.name ? attendee.name.split(" ") : [attendee.email, ""]; - return await conn - .sobject("Contact") + const createdContacts: { id: string; email: string }[] = []; + + if (createEventOn === SalesforceRecordEnum.CONTACT || createEventOn === SalesforceRecordEnum.LEAD) { + // See if the organizer exists in the CRM + await Promise.all( + contactsToCreate.map(async (attendee) => { + return await conn + .sobject(createEventOn) + .create( + this.generateCreateRecordBody({ + attendee, + recordType: createEventOn, + organizerId, + }) + ) + .then((result) => { + if (result.success) { + createdContacts.push({ id: result.id, email: attendee.email }); + } + }); + }) + ); + } + + if (createEventOn === SalesforceRecordEnum.ACCOUNT) { + if (!appOptions.createNewContactUnderAccount && !appOptions.createLeadIfAccountNull) { + this.setDoNotCreateEvent(true); + return [{ id: "Do not create event", email: "placeholder" }]; + } + + // Base this off of the first contact + const attendee = contactsToCreate[0]; + + const emailDomain = attendee.email.split("@")[1]; + + const response = await conn.query( + `SELECT Id, Email, AccountId FROM Contact WHERE Email LIKE '%@${emailDomain}' AND AccountId != null` + ); + + const accountId = this.getDominantAccountId(response.records as { AccountId: string }[]); + + if (accountId && appOptions.createNewContactUnderAccount) { + // First see if the contact already exists and connect it to the account + const userQuery = await conn.query(`SELECT Id, Email FROM Contact WHERE Email = '${attendee.email}'`); + if (userQuery.records.length) { + const contact = userQuery.records[0] as { Id: string; Email: string }; + await conn.sobject(SalesforceRecordEnum.CONTACT).update({ + // The first argument is the WHERE clause + Id: contact.Id, + AccountId: accountId, + }); + return [{ id: contact.Id, email: contact.Email }]; + } + + await conn + .sobject(SalesforceRecordEnum.CONTACT) .create({ - FirstName, - LastName: LastName || "-", - Email: attendee.email, - ...(organizerId && { OwnerId: organizerId }), + ...this.generateCreateRecordBody({ + attendee, + recordType: SalesforceRecordEnum.CONTACT, + organizerId, + }), + AccountId: accountId, }) .then((result) => { if (result.success) { - return { id: result.id, email: attendee.email }; + createdContacts.push({ id: result.id, email: attendee.email }); } }); - }) - ); - return createdContacts.filter((contact): contact is Contact => contact !== undefined); + } + + if (appOptions.createLeadIfAccountNull) { + await Promise.all( + contactsToCreate.map(async (attendee) => { + return await conn + .sobject(SalesforceRecordEnum.LEAD) + .create( + this.generateCreateRecordBody({ + attendee, + recordType: SalesforceRecordEnum.LEAD, + organizerId, + }) + ) + .then((result) => { + if (result.success) { + createdContacts.push({ id: result.id, email: attendee.email }); + } + }); + }) + ); + } + } + + return createdContacts; + } + + private setDoNotCreateEvent(boolean: boolean) { + this.doNotCreateEvent = boolean; + } + + private getDoNotCreateEvent() { + return this.doNotCreateEvent; + } + + private getDominantAccountId(contacts: { AccountId: string }[]) { + // To get the dominant AccountId we only need to iterate through half the array + const iterateLength = Math.ceil(contacts.length / 2); + // Store AccountId frequencies + const accountIdCounts: { [accountId: string]: number } = {}; + + for (const contact of contacts) { + const accountId = contact.AccountId; + accountIdCounts[accountId] = (accountIdCounts[accountId] || 0) + 1; + // If the number of AccountIds makes up 50% of the array length then return early + if (accountIdCounts[accountId] > iterateLength) return accountId; + } + + // Else figure out which AccountId occurs the most + let dominantAccountId; + let highestCount = 0; + + for (const accountId in accountIdCounts) { + if (accountIdCounts[accountId] > highestCount) { + highestCount = accountIdCounts[accountId]; + dominantAccountId = accountId; + } + } + + return dominantAccountId; + } + + private generateCreateRecordBody({ + attendee, + recordType, + organizerId, + }: { + attendee: { email: string; name: string }; + recordType: SalesforceRecordEnum; + organizerId?: string; + }) { + const [FirstName, LastName] = attendee.name ? attendee.name.split(" ") : [attendee.email, ""]; + + // Assume that the first part of the email domain is the company title + const company = attendee.email.split("@")[1].split(".")[0]; + + return { + LastName: LastName || "-", + FirstName, + Email: attendee.email, + ...(organizerId && { OwnerId: organizerId }), + ...(recordType === SalesforceRecordEnum.LEAD && { Company: company }), + }; } } diff --git a/packages/app-store/salesforce/lib/recordEnum.ts b/packages/app-store/salesforce/lib/recordEnum.ts new file mode 100644 index 00000000000000..b2b77eddecd733 --- /dev/null +++ b/packages/app-store/salesforce/lib/recordEnum.ts @@ -0,0 +1,5 @@ +export enum SalesforceRecordEnum { + CONTACT = "Contact", + LEAD = "Lead", + ACCOUNT = "Account", +} diff --git a/packages/app-store/salesforce/zod.ts b/packages/app-store/salesforce/zod.ts index 0d0e11352ff514..274e3e820a6761 100644 --- a/packages/app-store/salesforce/zod.ts +++ b/packages/app-store/salesforce/zod.ts @@ -1,10 +1,18 @@ import { z } from "zod"; import { eventTypeAppCardZod } from "../eventTypeAppCardZod"; +import { SalesforceRecordEnum } from "./lib/recordEnum"; export const appDataSchema = eventTypeAppCardZod.extend({ roundRobinLeadSkip: z.boolean().optional(), + roundRobinSkipCheckRecordOn: z + .nativeEnum(SalesforceRecordEnum) + .default(SalesforceRecordEnum.CONTACT) + .optional(), skipContactCreation: z.boolean().optional(), + createEventOn: z.nativeEnum(SalesforceRecordEnum).default(SalesforceRecordEnum.CONTACT).optional(), + createNewContactUnderAccount: z.boolean().optional(), + createLeadIfAccountNull: z.boolean().optional(), }); export const appKeysSchema = z.object({ diff --git a/packages/app-store/telli/DESCRIPTION.md b/packages/app-store/telli/DESCRIPTION.md new file mode 100644 index 00000000000000..11c91e109cbfbc --- /dev/null +++ b/packages/app-store/telli/DESCRIPTION.md @@ -0,0 +1,10 @@ +--- +items: + - 1.jpg + - 2.jpg + - 3.jpg + - 4.jpg + - 5.jpg +--- + +{DESCRIPTION} diff --git a/packages/app-store/telli/api/add.ts b/packages/app-store/telli/api/add.ts new file mode 100644 index 00000000000000..89aa62a3d41abc --- /dev/null +++ b/packages/app-store/telli/api/add.ts @@ -0,0 +1,20 @@ +import { createDefaultInstallation } from "@calcom/app-store/_utils/installation"; +import type { AppDeclarativeHandler } from "@calcom/types/AppHandler"; + +import appConfig from "../config.json"; + +const handler: AppDeclarativeHandler = { + appType: appConfig.type, + variant: appConfig.variant, + slug: appConfig.slug, + supportsMultipleInstalls: false, + handlerType: "add", + redirect: { + newTab: true, + url: "https://www.telli.so/en/caldotcom", + }, + createCredential: ({ appType, user, slug, teamId }) => + createDefaultInstallation({ appType, user: user, slug, key: {}, teamId }), +}; + +export default handler; diff --git a/packages/app-store/telli/api/index.ts b/packages/app-store/telli/api/index.ts new file mode 100644 index 00000000000000..4c0d2ead01e1f9 --- /dev/null +++ b/packages/app-store/telli/api/index.ts @@ -0,0 +1 @@ +export { default as add } from "./add"; diff --git a/packages/app-store/telli/components/.gitkeep b/packages/app-store/telli/components/.gitkeep new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/packages/app-store/telli/config.json b/packages/app-store/telli/config.json new file mode 100644 index 00000000000000..cd6b32b91e8c90 --- /dev/null +++ b/packages/app-store/telli/config.json @@ -0,0 +1,16 @@ +{ + "/*": "Don't modify slug - If required, do it using cli edit command", + "name": "telli", + "slug": "telli", + "type": "telli_automation", + "logo": "icon-dark.svg", + "url": "https://www.telli.so/en/caldotcom", + "variant": "automation", + "categories": ["automation"], + "publisher": "telli technologies GmbH", + "email": "founders@telli.so", + "description": "telli AI agents reach your customers, make calls independently & enhance your customer experience - fully integrated into Cal.com.", + "isTemplate": false, + "__createdUsingCli": true, + "__template": "link-as-an-app" +} diff --git a/packages/app-store/telli/index.ts b/packages/app-store/telli/index.ts new file mode 100644 index 00000000000000..d7f36022040096 --- /dev/null +++ b/packages/app-store/telli/index.ts @@ -0,0 +1 @@ +export * as api from "./api"; diff --git a/packages/app-store/telli/package.json b/packages/app-store/telli/package.json new file mode 100644 index 00000000000000..bde74dc481ef2f --- /dev/null +++ b/packages/app-store/telli/package.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://json.schemastore.org/package.json", + "private": true, + "name": "@calcom/telli", + "version": "0.0.0", + "main": "./index.ts", + "dependencies": { + "@calcom/lib": "*" + }, + "devDependencies": { + "@calcom/types": "*" + }, + "description": "telli AI agents reach your customers, make calls independently & enhance your customer experience - fully integrated into Cal.com." +} diff --git a/packages/app-store/telli/static/1.jpg b/packages/app-store/telli/static/1.jpg new file mode 100644 index 00000000000000..faa8d06d100758 Binary files /dev/null and b/packages/app-store/telli/static/1.jpg differ diff --git a/packages/app-store/telli/static/2.jpg b/packages/app-store/telli/static/2.jpg new file mode 100644 index 00000000000000..44c616aeb49aa2 Binary files /dev/null and b/packages/app-store/telli/static/2.jpg differ diff --git a/packages/app-store/telli/static/3.jpg b/packages/app-store/telli/static/3.jpg new file mode 100644 index 00000000000000..228992f006e7c2 Binary files /dev/null and b/packages/app-store/telli/static/3.jpg differ diff --git a/packages/app-store/telli/static/4.jpg b/packages/app-store/telli/static/4.jpg new file mode 100644 index 00000000000000..5425c480eff8b7 Binary files /dev/null and b/packages/app-store/telli/static/4.jpg differ diff --git a/packages/app-store/telli/static/5.jpg b/packages/app-store/telli/static/5.jpg new file mode 100644 index 00000000000000..1592180dc43f3b Binary files /dev/null and b/packages/app-store/telli/static/5.jpg differ diff --git a/packages/app-store/telli/static/icon-dark.svg b/packages/app-store/telli/static/icon-dark.svg new file mode 100644 index 00000000000000..dd1fca782229f3 --- /dev/null +++ b/packages/app-store/telli/static/icon-dark.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/packages/app-store/zoho-bigin/lib/CrmService.ts b/packages/app-store/zoho-bigin/lib/CrmService.ts index d556ad853e7bec..05907a747548ec 100644 --- a/packages/app-store/zoho-bigin/lib/CrmService.ts +++ b/packages/app-store/zoho-bigin/lib/CrmService.ts @@ -155,7 +155,7 @@ export default class BiginCrmService implements CRM { /*** * Finds existing Zoho Bigin Contact record based on email address. Returns a list of contacts objects that matched. */ - async getContacts(emails: string | string[]) { + async getContacts({ emails }: { emails: string | string[] }) { const token = await this.auth.getToken(); const emailsArray = Array.isArray(emails) ? emails : [emails]; @@ -288,6 +288,10 @@ export default class BiginCrmService implements CRM { async listCalendars(_event?: CalendarEvent): Promise { return Promise.resolve([]); } + + getAppOptions() { + console.log("No options implemented"); + } } const toISO8601String = (date: Date) => { diff --git a/packages/app-store/zohocrm/lib/CrmService.ts b/packages/app-store/zohocrm/lib/CrmService.ts index 21929a6989cf71..a1d498d06b181a 100644 --- a/packages/app-store/zohocrm/lib/CrmService.ts +++ b/packages/app-store/zohocrm/lib/CrmService.ts @@ -91,7 +91,7 @@ export default class ZohoCrmCrmService implements CRM { }); } - async getContacts(emails: string | string[]) { + async getContacts({ emails }: { emails: string | string[] }) { const auth = await this.auth; await auth.getToken(); const emailsArray = Array.isArray(emails) ? emails : [emails]; @@ -289,4 +289,8 @@ export default class ZohoCrmCrmService implements CRM { await auth.getToken(); return await this.deleteMeeting(uid); } + + getAppOptions() { + console.log("No options implemented"); + } } diff --git a/packages/core/EventManager.ts b/packages/core/EventManager.ts index 40799a2c308247..c8e6ed3f47c3ce 100644 --- a/packages/core/EventManager.ts +++ b/packages/core/EventManager.ts @@ -100,7 +100,7 @@ export default class EventManager { calendarCredentials: CredentialPayload[]; videoCredentials: CredentialPayload[]; crmCredentials: CredentialPayload[]; - appOptions: AppOptions; + appOptions?: z.infer; /** * Takes an array of credentials and initializes a new instance of the EventManager. @@ -132,7 +132,7 @@ export default class EventManager { (cred) => cred.type.endsWith("_crm") || cred.type.endsWith("_other_calendar") ); - this.appOptions = this.generateAppOptions(eventTypeAppMetadata); + this.appOptions = eventTypeAppMetadata; } /** @@ -969,29 +969,32 @@ export default class EventManager { const createdEvents = []; const uid = getUid(event); for (const credential of this.crmCredentials) { - const crm = new CrmManager(credential); + const currentAppOption = this.getAppOptionsFromEventMetadata(credential); + + const crm = new CrmManager(credential, currentAppOption); let success = true; - const skipContactCreation = this.appOptions.crm.skipContactCreation.includes(credential.appId || ""); - const createdEvent = await crm.createEvent(event, skipContactCreation).catch((error) => { + const createdEvent = await crm.createEvent(event, currentAppOption).catch((error) => { success = false; log.warn(`Error creating crm event for ${credential.type}`, error); }); - createdEvents.push({ - type: credential.type, - appName: credential.appId || "", - uid, - success, - createdEvent: { - id: createdEvent?.id || "", + if (createdEvent) { + createdEvents.push({ type: credential.type, + appName: credential.appId || "", + uid, + success, + createdEvent: { + id: createdEvent?.id || "", + type: credential.type, + credentialId: credential.id, + }, + id: createdEvent?.id || "", + originalEvent: event, credentialId: credential.id, - }, - id: createdEvent?.id || "", - originalEvent: event, - credentialId: credential.id, - }); + }); + } } return createdEvents; } @@ -1031,20 +1034,10 @@ export default class EventManager { } } - private generateAppOptions(eventTypeAppMetadata?: z.infer) { - const appOptions: AppOptions = { - crm: { - skipContactCreation: [], - }, - }; - - if (eventTypeAppMetadata) { - for (const key in eventTypeAppMetadata) { - const app = eventTypeAppMetadata[key as keyof typeof eventTypeAppMetadata]; - if (app?.skipContactCreation) appOptions.crm.skipContactCreation.push(key); - } - } + private getAppOptionsFromEventMetadata(credential: CredentialPayload) { + if (!this.appOptions || !credential.appId) return {}; - return appOptions; + if (credential.appId in this.appOptions) + return this.appOptions[credential.appId as keyof typeof this.appOptions]; } } diff --git a/packages/core/crmManager/crmManager.ts b/packages/core/crmManager/crmManager.ts index 23864fedb86891..835142effe71d6 100644 --- a/packages/core/crmManager/crmManager.ts +++ b/packages/core/crmManager/crmManager.ts @@ -8,13 +8,15 @@ const log = logger.getSubLogger({ prefix: ["CrmManager"] }); export default class CrmManager { crmService: CRM | null | undefined = null; credential: CredentialPayload; - constructor(credential: CredentialPayload) { + appOptions: any; + constructor(credential: CredentialPayload, appOptions?: any) { this.credential = credential; + this.appOptions = appOptions; } private async getCrmService(credential: CredentialPayload) { if (this.crmService) return this.crmService; - const crmService = await getCrm(credential); + const crmService = await getCrm(credential, this.appOptions); this.crmService = crmService; if (this.crmService === null) { @@ -25,10 +27,11 @@ export default class CrmManager { return crmService; } - public async createEvent(event: CalendarEvent, skipContactCreation?: boolean) { + public async createEvent(event: CalendarEvent, appOptions?: any) { const crmService = await this.getCrmService(this.credential); + const { skipContactCreation } = crmService?.getAppOptions(); // First see if the attendees already exist in the crm - let contacts = (await this.getContacts(event.attendees.map((a) => a.email))) || []; + let contacts = (await this.getContacts({ emails: event.attendees.map((a) => a.email) })) || []; // Ensure that all attendees are in the crm if (contacts.length == event.attendees.length) { return await crmService?.createEvent(event, contacts); @@ -54,9 +57,13 @@ export default class CrmManager { return await crmService?.deleteEvent(uid); } - public async getContacts(emailOrEmails: string | string[], includeOwner?: boolean) { + public async getContacts(params: { + emails: string | string[]; + includeOwner?: boolean; + forRoundRobinSkip?: boolean; + }) { const crmService = await this.getCrmService(this.credential); - const contacts = await crmService?.getContacts(emailOrEmails, includeOwner); + const contacts = await crmService?.getContacts(params); return contacts; } diff --git a/packages/embeds/embed-core/playground.ts b/packages/embeds/embed-core/playground.ts index 35f4d855f942be..35af9372fd7d66 100644 --- a/packages/embeds/embed-core/playground.ts +++ b/packages/embeds/embed-core/playground.ts @@ -474,7 +474,7 @@ if (only === "all" || only == "ns:monthView") { //@ts-ignore { elementOrSelector: "#cal-booking-place-monthView .place", - calLink: "pro/paid", + calLink: "free/30min", config: { iframeAttrs: { id: "cal-booking-place-monthView-iframe", @@ -499,7 +499,7 @@ if (only === "all" || only == "ns:weekView") { //@ts-ignore { elementOrSelector: "#cal-booking-place-weekView .place", - calLink: "pro/paid", + calLink: "free/30min", config: { iframeAttrs: { id: "cal-booking-place-weekView-iframe", @@ -528,7 +528,7 @@ if (only === "all" || only == "ns:columnView") { //@ts-ignore { elementOrSelector: "#cal-booking-place-columnView .place", - calLink: "pro/paid", + calLink: "free/30min", config: { iframeAttrs: { id: "cal-booking-place-columnView-iframe", diff --git a/packages/features/additionalTimezones/additionalTimezones.json b/packages/features/additionalTimezones/additionalTimezones.json new file mode 100644 index 00000000000000..5549cfb9dd2d9f --- /dev/null +++ b/packages/features/additionalTimezones/additionalTimezones.json @@ -0,0 +1,64 @@ +{ + "timezones": [ + { + "name": "Eastern Time - US & Canada", + "identifier": "America/New_York" + }, + { + "name": "Pacific Time - US & Canada", + "identifier": "America/Los_Angeles" + }, + { + "name": "Central Time - US & Canada", + "identifier": "America/Chicago" + }, + { + "name": "Mountain Time - US & Canada", + "identifier": "America/Denver" + }, + { + "name": "Atlantic Time - Canada", + "identifier": "America/Halifax" + }, + { + "name": "Eastern European Time", + "identifier": "Europe/Bucharest" + }, + { + "name": "Central European Time", + "identifier": "Europe/Berlin" + }, + { + "name": "Western European Time", + "identifier": "Europe/London" + }, + { + "name": "Australian Eastern Time", + "identifier": "Australia/Sydney" + }, + { + "name": "Japan Standard Time", + "identifier": "Asia/Tokyo" + }, + { + "name": "India Standard Time", + "identifier": "Asia/Kolkata" + }, + { + "name": "Gulf Standard Time", + "identifier": "Asia/Dubai" + }, + { + "name": "South Africa Standard Time", + "identifier": "Africa/Johannesburg" + }, + { + "name": "Brazil Time", + "identifier": "America/Sao_Paulo" + }, + { + "name": "Hawaii-Aleutian Standard Time", + "identifier": "Pacific/Honolulu" + } + ] +} diff --git a/packages/features/additionalTimezones/additionalTimezones.ts b/packages/features/additionalTimezones/additionalTimezones.ts new file mode 100644 index 00000000000000..84f15c9d846186 --- /dev/null +++ b/packages/features/additionalTimezones/additionalTimezones.ts @@ -0,0 +1,10 @@ +import * as additionalTimezones from "./additionalTimezones.json"; + +export interface Timezone { + name: string; + identifier: string; +} + +export const timezones: Timezone[] = additionalTimezones.timezones; + +export default additionalTimezones; diff --git a/packages/features/bookings/Booker/Booker.tsx b/packages/features/bookings/Booker/Booker.tsx index bdd2eb10c912da..2af7953dde3765 100644 --- a/packages/features/bookings/Booker/Booker.tsx +++ b/packages/features/bookings/Booker/Booker.tsx @@ -259,6 +259,8 @@ const BookerComponent = ({ return null; } + const shouldShowMeta = !hideEventTypeDetails; + return ( <> {event.data && !isPlatform ? : <>} @@ -327,7 +329,7 @@ const BookerComponent = ({ )} )} - {!hideEventTypeDetails && ( + {shouldShowMeta && ( { const { data: query, pushItemToKey, removeItemByKeyAndValue, removeAllQueryParams } = useFilterQuery(); const [searchText, setSearchText] = useState(""); - const members = trpc.viewer.teams.listMembers.useQuery({}); + const members = trpc.viewer.teams.legacyListMembers.useQuery({}); const filteredMembers = members?.data ?.filter((member) => member.accepted) diff --git a/packages/features/bookings/lib/book-event-form/booking-to-mutation-input-mapper.tsx b/packages/features/bookings/lib/book-event-form/booking-to-mutation-input-mapper.tsx index 1a80c0570dcc3d..d2ed62b7d58525 100644 --- a/packages/features/bookings/lib/book-event-form/booking-to-mutation-input-mapper.tsx +++ b/packages/features/bookings/lib/book-event-form/booking-to-mutation-input-mapper.tsx @@ -2,7 +2,6 @@ import { v4 as uuidv4 } from "uuid"; import dayjs from "@calcom/dayjs"; import { getRoutedTeamMemberIdsFromSearchParams } from "@calcom/lib/bookings/getRoutedTeamMemberIdsFromSearchParams"; -import { fromEntriesWithDuplicateKeys } from "@calcom/lib/fromEntriesWithDuplicateKeys"; import { parseRecurringDates } from "@calcom/lib/parse-dates"; import type { BookerEvent, BookingCreateBody, RecurringBookingCreateBody } from "../../types"; diff --git a/packages/features/bookings/lib/handleNewBooking.ts b/packages/features/bookings/lib/handleNewBooking.ts index 16d23f890c1c87..58ea737248028c 100644 --- a/packages/features/bookings/lib/handleNewBooking.ts +++ b/packages/features/bookings/lib/handleNewBooking.ts @@ -12,6 +12,7 @@ import { OrganizerDefaultConferencingAppType, getLocationValueForDB, } from "@calcom/app-store/locations"; +import { DailyLocationType } from "@calcom/app-store/locations"; import { getAppFromSlug } from "@calcom/app-store/utils"; import EventManager from "@calcom/core/EventManager"; import { getEventName } from "@calcom/core/event"; @@ -88,6 +89,7 @@ import { getSeatedBooking } from "./handleNewBooking/getSeatedBooking"; import { getVideoCallDetails } from "./handleNewBooking/getVideoCallDetails"; import { handleAppsStatus } from "./handleNewBooking/handleAppsStatus"; import { loadAndValidateUsers } from "./handleNewBooking/loadAndValidateUsers"; +import { scheduleNoShowTriggers } from "./handleNewBooking/scheduleNoShowTriggers"; import type { Invitee, IEventTypePaymentCredentialType, @@ -1654,6 +1656,21 @@ async function handler( loggerWithEventDetails.error("Error while scheduling workflow reminders", JSON.stringify({ error })); } + try { + if (isConfirmedByDefault && (booking.location === DailyLocationType || booking.location?.trim() === "")) { + await scheduleNoShowTriggers({ + booking: { startTime: booking.startTime, id: booking.id }, + triggerForUser, + organizerUser: { id: organizerUser.id }, + eventTypeId, + teamId, + orgId, + }); + } + } catch (error) { + loggerWithEventDetails.error("Error while scheduling no show triggers", JSON.stringify({ error })); + } + // booking successful req.statusCode = 201; diff --git a/packages/features/bookings/lib/handleNewBooking/loadAndValidateUsers.ts b/packages/features/bookings/lib/handleNewBooking/loadAndValidateUsers.ts index 6380ec73145644..e51c5e5b6eb566 100644 --- a/packages/features/bookings/lib/handleNewBooking/loadAndValidateUsers.ts +++ b/packages/features/bookings/lib/handleNewBooking/loadAndValidateUsers.ts @@ -39,7 +39,13 @@ export async function loadAndValidateUsers({ routedTeamMemberIds, contactOwnerEmail, }: InputProps): Promise { - let users: Users = await loadUsers({ eventType, dynamicUserList, req, routedTeamMemberIds, contactOwnerEmail }); + let users: Users = await loadUsers({ + eventType, + dynamicUserList, + req, + routedTeamMemberIds, + contactOwnerEmail, + }); const isDynamicAllowed = !users.some((user) => !user.allowDynamicBooking); if (!isDynamicAllowed && !eventTypeId) { logger.warn({ diff --git a/packages/features/bookings/lib/handleNewBooking/scheduleNoShowTriggers.ts b/packages/features/bookings/lib/handleNewBooking/scheduleNoShowTriggers.ts new file mode 100644 index 00000000000000..8c22c18b46c0de --- /dev/null +++ b/packages/features/bookings/lib/handleNewBooking/scheduleNoShowTriggers.ts @@ -0,0 +1,92 @@ +import dayjs from "@calcom/dayjs"; +import tasker from "@calcom/features/tasker"; +import getWebhooks from "@calcom/features/webhooks/lib/getWebhooks"; +import { WebhookTriggerEvents } from "@calcom/prisma/enums"; + +type ScheduleNoShowTriggersArgs = { + booking: { + startTime: Date; + id: number; + }; + triggerForUser: number | true | null; + organizerUser: { id: number }; + eventTypeId: number; + teamId?: number | null; + orgId?: number | null; +}; + +export const scheduleNoShowTriggers = async (args: ScheduleNoShowTriggersArgs) => { + const { booking, triggerForUser, organizerUser, eventTypeId, teamId, orgId } = args; + // Add task for automatic no show in cal video + const noShowPromises: Promise[] = []; + + const subscribersHostsNoShowStarted = await getWebhooks({ + userId: triggerForUser ? organizerUser.id : null, + eventTypeId, + triggerEvent: WebhookTriggerEvents.AFTER_HOSTS_CAL_VIDEO_NO_SHOW, + teamId, + orgId, + }); + + noShowPromises.push( + ...subscribersHostsNoShowStarted.map((webhook) => { + if (booking?.startTime && webhook.time && webhook.timeUnit) { + const scheduledAt = dayjs(booking.startTime) + .add(webhook.time, webhook.timeUnit.toLowerCase() as dayjs.ManipulateType) + .toDate(); + return tasker.create( + "triggerHostNoShowWebhook", + { + triggerEvent: WebhookTriggerEvents.AFTER_HOSTS_CAL_VIDEO_NO_SHOW, + bookingId: booking.id, + // Prevents null values from being serialized + webhook: { ...webhook, time: webhook.time, timeUnit: webhook.timeUnit }, + }, + { scheduledAt } + ); + } + return Promise.resolve(); + }) + ); + + const subscribersGuestsNoShowStarted = await getWebhooks({ + userId: triggerForUser ? organizerUser.id : null, + eventTypeId, + triggerEvent: WebhookTriggerEvents.AFTER_GUESTS_CAL_VIDEO_NO_SHOW, + teamId, + orgId, + }); + + noShowPromises.push( + ...subscribersGuestsNoShowStarted.map((webhook) => { + if (booking?.startTime && webhook.time && webhook.timeUnit) { + const scheduledAt = dayjs(booking.startTime) + .add(webhook.time, webhook.timeUnit.toLowerCase() as dayjs.ManipulateType) + .toDate(); + + return tasker.create( + "triggerGuestNoShowWebhook", + { + triggerEvent: WebhookTriggerEvents.AFTER_GUESTS_CAL_VIDEO_NO_SHOW, + bookingId: booking.id, + // Prevents null values from being serialized + webhook: { ...webhook, time: webhook.time, timeUnit: webhook.timeUnit }, + }, + { scheduledAt } + ); + } + + return Promise.resolve(); + }) + ); + + await Promise.all(noShowPromises); + + // TODO: Support no show workflows + // const workflowHostsNoShow = workflows.filter( + // (workflow) => workflow.trigger === WebhookTriggerEvents.AFTER_HOSTS_CAL_VIDEO_NO_SHOW + // ); + // const workflowGuestsNoShow = workflows.filter( + // (workflow) => workflow.trigger === WebhookTriggerEvents.AFTER_GUESTS_CAL_VIDEO_NO_SHOW + // ); +}; diff --git a/packages/features/ee/sso/page/teams-sso-view.tsx b/packages/features/ee/sso/page/teams-sso-view.tsx index 695197f0aeba37..118d78d612747f 100644 --- a/packages/features/ee/sso/page/teams-sso-view.tsx +++ b/packages/features/ee/sso/page/teams-sso-view.tsx @@ -23,7 +23,7 @@ const SAMLSSO = () => { data: team, isPending, error, - } = trpc.viewer.teams.getMinimal.useQuery( + } = trpc.viewer.teams.get.useQuery( { teamId }, { enabled: !!teamId, diff --git a/packages/features/ee/teams/components/AddNewTeamMembers.tsx b/packages/features/ee/teams/components/AddNewTeamMembers.tsx index 13b900d0fde3b4..a682a25b8a8ac4 100644 --- a/packages/features/ee/teams/components/AddNewTeamMembers.tsx +++ b/packages/features/ee/teams/components/AddNewTeamMembers.tsx @@ -1,10 +1,11 @@ +import { keepPreviousData } from "@tanstack/react-query"; import { useSession } from "next-auth/react"; import { useRouter } from "next/navigation"; -import { useEffect, useState } from "react"; +import { useEffect, useState, useMemo } from "react"; import { useOrgBranding } from "@calcom/features/ee/organizations/context/provider"; import InviteLinkSettingsModal from "@calcom/features/ee/teams/components/InviteLinkSettingsModal"; -import MemberInvitationModal from "@calcom/features/ee/teams/components/MemberInvitationModal"; +import { MemberInvitationModalWithoutMembers } from "@calcom/features/ee/teams/components/MemberInvitationModal"; import { classNames } from "@calcom/lib"; import { APP_NAME } from "@calcom/lib/constants"; import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams"; @@ -23,11 +24,7 @@ import { UserAvatar, } from "@calcom/ui"; -type TeamMember = RouterOutputs["viewer"]["teams"]["get"]["members"][number]; - -type FormValues = { - members: TeamMember[]; -}; +type TeamMember = RouterOutputs["viewer"]["teams"]["listMembers"]["members"][number]; const AddNewTeamMembers = ({ isOrg = false }: { isOrg?: boolean }) => { const searchParams = useCompatSearchParams(); @@ -49,29 +46,14 @@ const AddNewTeamMembers = ({ isOrg = false }: { isOrg?: boolean }) => { if (session.status === "loading" || !teamQuery.data) return ; - return ( - - ); + return ; }; -export const AddNewTeamMembersForm = ({ - defaultValues, - teamId, - isOrg, -}: { - defaultValues: FormValues; - teamId: number; - isOrg?: boolean; -}) => { +export const AddNewTeamMembersForm = ({ teamId, isOrg }: { teamId: number; isOrg?: boolean }) => { const searchParams = useCompatSearchParams(); - const { t, i18n } = useLocale(); + const { t } = useLocale(); const router = useRouter(); - const utils = trpc.useUtils(); const orgBranding = useOrgBranding(); const showDialog = searchParams?.get("inviteModal") === "true"; @@ -89,7 +71,24 @@ export const AddNewTeamMembersForm = ({ } ); - const inviteMemberMutation = trpc.viewer.teams.inviteMember.useMutation(); + const { data, fetchNextPage, isFetchingNextPage, hasNextPage } = + trpc.viewer.teams.listMembers.useInfiniteQuery( + { + limit: 10, + teamId, + }, + { + enabled: !!teamId, + getNextPageParam: (lastPage) => lastPage.nextCursor, + placeholderData: keepPreviousData, + refetchOnWindowFocus: true, + refetchOnMount: true, + staleTime: 0, + } + ); + + const flatData = useMemo(() => data?.pages?.flatMap((page) => page.members) ?? [], [data]) as TeamMember[]; + const totalFetched = flatData.length; const publishTeamMutation = trpc.viewer.teams.publish.useMutation({ onSuccess(data) { @@ -103,25 +102,34 @@ export const AddNewTeamMembersForm = ({ return ( <>
- {defaultValues.members.length > 0 && ( -
    - {defaultValues.members.map((member, index) => ( - - ))} -
+
    + {flatData.map((member, index) => ( + + ))} +
+ {totalFetched && ( +
+ +
)}
@@ -129,53 +137,16 @@ export const AddNewTeamMembersForm = ({ ) : ( <> - setMemberInviteModal(false)} - onSubmit={(values, resetFields) => { - inviteMemberMutation.mutate( - { - teamId, - language: i18n.language, - role: values.role, - usernameOrEmail: values.emailOrUsername, - }, - { - onSuccess: async (data) => { - await utils.viewer.teams.get.invalidate(); - setMemberInviteModal(false); - resetFields(); - if (Array.isArray(data.usernameOrEmail)) { - showToast( - t("email_invite_team_bulk", { - userCount: data.numUsersInvited, - }), - "success" - ); - } else { - showToast( - t("email_invite_team", { - email: data.usernameOrEmail, - }), - "success" - ); - } - }, - onError: (error) => { - showToast(error.message, "error"); - }, - } - ); - }} + hideInvitationModal={() => setMemberInviteModal(false)} onSettingsOpen={() => { setMemberInviteModal(false); setInviteLinkSettingsModal(true); }} - members={defaultValues.members} /> {team?.inviteToken && ( ; -type ConnectedAppsType = { - name: string | null; - logo: string | null; - externalId: string | null; - app: { slug: string; categories: AppCategories[] } | null; -}; - export function EditMemberSheet({ state, dispatch, @@ -108,10 +100,10 @@ export function EditMemberSheet({ const changeRoleMutation = trpc.viewer.teams.changeMemberRole.useMutation({ onMutate: async ({ teamId, memberId, role }) => { - await utils.viewer.teams.lazyLoadMembers.cancel(); - const previousValue = utils.viewer.teams.lazyLoadMembers.getInfiniteData({ + await utils.viewer.teams.listMembers.cancel(); + const previousValue = utils.viewer.teams.listMembers.getInfiniteData({ limit: 10, - teamId: teamId, + teamId, searchTerm: undefined, }); @@ -125,7 +117,6 @@ export function EditMemberSheet({ setRole(role); setMutationLoading(false); await utils.viewer.teams.get.invalidate(); - await utils.viewer.teams.lazyLoadMembers.invalidate(); await utils.viewer.organizations.listMembers.invalidate(); showToast(t("profile_updated_successfully"), "success"); setEditMode(false); diff --git a/packages/features/ee/teams/components/EventTypesList.tsx b/packages/features/ee/teams/components/EventTypesList.tsx index 71c0c508042d80..77a273807a7e6e 100644 --- a/packages/features/ee/teams/components/EventTypesList.tsx +++ b/packages/features/ee/teams/components/EventTypesList.tsx @@ -21,7 +21,7 @@ import { Icon, } from "@calcom/ui"; -import type { User } from "./MemberListItem"; +import type { User } from "./MemberList"; interface Props { table: Table; @@ -44,7 +44,7 @@ export function EventTypesList({ table, teamId }: Props) { "success" ); - utils.viewer.teams.lazyLoadMembers.invalidate(); + utils.viewer.teams.listMembers.invalidate(); utils.viewer.eventTypes.invalidate(); // Clear the selected values @@ -62,7 +62,7 @@ export function EventTypesList({ table, teamId }: Props) { "success" ); - utils.viewer.teams.lazyLoadMembers.invalidate(); + utils.viewer.teams.listMembers.invalidate(); utils.viewer.eventTypes.invalidate(); // Clear the selected values diff --git a/packages/features/ee/teams/components/InviteLinkSettingsModal.tsx b/packages/features/ee/teams/components/InviteLinkSettingsModal.tsx index 2efab7f0afab94..13aa1752551ec4 100644 --- a/packages/features/ee/teams/components/InviteLinkSettingsModal.tsx +++ b/packages/features/ee/teams/components/InviteLinkSettingsModal.tsx @@ -26,7 +26,6 @@ export default function InviteLinkSettingsModal(props: InvitationLinkSettingsMod showToast(t("invite_link_deleted"), "success"); trpcContext.viewer.teams.get.invalidate(); trpcContext.viewer.teams.list.invalidate(); - trpcContext.viewer.teams.getMinimal.invalidate(); props.onExit(); }, onError: (e) => { @@ -39,7 +38,6 @@ export default function InviteLinkSettingsModal(props: InvitationLinkSettingsMod showToast(t("invite_link_updated"), "success"); trpcContext.viewer.teams.get.invalidate(); trpcContext.viewer.teams.list.invalidate(); - trpcContext.viewer.teams.getMinimal.invalidate(); }, onError: (e) => { showToast(e.message, "error"); diff --git a/packages/features/ee/teams/components/MakeTeamPrivateSwitch.tsx b/packages/features/ee/teams/components/MakeTeamPrivateSwitch.tsx index 71e62f76ca26ef..f11fc2b15bad17 100644 --- a/packages/features/ee/teams/components/MakeTeamPrivateSwitch.tsx +++ b/packages/features/ee/teams/components/MakeTeamPrivateSwitch.tsx @@ -25,7 +25,6 @@ const MakeTeamPrivateSwitch = ({ }, async onSuccess() { await utils.viewer.teams.get.invalidate(); - await utils.viewer.teams.getMinimal.invalidate(); showToast(t(isOrg ? "your_org_updated_successfully" : "your_team_updated_successfully"), "success"); }, }); diff --git a/packages/features/ee/teams/components/MemberChangeRoleModal.tsx b/packages/features/ee/teams/components/MemberChangeRoleModal.tsx index 45198f70d2465e..955e6f1861a9dc 100644 --- a/packages/features/ee/teams/components/MemberChangeRoleModal.tsx +++ b/packages/features/ee/teams/components/MemberChangeRoleModal.tsx @@ -24,7 +24,7 @@ export const updateRoleInCache = ({ role: MembershipRole; memberId: number; }) => { - utils.viewer.teams.lazyLoadMembers.setInfiniteData( + utils.viewer.teams.listMembers.setInfiniteData( { limit: 10, teamId, @@ -91,10 +91,10 @@ export default function MemberChangeRoleModal(props: { const changeRoleMutation = trpc.viewer.teams.changeMemberRole.useMutation({ onMutate: async ({ teamId, memberId, role }) => { - await utils.viewer.teams.lazyLoadMembers.cancel(); - const previousValue = utils.viewer.teams.lazyLoadMembers.getInfiniteData({ + await utils.viewer.teams.listMembers.cancel(); + const previousValue = utils.viewer.teams.listMembers.getInfiniteData({ limit: 10, - teamId: teamId, + teamId, searchTerm: props.searchTerm, }); diff --git a/packages/features/ee/teams/components/MemberInvitationModal.tsx b/packages/features/ee/teams/components/MemberInvitationModal.tsx index 868fac9d98efef..2a22fce340a058 100644 --- a/packages/features/ee/teams/components/MemberInvitationModal.tsx +++ b/packages/features/ee/teams/components/MemberInvitationModal.tsx @@ -469,7 +469,8 @@ export const MemberInvitationModalWithoutMembers = ({ teamId, token, onSettingsOpen, -}: { + ...props +}: Partial & { hideInvitationModal: () => void; showMemberInvitationModal: boolean; teamId: number; @@ -495,6 +496,7 @@ export const MemberInvitationModalWithoutMembers = ({ return ( { await utils.viewer.teams.get.invalidate(); - await utils.viewer.teams.lazyLoadMembers.invalidate(); + await utils.viewer.teams.listMembers.invalidate(); await utils.viewer.organizations.getMembers.invalidate(); hideInvitationModal(); diff --git a/packages/features/ee/teams/components/MemberListItem.tsx b/packages/features/ee/teams/components/MemberList.tsx similarity index 98% rename from packages/features/ee/teams/components/MemberListItem.tsx rename to packages/features/ee/teams/components/MemberList.tsx index b23cd347981bdc..8f37738a57a830 100644 --- a/packages/features/ee/teams/components/MemberListItem.tsx +++ b/packages/features/ee/teams/components/MemberList.tsx @@ -41,12 +41,12 @@ import { EventTypesList } from "./EventTypesList"; import TeamAvailabilityModal from "./TeamAvailabilityModal"; interface Props { - team: NonNullable; + team: NonNullable; isOrgAdminOrOwner: boolean | undefined; setShowMemberInvitationModal: Dispatch>; } -export type User = RouterOutputs["viewer"]["teams"]["lazyLoadMembers"]["members"][number]; +export type User = RouterOutputs["viewer"]["teams"]["listMembers"]["members"][number]; const checkIsOrg = (team: Props["team"]) => { return team.isOrganization; @@ -111,7 +111,7 @@ function reducer(state: State, action: Action): State { } } -export default function MemberListItem(props: Props) { +export default function MemberList(props: Props) { const { t, i18n } = useLocale(); const { data: session } = useSession(); const utils = trpc.useUtils(); @@ -124,7 +124,7 @@ export default function MemberListItem(props: Props) { const { copyToClipboard, isCopied } = useCopy(); const debouncedSearchTerm = useDebounce(searchTerm, 500); - const { data, isPending, fetchNextPage, isFetching } = trpc.viewer.teams.lazyLoadMembers.useInfiniteQuery( + const { data, isPending, fetchNextPage, isFetching } = trpc.viewer.teams.listMembers.useInfiniteQuery( { limit: 10, searchTerm: debouncedSearchTerm, @@ -151,7 +151,7 @@ export default function MemberListItem(props: Props) { teamId: number; searchTerm: string; }) => { - utils.viewer.teams.lazyLoadMembers.setInfiniteData( + utils.viewer.teams.listMembers.setInfiniteData( { limit: 10, teamId, @@ -178,8 +178,8 @@ export default function MemberListItem(props: Props) { const removeMemberMutation = trpc.viewer.teams.removeMember.useMutation({ onMutate: async ({ teamIds }) => { - await utils.viewer.teams.lazyLoadMembers.cancel(); - const previousValue = utils.viewer.teams.lazyLoadMembers.getInfiniteData({ + await utils.viewer.teams.listMembers.cancel(); + const previousValue = utils.viewer.teams.listMembers.getInfiniteData({ limit: 10, teamId: teamIds[0], searchTerm: searchTerm, diff --git a/packages/features/ee/teams/components/TeamAvailabilityModal.tsx b/packages/features/ee/teams/components/TeamAvailabilityModal.tsx index f485f144a181bd..a39d3003589a8c 100644 --- a/packages/features/ee/teams/components/TeamAvailabilityModal.tsx +++ b/packages/features/ee/teams/components/TeamAvailabilityModal.tsx @@ -12,8 +12,8 @@ import { Avatar, DatePicker, Label, Select, TimezoneSelect } from "@calcom/ui"; import TeamAvailabilityTimes from "./TeamAvailabilityTimes"; interface Props { - team?: RouterOutputs["viewer"]["teams"]["getMinimal"]; - member?: RouterOutputs["viewer"]["teams"]["lazyLoadMembers"]["members"][number]; + team?: RouterOutputs["viewer"]["teams"]["get"]; + member?: RouterOutputs["viewer"]["teams"]["listMembers"]["members"][number]; } export default function TeamAvailabilityModal(props: Props) { diff --git a/packages/features/ee/teams/components/TeamEventTypeForm.tsx b/packages/features/ee/teams/components/TeamEventTypeForm.tsx index f80bf1d8a0842c..1c3e5461422532 100644 --- a/packages/features/ee/teams/components/TeamEventTypeForm.tsx +++ b/packages/features/ee/teams/components/TeamEventTypeForm.tsx @@ -27,10 +27,7 @@ export const TeamEventTypeForm = ({ }: props) => { const { t } = useLocale(); const orgBranding = useOrgBranding(); - const { data: team } = trpc.viewer.teams.getMinimal.useQuery( - { teamId, isOrg: false }, - { enabled: !!teamId } - ); + const { data: team } = trpc.viewer.teams.get.useQuery({ teamId, isOrg: false }, { enabled: !!teamId }); const urlPrefix = orgBranding?.fullDomain ?? process.env.NEXT_PUBLIC_WEBSITE_URL; const { form, createMutation, isManagedEventType } = useCreateEventType(onSuccessMutation, onErrorMutation); diff --git a/packages/features/ee/teams/pages/team-appearance-view.tsx b/packages/features/ee/teams/pages/team-appearance-view.tsx index dcdaa53349e5ca..fb3bfd11c9f716 100644 --- a/packages/features/ee/teams/pages/team-appearance-view.tsx +++ b/packages/features/ee/teams/pages/team-appearance-view.tsx @@ -23,7 +23,7 @@ type BrandColorsFormValues = { darkBrandColor: string; }; -type ProfileViewProps = { team: RouterOutputs["viewer"]["teams"]["getMinimal"] } & { isAppDir?: boolean }; +type ProfileViewProps = { team: RouterOutputs["viewer"]["teams"]["get"] } & { isAppDir?: boolean }; const ProfileView = ({ team, isAppDir }: ProfileViewProps) => { const { t } = useLocale(); @@ -193,7 +193,7 @@ const ProfileViewWrapper = ({ isAppDir }: { isAppDir?: boolean }) => { data: team, isPending, error, - } = trpc.viewer.teams.getMinimal.useQuery( + } = trpc.viewer.teams.get.useQuery( { teamId: Number(params.id) }, { enabled: !!Number(params.id), diff --git a/packages/features/ee/teams/pages/team-booking-limits-view.tsx b/packages/features/ee/teams/pages/team-booking-limits-view.tsx index 892bde1c9ea743..2f3359b49b4a6b 100644 --- a/packages/features/ee/teams/pages/team-booking-limits-view.tsx +++ b/packages/features/ee/teams/pages/team-booking-limits-view.tsx @@ -16,7 +16,7 @@ import type { RouterOutputs } from "@calcom/trpc/react"; import type { IntervalLimit } from "@calcom/types/Calendar"; import { Button, CheckboxField, Form, SettingsToggle, showToast } from "@calcom/ui"; -type ProfileViewProps = { team: RouterOutputs["viewer"]["teams"]["getMinimal"] }; +type ProfileViewProps = { team: RouterOutputs["viewer"]["teams"]["get"] }; const BookingLimitsView = ({ team }: ProfileViewProps) => { const { t } = useLocale(); @@ -146,7 +146,7 @@ const BookingLimitsViewWrapper = () => { data: team, isPending, error, - } = trpc.viewer.teams.getMinimal.useQuery( + } = trpc.viewer.teams.get.useQuery( { teamId: Number(params.id) }, { enabled: !!Number(params.id), diff --git a/packages/features/ee/teams/pages/team-members-view.tsx b/packages/features/ee/teams/pages/team-members-view.tsx index b4695cdcbb5f60..1d6b6ef865a7be 100644 --- a/packages/features/ee/teams/pages/team-members-view.tsx +++ b/packages/features/ee/teams/pages/team-members-view.tsx @@ -14,7 +14,7 @@ import DisableTeamImpersonation from "../components/DisableTeamImpersonation"; import InviteLinkSettingsModal from "../components/InviteLinkSettingsModal"; import MakeTeamPrivateSwitch from "../components/MakeTeamPrivateSwitch"; import { MemberInvitationModalWithoutMembers } from "../components/MemberInvitationModal"; -import MemberListItem from "../components/MemberListItem"; +import MemberList from "../components/MemberList"; import TeamInviteList from "../components/TeamInviteList"; const MembersView = ({ isAppDir }: { isAppDir?: boolean }) => { @@ -32,7 +32,7 @@ const MembersView = ({ isAppDir }: { isAppDir?: boolean }) => { data: team, isPending: isTeamsLoading, error: teamError, - } = trpc.viewer.teams.getMinimal.useQuery( + } = trpc.viewer.teams.get.useQuery( { teamId }, { enabled: !!teamId, @@ -88,7 +88,7 @@ const MembersView = ({ isAppDir }: { isAppDir?: boolean }) => { {((team?.isPrivate && isAdmin) || !team?.isPrivate || isOrgAdminOrOwner) && team && ( <> - { data: team, isPending, error, - } = trpc.viewer.teams.getMinimal.useQuery( + } = trpc.viewer.teams.get.useQuery( { teamId }, { enabled: !!teamId, @@ -262,7 +262,7 @@ const ProfileView = ({ isAppDir }: { isAppDir?: boolean }) => { ); }; -export type TeamProfileFormProps = { team: RouterOutputs["viewer"]["teams"]["getMinimal"] }; +export type TeamProfileFormProps = { team: RouterOutputs["viewer"]["teams"]["get"] }; const TeamProfileForm = ({ team }: TeamProfileFormProps) => { const utils = trpc.useUtils(); diff --git a/packages/features/ee/users/components/UsersTable.tsx b/packages/features/ee/users/components/UsersTable.tsx index 291d95008f3a23..c647d7e183569a 100644 --- a/packages/features/ee/users/components/UsersTable.tsx +++ b/packages/features/ee/users/components/UsersTable.tsx @@ -116,6 +116,7 @@ function UsersTableBare() { })), }; }); + utils.viewer.admin.listPaginated.invalidate(); }, }); @@ -187,14 +188,16 @@ function UsersTableBare() { />
- {user.name} - /{user.username} - {user.locked && ( - - - - )} -
+
+ {user.name} + /{user.username} + {user.locked && ( + + + + )} +
+
{user.email}
diff --git a/packages/features/ee/workflows/components/TimeTimeUnitInput.tsx b/packages/features/ee/workflows/components/TimeTimeUnitInput.tsx index da4f8e6fe73f42..7561d8250a7b01 100644 --- a/packages/features/ee/workflows/components/TimeTimeUnitInput.tsx +++ b/packages/features/ee/workflows/components/TimeTimeUnitInput.tsx @@ -1,5 +1,5 @@ import { useState } from "react"; -import type { UseFormReturn } from "react-hook-form"; +import { useFormContext } from "react-hook-form"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { TimeUnit } from "@calcom/prisma/enums"; @@ -13,27 +13,23 @@ import { TextField, } from "@calcom/ui"; -import type { FormValues } from "../pages/workflow"; - const TIME_UNITS = [TimeUnit.DAY, TimeUnit.HOUR, TimeUnit.MINUTE] as const; type Props = { - form: UseFormReturn; disabled: boolean; }; const TimeUnitAddonSuffix = ({ DropdownItems, timeUnitOptions, - form, }: { - form: UseFormReturn; DropdownItems: JSX.Element; timeUnitOptions: { [x: string]: string }; }) => { // because isDropdownOpen already triggers a render cycle we can use getValues() // instead of watch() function - const timeUnit = form.getValues("timeUnit"); + const form = useFormContext(); + const timeUnit = form.getValues("timeUnit") ?? TimeUnit.MINUTE; const [isDropdownOpen, setIsDropdownOpen] = useState(false); return ( @@ -51,7 +47,8 @@ const TimeUnitAddonSuffix = ({ }; export const TimeTimeUnitInput = (props: Props) => { - const { form } = props; + const form = useFormContext(); + const { t } = useLocale(); const timeUnitOptions = TIME_UNITS.reduce((acc, option) => { acc[option] = t(`${option.toLowerCase()}_timeUnit`); @@ -70,7 +67,6 @@ export const TimeTimeUnitInput = (props: Props) => { {...form.register("time", { valueAsNumber: true })} addOnSuffix={ @@ -80,7 +76,7 @@ export const TimeTimeUnitInput = (props: Props) => { key={index} type="button" onClick={() => { - form.setValue("timeUnit", timeUnit); + form.setValue("timeUnit", timeUnit, { shouldDirty: true }); }}> {timeUnitOptions[timeUnit]} diff --git a/packages/features/ee/workflows/components/WorkflowStepContainer.tsx b/packages/features/ee/workflows/components/WorkflowStepContainer.tsx index 4744d946dd1cfc..5dd72e8d5fc6ca 100644 --- a/packages/features/ee/workflows/components/WorkflowStepContainer.tsx +++ b/packages/features/ee/workflows/components/WorkflowStepContainer.tsx @@ -1,4 +1,5 @@ import type { WorkflowStep } from "@prisma/client"; +import { type TFunction } from "i18next"; import type { Dispatch, SetStateAction } from "react"; import { useEffect, useRef, useState } from "react"; import type { UseFormReturn } from "react-hook-form"; @@ -69,6 +70,17 @@ type WorkflowStepProps = { readOnly: boolean; }; +const getTimeSectionText = (trigger: WorkflowTriggerEvents, t: TFunction) => { + const triggerMap: Partial> = { + [WorkflowTriggerEvents.AFTER_EVENT]: "how_long_after", + [WorkflowTriggerEvents.BEFORE_EVENT]: "how_long_before", + [WorkflowTriggerEvents.AFTER_HOSTS_CAL_VIDEO_NO_SHOW]: "how_long_after_hosts_no_show", + [WorkflowTriggerEvents.AFTER_GUESTS_CAL_VIDEO_NO_SHOW]: "how_long_after_guests_no_show", + }; + if (!triggerMap[trigger]) return null; + return t(triggerMap[trigger]!); +}; + export default function WorkflowStepContainer(props: WorkflowStepProps) { const { t } = useLocale(); const utils = trpc.useUtils(); @@ -114,14 +126,7 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) { : false ); - const [showTimeSection, setShowTimeSection] = useState( - form.getValues("trigger") === WorkflowTriggerEvents.BEFORE_EVENT || - form.getValues("trigger") === WorkflowTriggerEvents.AFTER_EVENT - ); - - const [showTimeSectionAfter, setShowTimeSectionAfter] = useState( - form.getValues("trigger") === WorkflowTriggerEvents.AFTER_EVENT - ); + const [timeSectionText, setTimeSectionText] = useState(getTimeSectionText(form.getValues("trigger"), t)); const { data: actionOptions } = trpc.viewer.workflows.getWorkflowActionOptions.useQuery(); const triggerOptions = getWorkflowTriggerOptions(t); @@ -312,21 +317,21 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) { onChange={(val) => { if (val) { form.setValue("trigger", val.value); - if ( - val.value === WorkflowTriggerEvents.BEFORE_EVENT || - val.value === WorkflowTriggerEvents.AFTER_EVENT - ) { - setShowTimeSection(true); - if (val.value === WorkflowTriggerEvents.AFTER_EVENT) { - setShowTimeSectionAfter(true); + const newTimeSectionText = getTimeSectionText(val.value, t); + if (newTimeSectionText) { + setTimeSectionText(newTimeSectionText); + if ( + val.value === WorkflowTriggerEvents.AFTER_HOSTS_CAL_VIDEO_NO_SHOW || + val.value === WorkflowTriggerEvents.AFTER_GUESTS_CAL_VIDEO_NO_SHOW + ) { + form.setValue("time", 5); + form.setValue("timeUnit", TimeUnit.MINUTE); } else { - setShowTimeSectionAfter(false); + form.setValue("time", 24); + form.setValue("timeUnit", TimeUnit.HOUR); } - form.setValue("time", 24); - form.setValue("timeUnit", TimeUnit.HOUR); } else { - setShowTimeSection(false); - setShowTimeSectionAfter(false); + setTimeSectionText(null); form.unregister("time"); form.unregister("timeUnit"); } @@ -338,10 +343,10 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) { ); }} /> - {showTimeSection && ( + {!!timeSectionText && (
- - + + {!props.readOnly && (
diff --git a/packages/features/ee/workflows/lib/constants.ts b/packages/features/ee/workflows/lib/constants.ts index c127b471353f33..1445a1de6b0f0f 100644 --- a/packages/features/ee/workflows/lib/constants.ts +++ b/packages/features/ee/workflows/lib/constants.ts @@ -6,6 +6,8 @@ export const WORKFLOW_TRIGGER_EVENTS = [ WorkflowTriggerEvents.NEW_EVENT, WorkflowTriggerEvents.AFTER_EVENT, WorkflowTriggerEvents.RESCHEDULE_EVENT, + WorkflowTriggerEvents.AFTER_HOSTS_CAL_VIDEO_NO_SHOW, + WorkflowTriggerEvents.AFTER_GUESTS_CAL_VIDEO_NO_SHOW, ] as const; export const WORKFLOW_ACTIONS = [ diff --git a/packages/features/ee/workflows/lib/getOptions.ts b/packages/features/ee/workflows/lib/getOptions.ts index f8d74275d652c6..d015eef14a86ed 100644 --- a/packages/features/ee/workflows/lib/getOptions.ts +++ b/packages/features/ee/workflows/lib/getOptions.ts @@ -1,6 +1,7 @@ import type { TFunction } from "next-i18next"; import type { WorkflowActions } from "@calcom/prisma/enums"; +import { WorkflowTriggerEvents } from "@calcom/prisma/enums"; import { isSMSOrWhatsappAction, isWhatsappAction, isEmailToAttendeeAction } from "./actionHelperFunctions"; import { @@ -24,7 +25,14 @@ export function getWorkflowActionOptions(t: TFunction, isTeamsPlan?: boolean, is } export function getWorkflowTriggerOptions(t: TFunction) { - return WORKFLOW_TRIGGER_EVENTS.map((triggerEvent) => { + // TODO: remove this after workflows are supported + const filterdWorkflowTriggerEvents = WORKFLOW_TRIGGER_EVENTS.filter( + (event) => + event !== WorkflowTriggerEvents.AFTER_HOSTS_CAL_VIDEO_NO_SHOW && + event !== WorkflowTriggerEvents.AFTER_GUESTS_CAL_VIDEO_NO_SHOW + ); + + return filterdWorkflowTriggerEvents.map((triggerEvent) => { const triggerString = t(`${triggerEvent.toLowerCase()}_trigger`); return { label: triggerString.charAt(0).toUpperCase() + triggerString.slice(1), value: triggerEvent }; diff --git a/packages/features/eventtypes/components/tabs/advanced/EventAdvancedTab.tsx b/packages/features/eventtypes/components/tabs/advanced/EventAdvancedTab.tsx index 08c1f89e86e2a2..fbf65ee3a02aa9 100644 --- a/packages/features/eventtypes/components/tabs/advanced/EventAdvancedTab.tsx +++ b/packages/features/eventtypes/components/tabs/advanced/EventAdvancedTab.tsx @@ -1,9 +1,8 @@ -import dynamic from "next/dynamic"; import { useState } from "react"; import { Controller, useFormContext } from "react-hook-form"; import type { z } from "zod"; -import type { EventAdvancedWebWrapperProps } from "@calcom/atoms/event-types/wrappers/EventAdvancedWebWrapper"; +import { useAtomsContext, useIsPlatform } from "@calcom/atoms/monorepo"; import type { EventNameObjectType } from "@calcom/core/event"; import { getEventName } from "@calcom/core/event"; import getLocationsOptionsForSelect from "@calcom/features/bookings/lib/getLocationOptionsForSelect"; @@ -14,7 +13,7 @@ import { allowDisablingHostConfirmationEmails, } from "@calcom/features/ee/workflows/lib/allowDisablingStandardEmails"; import { MultiplePrivateLinksController } from "@calcom/features/eventtypes/components"; -import type { FormValues } from "@calcom/features/eventtypes/lib/types"; +import type { FormValues, EventTypeSetupProps } from "@calcom/features/eventtypes/lib/types"; import { FormBuilder } from "@calcom/features/form-builder/FormBuilder"; import type { fieldSchema } from "@calcom/features/form-builder/schema"; import type { EditableSchema } from "@calcom/features/form-builder/schema"; @@ -39,21 +38,26 @@ import { SettingsToggle, Switch, TextField, - showToast, ColorPicker, } from "@calcom/ui"; +import CustomEventTypeModal from "./CustomEventTypeModal"; import { DisableAllEmailsSetting } from "./DisableAllEmailsSetting"; import RequiresConfirmationController from "./RequiresConfirmationController"; type BookingField = z.infer; -const CustomEventTypeModal = dynamic(() => import("./CustomEventTypeModal")); +export type EventAdvancedBaseProps = Pick & { + user?: Partial< + Pick + >; + isUserLoading?: boolean; + showToast: (message: string, variant: "success" | "warning" | "error") => void; +}; -export type EventAdvancedTabProps = EventAdvancedWebWrapperProps & { +export type EventAdvancedTabProps = EventAdvancedBaseProps & { calendarsQueryData?: RouterOutputs["viewer"]["connectedCalendars"]; - user?: RouterOutputs["viewer"]["me"]; - isUserLoading?: boolean; + showBookerLayoutSelector: boolean; }; export const EventAdvancedTab = ({ @@ -62,7 +66,11 @@ export const EventAdvancedTab = ({ calendarsQueryData, user, isUserLoading, + showToast, + showBookerLayoutSelector, }: EventAdvancedTabProps) => { + const isPlatform = useIsPlatform(); + const platformContext = useAtomsContext(); const formMethods = useFormContext(); const { t } = useLocale(); const [showEventNameTip, setShowEventNameTip] = useState(false); @@ -169,7 +177,7 @@ export const EventAdvancedTab = ({ const displayDestinationCalendarSelector = !!calendarsQueryData?.connectedCalendars?.length && (!team || isChildrenManagedEventType); - const verifiedSecondaryEmails = [ + let verifiedSecondaryEmails = [ { label: user?.email || "", value: -1, @@ -178,6 +186,20 @@ export const EventAdvancedTab = ({ .filter((secondaryEmail) => !!secondaryEmail.emailVerified) .map((secondaryEmail) => ({ label: secondaryEmail.email, value: secondaryEmail.id })), ]; + + const removePlatformClientIdFromEmail = (email: string, clientId: string) => + email.replace(`+${clientId}`, ""); + + let userEmail = user?.email || ""; + + if (isPlatform && platformContext.clientId) { + verifiedSecondaryEmails = verifiedSecondaryEmails.map((email) => ({ + ...email, + label: removePlatformClientIdFromEmail(email.label, platformContext.clientId), + })); + userEmail = removePlatformClientIdFromEmail(userEmail, platformContext.clientId); + } + const selectedSecondaryEmailId = formMethods.getValues("secondaryEmailId") || -1; return (
@@ -257,7 +279,7 @@ export const EventAdvancedTab = ({ placeholder={ selectedSecondaryEmailId === -1 && ( - {t("default")} {user?.email || ""} + {t("default")} {userEmail} ) } @@ -275,13 +297,15 @@ export const EventAdvancedTab = ({ )}
- + {showBookerLayoutSelector && ( + + )}
)} /> - { - return ( - { - if (!e) { - formMethods.setValue("multiplePrivateLinks", [], { shouldDirty: true }); - } else { - formMethods.setValue( - "multiplePrivateLinks", - [generateHashedLink(formMethods.getValues("users")[0]?.id ?? team?.id)], - { shouldDirty: true } - ); - } - setMultiplePrivateLinksVisible(e); - }}> - {!isManagedEventType && ( -
- -
- )} -
- ); - }} - /> + {!isPlatform && ( + { + return ( + { + if (!e) { + formMethods.setValue("multiplePrivateLinks", [], { shouldDirty: true }); + } else { + formMethods.setValue( + "multiplePrivateLinks", + [generateHashedLink(formMethods.getValues("users")[0]?.id ?? team?.id)], + { shouldDirty: true } + ); + } + setMultiplePrivateLinksVisible(e); + }}> + {!isManagedEventType && ( +
+ +
+ )} +
+ ); + }} + /> + )} ( diff --git a/packages/features/eventtypes/components/tabs/webhooks/EventWebhooksTab.tsx b/packages/features/eventtypes/components/tabs/webhooks/EventWebhooksTab.tsx index 869899e7b47027..0c62c2c09b4fb6 100644 --- a/packages/features/eventtypes/components/tabs/webhooks/EventWebhooksTab.tsx +++ b/packages/features/eventtypes/components/tabs/webhooks/EventWebhooksTab.tsx @@ -80,6 +80,8 @@ export const EventWebhooksTab = ({ eventType }: Pick diff --git a/packages/features/form-builder/FormBuilder.tsx b/packages/features/form-builder/FormBuilder.tsx index 0bc8f52b20a54b..0abe51b487d771 100644 --- a/packages/features/form-builder/FormBuilder.tsx +++ b/packages/features/form-builder/FormBuilder.tsx @@ -7,7 +7,7 @@ import type { z } from "zod"; import { classNames } from "@calcom/lib"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { md } from "@calcom/lib/markdownIt"; -import { markdownToSafeHTML } from "@calcom/lib/markdownToSafeHTML"; +import { markdownToSafeHTMLClient } from "@calcom/lib/markdownToSafeHTMLClient"; import turndown from "@calcom/lib/turndownService"; import { Badge, @@ -153,7 +153,7 @@ export const FormBuilder = function FormBuilder({ } if (fieldsThatSupportLabelAsSafeHtml.includes(field.type)) { - field = { ...field, labelAsSafeHtml: markdownToSafeHTML(field.label ?? "") }; + field = { ...field, labelAsSafeHtml: markdownToSafeHTMLClient(field.label ?? "") }; } const numOptions = options?.length ?? 0; const firstOptionInput = @@ -692,7 +692,7 @@ function FieldLabel({ field }: { field: RhfFormField }) { ); diff --git a/packages/features/settings/BookerLayoutSelector.tsx b/packages/features/settings/BookerLayoutSelector.tsx index e1c3f0b02c7347..5686dd6e09fc68 100644 --- a/packages/features/settings/BookerLayoutSelector.tsx +++ b/packages/features/settings/BookerLayoutSelector.tsx @@ -34,7 +34,7 @@ type BookerLayoutSelectorProps = { isLoading?: boolean; isDisabled?: boolean; isOuterBorder?: boolean; - user?: RouterOutputs["viewer"]["me"]; + user?: Partial>; isUserLoading?: boolean; }; @@ -104,7 +104,7 @@ type BookerLayoutFieldsProps = { showUserSettings: boolean; isDark?: boolean; isOuterBorder?: boolean; - user?: RouterOutputs["viewer"]["me"]; + user?: Partial>; isUserLoading?: boolean; }; diff --git a/packages/features/settings/outOfOffice/CreateNewOutOfOfficeEntryButton.tsx b/packages/features/settings/outOfOffice/CreateNewOutOfOfficeEntryButton.tsx index 782fe3724b6685..fc9de2d2cd8e5a 100644 --- a/packages/features/settings/outOfOffice/CreateNewOutOfOfficeEntryButton.tsx +++ b/packages/features/settings/outOfOffice/CreateNewOutOfOfficeEntryButton.tsx @@ -25,7 +25,7 @@ const CreateNewOutOfOfficeEntry = () => { <>
); }} /> + + {showTimeSection && ( +
+ + +
+ )} + 0) { const promise = bookings.map((booking) => { return addedEventTriggers.map((triggerEvent) => { + if ( + triggerEvent === WebhookTriggerEvents.AFTER_GUESTS_CAL_VIDEO_NO_SHOW || + triggerEvent === WebhookTriggerEvents.AFTER_HOSTS_CAL_VIDEO_NO_SHOW + ) + return Promise.resolve(); + scheduleTrigger({ booking, subscriberUrl: webhook.subscriberUrl, subscriber: webhook, triggerEvent }); }); }); diff --git a/packages/features/webhooks/pages/webhook-edit-view.tsx b/packages/features/webhooks/pages/webhook-edit-view.tsx index a067d4be5bb178..d8c3ed4c14c0d8 100644 --- a/packages/features/webhooks/pages/webhook-edit-view.tsx +++ b/packages/features/webhooks/pages/webhook-edit-view.tsx @@ -88,6 +88,8 @@ export function EditWebhookView({ webhook }: { webhook?: WebhookProps }) { active: values.active, payloadTemplate: values.payloadTemplate, secret: values.secret, + time: values.time, + timeUnit: values.timeUnit, }); }} apps={installedApps?.items.map((app) => app.slug)} diff --git a/packages/features/webhooks/pages/webhook-new-view.tsx b/packages/features/webhooks/pages/webhook-new-view.tsx index de24bfa327b879..90a9b1a8158499 100644 --- a/packages/features/webhooks/pages/webhook-new-view.tsx +++ b/packages/features/webhooks/pages/webhook-new-view.tsx @@ -82,6 +82,8 @@ export const NewWebhookView = () => { active: values.active, payloadTemplate: values.payloadTemplate, secret: values.secret, + time: values.time, + timeUnit: values.timeUnit, teamId, platform, }); diff --git a/packages/lib/dailyApiFetcher.ts b/packages/lib/dailyApiFetcher.ts new file mode 100644 index 00000000000000..5e50538ea7b037 --- /dev/null +++ b/packages/lib/dailyApiFetcher.ts @@ -0,0 +1,15 @@ +import { getDailyAppKeys } from "@calcom/app-store/dailyvideo/lib/getDailyAppKeys"; +import { handleErrorsJson } from "@calcom/lib/errors"; + +export const fetcher = async (endpoint: string, init?: RequestInit | undefined) => { + const { api_key } = await getDailyAppKeys(); + return fetch(`https://api.daily.co/v1${endpoint}`, { + method: "GET", + headers: { + Authorization: `Bearer ${api_key}`, + "Content-Type": "application/json", + ...init?.headers, + }, + ...init, + }).then(handleErrorsJson); +}; diff --git a/packages/lib/event-types/getEventTypesPublic.ts b/packages/lib/event-types/getEventTypesPublic.ts index 628de9e6b98e2b..3e786c20d7c40f 100644 --- a/packages/lib/event-types/getEventTypesPublic.ts +++ b/packages/lib/event-types/getEventTypesPublic.ts @@ -1,6 +1,8 @@ +import type { Prisma } from "@prisma/client"; + import logger from "@calcom/lib/logger"; import prisma from "@calcom/prisma"; -import { baseEventTypeSelect } from "@calcom/prisma/selects"; +import type { baseEventTypeSelect } from "@calcom/prisma/selects"; import { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils"; import { markdownToSafeHTML } from "../markdownToSafeHTML"; @@ -21,42 +23,46 @@ export async function getEventTypesPublic(userId: number) { })); } +type BaseEventType = Prisma.EventTypeGetPayload<{ + select: typeof baseEventTypeSelect; +}>; + +type RawEventType = BaseEventType & { + metadata: Record | null; +}; + const getEventTypesWithHiddenFromDB = async (userId: number) => { - const eventTypes = await prisma.eventType.findMany({ - where: { - AND: [ - { - teamId: null, - }, - { - OR: [ - { - userId, - }, - { - users: { - some: { - id: userId, - }, - }, - }, - ], - }, - ], - }, - orderBy: [ - { - position: "desc", - }, - { - id: "asc", - }, - ], - select: { - ...baseEventTypeSelect, - metadata: true, - }, - }); + const eventTypes = await prisma.$queryRaw` + SELECT data."id", data."title", data."description", data."length", data."schedulingType"::text, + data."recurringEvent", data."slug", data."hidden", data."price", data."currency", + data."lockTimeZoneToggleOnBookingPage", data."requiresConfirmation", data."requiresBookerEmailVerification", + data."metadata" + FROM ( + SELECT "EventType"."id", "EventType"."title", "EventType"."description", + "EventType"."position", "EventType"."length", "EventType"."schedulingType"::text, + "EventType"."recurringEvent", "EventType"."slug", "EventType"."hidden", + "EventType"."price", "EventType"."currency", + "EventType"."lockTimeZoneToggleOnBookingPage", "EventType"."requiresConfirmation", + "EventType"."requiresBookerEmailVerification", "EventType"."metadata" + FROM "EventType" + WHERE "EventType"."teamId" IS NULL AND "EventType"."userId" = ${userId} + UNION + SELECT "EventType"."id", "EventType"."title", "EventType"."description", + "EventType"."position", "EventType"."length", "EventType"."schedulingType"::text, + "EventType"."recurringEvent", "EventType"."slug", "EventType"."hidden", + "EventType"."price", "EventType"."currency", + "EventType"."lockTimeZoneToggleOnBookingPage", "EventType"."requiresConfirmation", + "EventType"."requiresBookerEmailVerification", "EventType"."metadata" + FROM "EventType" + WHERE "EventType"."teamId" IS NULL + AND "EventType"."id" IN ( + SELECT "uet1"."A" FROM "_user_eventtype" AS "uet1" + INNER JOIN "users" AS "u1" ON "u1"."id" = "uet1"."B" + WHERE "u1"."id" = ${userId} AND "uet1"."A" IS NOT NULL + ) + ) data + ORDER BY data."position" DESC, data."id" ASC`; + // map and filter metadata, exclude eventType entirely when faulty metadata is found. // report error to exception so we don't lose the error. return eventTypes.reduce((eventTypes, eventType) => { diff --git a/packages/lib/fromEntriesWithDuplicateKeys.ts b/packages/lib/fromEntriesWithDuplicateKeys.ts index 6cc389215f6b98..11bf425fd2a5e6 100644 --- a/packages/lib/fromEntriesWithDuplicateKeys.ts +++ b/packages/lib/fromEntriesWithDuplicateKeys.ts @@ -21,4 +21,4 @@ export function fromEntriesWithDuplicateKeys(entries: IterableIterator<[string, } } return result; -} \ No newline at end of file +} diff --git a/packages/lib/getLabelValueMapFromResponses.ts b/packages/lib/getLabelValueMapFromResponses.ts index 9473c8f26bade2..5779b17327966d 100644 --- a/packages/lib/getLabelValueMapFromResponses.ts +++ b/packages/lib/getLabelValueMapFromResponses.ts @@ -1,6 +1,6 @@ import type z from "zod"; -import { TITLE_FIELD } from "@calcom/features/bookings/lib/SystemField"; +import { TITLE_FIELD, SMS_REMINDER_NUMBER_FIELD } from "@calcom/features/bookings/lib/SystemField"; import type { bookingResponse } from "@calcom/features/bookings/lib/getBookingResponsesSchema"; import type { CalendarEvent } from "@calcom/types/Calendar"; @@ -17,6 +17,9 @@ export default function getLabelValueMapFromResponses( if (!!responses?.[TITLE_FIELD] && !isDynamicEvent) { userFieldsResponses[TITLE_FIELD] = responses[TITLE_FIELD]; } + if (!!responses?.[SMS_REMINDER_NUMBER_FIELD] && !isDynamicEvent) { + userFieldsResponses[SMS_REMINDER_NUMBER_FIELD] = responses[SMS_REMINDER_NUMBER_FIELD]; + } for (const [, value] of Object.entries(userFieldsResponses)) { if (!value.label || (!isOrganizer && value.isHidden)) { diff --git a/packages/lib/markdownToSafeHTMLClient.ts b/packages/lib/markdownToSafeHTMLClient.ts new file mode 100644 index 00000000000000..a377608f60c8b8 --- /dev/null +++ b/packages/lib/markdownToSafeHTMLClient.ts @@ -0,0 +1,30 @@ +import DOMPurify from "dompurify"; + +import { md } from "@calcom/lib/markdownIt"; + +if (typeof window == "undefined") { + console.warn( + "`markdownToSafeHTMLClient` should not be used on the server side. use markdownToSafeHTML instead" + ); +} + +export function markdownToSafeHTMLClient(markdown: string | null) { + if (!markdown) return ""; + + const html = md.render(markdown); + + const safeHTML = DOMPurify.sanitize(html); + + const safeHTMLWithListFormatting = safeHTML + .replace( + /
    /g, + "
      " + ) + .replace( + /
        /g, + "
          " + ) + .replace(/ { } return acc; }, {}); + + additionalTimezones.forEach((tz) => { + cityTimezones[tz.identifier] = tz.name; + }); + return cityTimezones || {}; }; diff --git a/packages/platform/atoms/connect/OAuthConnect.tsx b/packages/platform/atoms/connect/OAuthConnect.tsx index 99ec1e7e26d431..8c3e5d21d9abb5 100644 --- a/packages/platform/atoms/connect/OAuthConnect.tsx +++ b/packages/platform/atoms/connect/OAuthConnect.tsx @@ -75,6 +75,7 @@ export const OAuthConnect: FC< tooltip={tooltip ? tooltip : } tooltipSide={tooltipSide} tooltipOffset={10} + tooltipClassName="p-0 text-inherit bg-inherit" className={cn("", !isDisabled && "cursor-pointer", className)} onClick={() => { connect(); diff --git a/packages/platform/atoms/connect/apple/AppleConnect.tsx b/packages/platform/atoms/connect/apple/AppleConnect.tsx index 2d1d25bd4d7fdf..cba44f3ef615f1 100644 --- a/packages/platform/atoms/connect/apple/AppleConnect.tsx +++ b/packages/platform/atoms/connect/apple/AppleConnect.tsx @@ -93,6 +93,7 @@ export const AppleConnect: FC>> = ({ tooltip={tooltip ? tooltip : } tooltipSide={tooltipSide} tooltipOffset={10} + tooltipClassName="p-0 text-inherit bg-inherit" className={cn("", !isDisabled && "cursor-pointer", className)} onClick={() => setIsDialogOpen(true)}> {displayedLabel} diff --git a/packages/platform/atoms/event-types/hooks/usePlatformTabsNavigations.tsx b/packages/platform/atoms/event-types/hooks/usePlatformTabsNavigations.tsx index 32bac774a0d3fa..dfbaa1c21376ac 100644 --- a/packages/platform/atoms/event-types/hooks/usePlatformTabsNavigations.tsx +++ b/packages/platform/atoms/event-types/hooks/usePlatformTabsNavigations.tsx @@ -60,12 +60,14 @@ export const usePlatformTabsNavigations = ({ formMethods, eventType, team, tabs onClick: (tab) => { setCurrentTab(tab); }, + currentTab, }); if (!requirePayment) { navigation.splice(3, 0, { name: "recurring", onClick: () => setCurrentTab("recurring"), + isActive: currentTab === "recurring", href: `${url}?tabName=recurring`, icon: "repeat", info: `recurring_event_tab_description`, @@ -75,6 +77,7 @@ export const usePlatformTabsNavigations = ({ formMethods, eventType, team, tabs navigation.splice(1, 0, { name: "availability", onClick: () => setCurrentTab("availability"), + isActive: currentTab === "availability", href: `${url}?tabName=availability`, icon: "calendar", info: @@ -96,6 +99,7 @@ export const usePlatformTabsNavigations = ({ formMethods, eventType, team, tabs navigation.splice(2, 0, { name: "assignment", onClick: () => setCurrentTab("team"), + isActive: currentTab === "team", href: `${url}?tabName=team`, icon: "users", info: `${t(watchSchedulingType?.toLowerCase() ?? "")}${ @@ -133,15 +137,17 @@ type getNavigationProps = { tabs: PlatformTabs[]; url: string; onClick: (tab: PlatformTabs) => void; + currentTab: PlatformTabs; }; -function getNavigation({ length, multipleDuration, t, tabs, url, onClick }: getNavigationProps) { +function getNavigation({ length, multipleDuration, t, tabs, url, onClick, currentTab }: getNavigationProps) { const duration = multipleDuration?.map((duration) => ` ${duration}`) || length; const tabsNavigation: VerticalTabItemProps[] = []; tabs.includes("setup") && tabsNavigation.push({ name: "event_setup_tab_title", onClick: () => onClick("setup"), + isActive: currentTab === "setup", href: `${url}?tabName=setup`, icon: "link", info: `${duration} ${t("minute_timeUnit")}`, // TODO: Get this from props @@ -150,6 +156,7 @@ function getNavigation({ length, multipleDuration, t, tabs, url, onClick }: getN tabsNavigation.push({ name: "event_limit_tab_title", onClick: () => onClick("limits"), + isActive: currentTab === "limits", href: `${url}?tabName=limits`, icon: "clock", info: `event_limit_tab_description`, @@ -159,6 +166,7 @@ function getNavigation({ length, multipleDuration, t, tabs, url, onClick }: getN tabsNavigation.push({ name: "event_advanced_tab_title", onClick: () => onClick("advanced"), + isActive: currentTab === "advanced", href: `${url}?tabName=advanced`, icon: "sliders-vertical", info: `event_advanced_tab_description`, diff --git a/packages/platform/atoms/event-types/wrappers/EventAdvancedPlatformWrapper.tsx b/packages/platform/atoms/event-types/wrappers/EventAdvancedPlatformWrapper.tsx new file mode 100644 index 00000000000000..b669b030c4ec46 --- /dev/null +++ b/packages/platform/atoms/event-types/wrappers/EventAdvancedPlatformWrapper.tsx @@ -0,0 +1,17 @@ +import type { EventAdvancedBaseProps } from "@calcom/features/eventtypes/components/tabs/advanced/EventAdvancedTab"; +import { EventAdvancedTab } from "@calcom/features/eventtypes/components/tabs/advanced/EventAdvancedTab"; + +import { useConnectedCalendars } from "../../hooks/useConnectedCalendars"; + +const EventAdvancedPlatformWrapper = (props: EventAdvancedBaseProps) => { + const { data: connectedCalendarsQuery } = useConnectedCalendars({}); + return ( + + ); +}; + +export default EventAdvancedPlatformWrapper; diff --git a/packages/platform/atoms/event-types/wrappers/EventAdvancedWebWrapper.tsx b/packages/platform/atoms/event-types/wrappers/EventAdvancedWebWrapper.tsx index 0fa9f2da6864af..8b38718c74f0ae 100644 --- a/packages/platform/atoms/event-types/wrappers/EventAdvancedWebWrapper.tsx +++ b/packages/platform/atoms/event-types/wrappers/EventAdvancedWebWrapper.tsx @@ -1,25 +1,14 @@ +import type { EventAdvancedBaseProps } from "@calcom/features/eventtypes/components/tabs/advanced/EventAdvancedTab"; import { EventAdvancedTab } from "@calcom/features/eventtypes/components/tabs/advanced/EventAdvancedTab"; -import type { EventTypeSetupProps } from "@calcom/features/eventtypes/lib/types"; -import type { RouterOutputs } from "@calcom/trpc/react"; import { trpc } from "@calcom/trpc/react"; -export type EventAdvancedWebWrapperProps = Pick & { - loggedInUser?: RouterOutputs["viewer"]["me"]; - isLoggedInUserPending?: boolean; -}; - -const EventAdvancedWebWrapper = ({ - loggedInUser, - isLoggedInUserPending, - ...props -}: EventAdvancedWebWrapperProps) => { +const EventAdvancedWebWrapper = ({ ...props }: EventAdvancedBaseProps) => { const connectedCalendarsQuery = trpc.viewer.connectedCalendars.useQuery(); return ( ); }; diff --git a/packages/platform/atoms/event-types/wrappers/EventTypePlatformWrapper.tsx b/packages/platform/atoms/event-types/wrappers/EventTypePlatformWrapper.tsx index 9dbd993b7b1ecd..9eaff311d41a6a 100644 --- a/packages/platform/atoms/event-types/wrappers/EventTypePlatformWrapper.tsx +++ b/packages/platform/atoms/event-types/wrappers/EventTypePlatformWrapper.tsx @@ -10,6 +10,7 @@ import type { EventTypeSetupProps, FormValues, TabMap } from "@calcom/features/e import { useLocale } from "@calcom/lib/hooks/useLocale"; import { SchedulingType } from "@calcom/prisma/enums"; +import { useMe } from "../../hooks/useMe"; import { AtomsWrapper } from "../../src/components/atoms-wrapper"; import { useToast } from "../../src/components/ui/use-toast"; import { useAtomsEventTypeById, QUERY_KEY as ATOM_EVENT_TYPE_QUERY_KEY } from "../hooks/useAtomEventTypeById"; @@ -17,6 +18,7 @@ import { useAtomUpdateEventType } from "../hooks/useAtomUpdateEventType"; import { useEventTypeForm } from "../hooks/useEventTypeForm"; import { useHandleRouteChange } from "../hooks/useHandleRouteChange"; import { usePlatformTabsNavigations } from "../hooks/usePlatformTabsNavigations"; +import EventAdvancedPlatformWrapper from "./EventAdvancedPlatformWrapper"; import EventLimitsTabPlatformWrapper from "./EventLimitsTabPlatformWrapper"; import EventRecurringTabPlatformWrapper from "./EventRecurringTabPlatformWrapper"; import SetupTab from "./EventSetupTabPlatformWrapper"; @@ -42,6 +44,7 @@ const EventType = ({ const [pendingRoute, setPendingRoute] = useState(""); const { eventType, locationOptions, team, teamMembers, destinationCalendar } = props; const [slugExistsChildrenDialogOpen, setSlugExistsChildrenDialogOpen] = useState([]); + const { data: user, isLoading: isUserLoading } = useMe(); const updateMutation = useAtomUpdateEventType({ onSuccess: async () => { @@ -73,6 +76,10 @@ const EventType = ({ const { form, handleSubmit } = useEventTypeForm({ eventType, onSubmit: updateMutation.mutate }); const slug = form.watch("slug") ?? eventType.slug; + const showToast = (message: string, variant: "success" | "warning" | "error") => { + toast({ description: message }); + }; + const tabMap = { setup: tabs.includes("setup") ? ( , team: <>, + advanced: tabs.includes("advanced") ? ( + + ) : ( + <> + ), + limits: tabs.includes("limits") ? : <>, - advanced: <>, instant: <>, recurring: tabs.includes("recurring") ? ( diff --git a/packages/platform/atoms/event-types/wrappers/EventTypeWebWrapper.tsx b/packages/platform/atoms/event-types/wrappers/EventTypeWebWrapper.tsx index 1ddbfdbe2b461c..6ea31053a6cec5 100644 --- a/packages/platform/atoms/event-types/wrappers/EventTypeWebWrapper.tsx +++ b/packages/platform/atoms/event-types/wrappers/EventTypeWebWrapper.tsx @@ -250,8 +250,9 @@ const EventTypeWeb = ({ ), instant: , diff --git a/packages/prisma/migrations/20240920100549_add_daily_no_show/migration.sql b/packages/prisma/migrations/20240920100549_add_daily_no_show/migration.sql new file mode 100644 index 00000000000000..982ab9fc8dbcf5 --- /dev/null +++ b/packages/prisma/migrations/20240920100549_add_daily_no_show/migration.sql @@ -0,0 +1,10 @@ +-- AlterEnum +-- This migration adds more than one value to an enum. +-- With PostgreSQL versions 11 and earlier, this is not possible +-- in a single migration. This can be worked around by creating +-- multiple migrations, each migration adding only one value to +-- the enum. + + +ALTER TYPE "WorkflowTriggerEvents" ADD VALUE 'AFTER_HOSTS_CAL_VIDEO_NO_SHOW'; +ALTER TYPE "WorkflowTriggerEvents" ADD VALUE 'AFTER_GUESTS_CAL_VIDEO_NO_SHOW'; diff --git a/packages/prisma/migrations/20240920192534_add_no_show_daily_webhook_trigger/migration.sql b/packages/prisma/migrations/20240920192534_add_no_show_daily_webhook_trigger/migration.sql new file mode 100644 index 00000000000000..18c69325943248 --- /dev/null +++ b/packages/prisma/migrations/20240920192534_add_no_show_daily_webhook_trigger/migration.sql @@ -0,0 +1,10 @@ +-- AlterEnum +-- This migration adds more than one value to an enum. +-- With PostgreSQL versions 11 and earlier, this is not possible +-- in a single migration. This can be worked around by creating +-- multiple migrations, each migration adding only one value to +-- the enum. + + +ALTER TYPE "WebhookTriggerEvents" ADD VALUE 'AFTER_HOSTS_CAL_VIDEO_NO_SHOW'; +ALTER TYPE "WebhookTriggerEvents" ADD VALUE 'AFTER_GUESTS_CAL_VIDEO_NO_SHOW'; diff --git a/packages/prisma/migrations/20240920195815_add_time_unit_in_webhooks/migration.sql b/packages/prisma/migrations/20240920195815_add_time_unit_in_webhooks/migration.sql new file mode 100644 index 00000000000000..b041ff6de3ae73 --- /dev/null +++ b/packages/prisma/migrations/20240920195815_add_time_unit_in_webhooks/migration.sql @@ -0,0 +1,3 @@ +-- AlterTable +ALTER TABLE "Webhook" ADD COLUMN "time" INTEGER, +ADD COLUMN "timeUnit" "TimeUnit"; diff --git a/packages/prisma/migrations/20241010070020_add_active/migration.sql b/packages/prisma/migrations/20241010070020_add_active/migration.sql new file mode 100644 index 00000000000000..9203e22c9b1c9a --- /dev/null +++ b/packages/prisma/migrations/20241010070020_add_active/migration.sql @@ -0,0 +1,2 @@ +-- CreateIndex +CREATE INDEX "Webhook_active_idx" ON "Webhook"("active"); diff --git a/packages/prisma/migrations/20241010171846_add_eventtype_parent_id_index/migration.sql b/packages/prisma/migrations/20241010171846_add_eventtype_parent_id_index/migration.sql new file mode 100644 index 00000000000000..e96f204ef6f086 --- /dev/null +++ b/packages/prisma/migrations/20241010171846_add_eventtype_parent_id_index/migration.sql @@ -0,0 +1,2 @@ +-- CreateIndex +CREATE INDEX "EventType_parentId_idx" ON "EventType"("parentId"); diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index b01a81168eb76f..afb86fd9c0d515 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -160,6 +160,7 @@ model EventType { @@index([teamId]) @@index([scheduleId]) @@index([secondaryEmailId]) + @@index([parentId]) } model Credential { @@ -570,60 +571,60 @@ enum BookingStatus { } model Booking { - id Int @id @default(autoincrement()) - uid String @unique + id Int @id @default(autoincrement()) + uid String @unique // (optional) UID based on slot start/end time & email against duplicates - idempotencyKey String? @unique - user User? @relation(fields: [userId], references: [id], onDelete: Cascade) - userId Int? + idempotencyKey String? @unique + user User? @relation(fields: [userId], references: [id], onDelete: Cascade) + userId Int? // User's email at the time of booking /// @zod.email() - userPrimaryEmail String? - references BookingReference[] - eventType EventType? @relation(fields: [eventTypeId], references: [id]) - eventTypeId Int? - title String - description String? - customInputs Json? + userPrimaryEmail String? + references BookingReference[] + eventType EventType? @relation(fields: [eventTypeId], references: [id]) + eventTypeId Int? + title String + description String? + customInputs Json? /// @zod.custom(imports.bookingResponses) - responses Json? - startTime DateTime - endTime DateTime - attendees Attendee[] - location String? - createdAt DateTime @default(now()) - updatedAt DateTime? - status BookingStatus @default(ACCEPTED) - paid Boolean @default(false) - payment Payment[] - destinationCalendar DestinationCalendar? @relation(fields: [destinationCalendarId], references: [id]) - destinationCalendarId Int? - cancellationReason String? - rejectionReason String? - dynamicEventSlugRef String? - dynamicGroupSlugRef String? - rescheduled Boolean? - fromReschedule String? - recurringEventId String? - smsReminderNumber String? - workflowReminders WorkflowReminder[] - scheduledJobs String[] // scheduledJobs is deprecated, please use scheduledTriggers instead - seatsReferences BookingSeat[] + responses Json? + startTime DateTime + endTime DateTime + attendees Attendee[] + location String? + createdAt DateTime @default(now()) + updatedAt DateTime? + status BookingStatus @default(ACCEPTED) + paid Boolean @default(false) + payment Payment[] + destinationCalendar DestinationCalendar? @relation(fields: [destinationCalendarId], references: [id]) + destinationCalendarId Int? + cancellationReason String? + rejectionReason String? + dynamicEventSlugRef String? + dynamicGroupSlugRef String? + rescheduled Boolean? + fromReschedule String? + recurringEventId String? + smsReminderNumber String? + workflowReminders WorkflowReminder[] + scheduledJobs String[] // scheduledJobs is deprecated, please use scheduledTriggers instead + seatsReferences BookingSeat[] /// @zod.custom(imports.bookingMetadataSchema) - metadata Json? - isRecorded Boolean @default(false) - iCalUID String? @default("") - iCalSequence Int @default(0) - instantMeetingToken InstantMeetingToken? - rating Int? - ratingFeedback String? - noShowHost Boolean? @default(false) - scheduledTriggers WebhookScheduledTriggers[] - oneTimePassword String? @unique @default(uuid()) + metadata Json? + isRecorded Boolean @default(false) + iCalUID String? @default("") + iCalSequence Int @default(0) + instantMeetingToken InstantMeetingToken? + rating Int? + ratingFeedback String? + noShowHost Boolean? @default(false) + scheduledTriggers WebhookScheduledTriggers[] + oneTimePassword String? @unique @default(uuid()) /// @zod.email() - cancelledBy String? + cancelledBy String? /// @zod.email() - rescheduledBy String? + rescheduledBy String? routedFromRoutingFormReponse App_RoutingForms_FormResponse? @@index([eventTypeId]) @@ -767,6 +768,8 @@ enum WebhookTriggerEvents { INSTANT_MEETING RECORDING_TRANSCRIPTION_GENERATED OOO_CREATED + AFTER_HOSTS_CAL_VIDEO_NO_SHOW + AFTER_GUESTS_CAL_VIDEO_NO_SHOW } model Webhook { @@ -790,9 +793,12 @@ model Webhook { secret String? platform Boolean @default(false) scheduledTriggers WebhookScheduledTriggers[] + time Int? + timeUnit TimeUnit? @@unique([userId, subscriberUrl], name: "courseIdentifier") @@unique([platformOAuthClientId, subscriberUrl], name: "oauthclientwebhook") + @@index([active]) } model Impersonations { @@ -935,15 +941,16 @@ model App_RoutingForms_Form { } model App_RoutingForms_FormResponse { - id Int @id @default(autoincrement()) - formFillerId String @default(cuid()) - form App_RoutingForms_Form @relation(fields: [formId], references: [id], onDelete: Cascade) - formId String - response Json - createdAt DateTime @default(now()) - routedToBookingUid String? @unique + id Int @id @default(autoincrement()) + formFillerId String @default(cuid()) + form App_RoutingForms_Form @relation(fields: [formId], references: [id], onDelete: Cascade) + formId String + response Json + createdAt DateTime @default(now()) + routedToBookingUid String? @unique // We should not cascade delete the booking, because we want to keep the form response even if the routedToBooking is deleted - routedToBooking Booking? @relation(fields: [routedToBookingUid], references: [uid]) + routedToBooking Booking? @relation(fields: [routedToBookingUid], references: [uid]) + @@unique([formFillerId, formId]) @@index([formFillerId]) @@index([formId]) @@ -967,6 +974,8 @@ enum WorkflowTriggerEvents { NEW_EVENT AFTER_EVENT RESCHEDULE_EVENT + AFTER_HOSTS_CAL_VIDEO_NO_SHOW + AFTER_GUESTS_CAL_VIDEO_NO_SHOW } enum WorkflowActions { diff --git a/packages/prisma/zod/webhook.ts b/packages/prisma/zod/webhook.ts index 1e502ece7d9769..56558ddceb771f 100755 --- a/packages/prisma/zod/webhook.ts +++ b/packages/prisma/zod/webhook.ts @@ -1,6 +1,6 @@ import * as z from "zod" import * as imports from "../zod-utils" -import { WebhookTriggerEvents } from "@prisma/client" +import { WebhookTriggerEvents, TimeUnit } from "@prisma/client" import { CompleteUser, UserModel, CompleteTeam, TeamModel, CompleteEventType, EventTypeModel, CompletePlatformOAuthClient, PlatformOAuthClientModel, CompleteApp, AppModel, CompleteWebhookScheduledTriggers, WebhookScheduledTriggersModel } from "./index" export const _WebhookModel = z.object({ @@ -17,6 +17,8 @@ export const _WebhookModel = z.object({ appId: z.string().nullish(), secret: z.string().nullish(), platform: z.boolean(), + time: z.number().int().nullish(), + timeUnit: z.nativeEnum(TimeUnit).nullish(), }) export interface CompleteWebhook extends z.infer { diff --git a/packages/trpc/server/routers/viewer/teams/_router.tsx b/packages/trpc/server/routers/viewer/teams/_router.tsx index 2e93506469d9e6..7a647d36d4993c 100644 --- a/packages/trpc/server/routers/viewer/teams/_router.tsx +++ b/packages/trpc/server/routers/viewer/teams/_router.tsx @@ -8,15 +8,14 @@ import { ZCreateInputSchema } from "./create.schema"; import { ZCreateInviteInputSchema } from "./createInvite.schema"; import { ZDeleteInputSchema } from "./delete.schema"; import { ZDeleteInviteInputSchema } from "./deleteInvite.schema"; -import { ZGetInputSchema } from "./get.schema"; +import { ZGetSchema } from "./get.schema"; import { ZGetMemberAvailabilityInputSchema } from "./getMemberAvailability.schema"; import { ZGetMembershipbyUserInputSchema } from "./getMembershipbyUser.schema"; -import { ZGetMinimalSchema } from "./getMinimal.schema"; import { ZGetUserConnectedAppsInputSchema } from "./getUserConnectedApps.schema"; import { ZHasEditPermissionForUserSchema } from "./hasEditPermissionForUser.schema"; import { ZInviteMemberInputSchema } from "./inviteMember/inviteMember.schema"; import { ZInviteMemberByTokenSchemaInputSchema } from "./inviteMemberByToken.schema"; -import { ZLazyLoadMembersInputSchema } from "./lazyLoadMembers.schema"; +import { ZListMembersInputSchema as ZLegegacyListMembers } from "./legacyListMembers.schema"; import { ZGetListSchema } from "./list.schema"; import { ZListMembersInputSchema } from "./listMembers.schema"; import { hasTeamPlan } from "./procedures/hasTeamPlan"; @@ -34,15 +33,10 @@ const namespaced = (s: string) => `${NAMESPACE}.${s}`; export const viewerTeamsRouter = router({ // Retrieves team by id - get: authedProcedure.input(ZGetInputSchema).query(async (opts) => { + get: authedProcedure.input(ZGetSchema).query(async (opts) => { const handler = await importHandler(namespaced("get"), () => import("./get.handler")); return handler(opts); }), - // Returns team - getMinimal: authedProcedure.input(ZGetMinimalSchema).query(async (opts) => { - const handler = await importHandler(namespaced("getMinimal"), () => import("./getMinimal.handler")); - return handler(opts); - }), // Returns teams I a member of list: authedProcedure.input(ZGetListSchema).query(async (opts) => { const handler = await importHandler(namespaced("list"), () => import("./list.handler")); @@ -125,10 +119,10 @@ export const viewerTeamsRouter = router({ const handler = await importHandler(namespaced("listMembers"), () => import("./listMembers.handler")); return handler(opts); }), - lazyLoadMembers: authedProcedure.input(ZLazyLoadMembersInputSchema).query(async (opts) => { + legacyListMembers: authedProcedure.input(ZLegegacyListMembers).query(async (opts) => { const handler = await importHandler( - namespaced("lazyLoadMembers"), - () => import("./lazyLoadMembers.handler") + namespaced("legacyListMembers"), + () => import("./legacyListMembers.handler") ); return handler(opts); }), diff --git a/packages/trpc/server/routers/viewer/teams/getMinimal.handler.test.ts b/packages/trpc/server/routers/viewer/teams/get.handler.test.ts similarity index 90% rename from packages/trpc/server/routers/viewer/teams/getMinimal.handler.test.ts rename to packages/trpc/server/routers/viewer/teams/get.handler.test.ts index c726064dce00ff..a582d8bf9d2867 100644 --- a/packages/trpc/server/routers/viewer/teams/getMinimal.handler.test.ts +++ b/packages/trpc/server/routers/viewer/teams/get.handler.test.ts @@ -8,9 +8,9 @@ import { import { describe, it, beforeEach, vi, expect } from "vitest"; import type { TrpcSessionUser } from "../../../trpc"; -import getTeamWithMinimalData from "./getMinimal.handler"; +import getTeam from "./get.handler"; -describe("getTeamWithMinimalData", () => { +describe("getTeam", () => { beforeEach(() => { // Reset all mocks before each test vi.clearAllMocks(); @@ -64,7 +64,7 @@ describe("getTeamWithMinimalData", () => { } as NonNullable, }; - const result = await getTeamWithMinimalData({ + const result = await getTeam({ ctx, input: { teamId: team.id, diff --git a/packages/trpc/server/routers/viewer/teams/get.handler.ts b/packages/trpc/server/routers/viewer/teams/get.handler.ts index 86551b9b2fb4b4..0d252daa64d7b3 100644 --- a/packages/trpc/server/routers/viewer/teams/get.handler.ts +++ b/packages/trpc/server/routers/viewer/teams/get.handler.ts @@ -1,68 +1,49 @@ -import { markdownToSafeHTML } from "@calcom/lib/markdownToSafeHTML"; -import { getTeamWithMembers } from "@calcom/lib/server/queries/teams"; -import { MembershipRole } from "@calcom/prisma/enums"; +import { getTeamWithoutMembers } from "@calcom/lib/server/queries/teams"; +import { MembershipRepository } from "@calcom/lib/server/repository/membership"; import { TRPCError } from "@trpc/server"; import type { TrpcSessionUser } from "../../../trpc"; import type { TGetInputSchema } from "./get.schema"; -type GetOptions = { +type GetDataOptions = { ctx: { user: NonNullable; }; input: TGetInputSchema; }; -export const getHandler = async ({ ctx, input }: GetOptions) => { - const team = await getTeamWithMembers({ +export const get = async ({ ctx, input }: GetDataOptions) => { + const teamMembership = await MembershipRepository.findFirstByUserIdAndTeamId({ + userId: ctx.user.id, + teamId: input.teamId, + }); + + if (!teamMembership) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not a member of this team.", + }); + } + + const team = await getTeamWithoutMembers({ id: input.teamId, - currentOrg: ctx.user.profile?.organization ?? null, userId: ctx.user.organization?.isOrgAdmin ? undefined : ctx.user.id, isOrgView: input?.isOrg, }); if (!team) { - throw new TRPCError({ code: "NOT_FOUND", message: "Team not found." }); - } - - const membership = team?.members.find((membership) => membership.id === ctx.user.id); - - if (!membership) { - throw new TRPCError({ code: "NOT_FOUND", message: "Not a member of this team." }); - } - const { members, ...restTeam } = team; - - // Hide Members of team when 1) Org is private and logged in user is not admin or owner - // OR - // 2)Team is private and logged in user is not admin or owner of team or Organization's admin or owner - function shouldHideMembers() { - const isOrgPrivate = ctx.user.profile?.organization?.isPrivate; - const isOrgAdminOrOwner = ctx.user.organization?.isOrgAdmin; - const isTargetingOrg = input.teamId === ctx.user.organizationId; - - if (isTargetingOrg) { - return isOrgPrivate && !isOrgAdminOrOwner; - } - - const isTeamAdminOrOwner = - membership?.role === MembershipRole.OWNER || membership?.role === MembershipRole.ADMIN; - - if (team?.isPrivate && !isTeamAdminOrOwner && !isOrgAdminOrOwner) { - return true; - } - return false; + throw new TRPCError({ + code: "NOT_FOUND", + message: "Team not found", + }); } - return { - ...restTeam, - members: shouldHideMembers() ? [] : members, - safeBio: markdownToSafeHTML(team.bio), - membership: { - role: membership.role, - accepted: membership.accepted, - }, + const membership = { + role: teamMembership.role, + accepted: teamMembership.accepted, }; + return { ...team, membership }; }; -export default getHandler; +export default get; diff --git a/packages/trpc/server/routers/viewer/teams/get.schema.ts b/packages/trpc/server/routers/viewer/teams/get.schema.ts index fcf650e1c7a9aa..8542d2e68e1961 100644 --- a/packages/trpc/server/routers/viewer/teams/get.schema.ts +++ b/packages/trpc/server/routers/viewer/teams/get.schema.ts @@ -1,8 +1,8 @@ import { z } from "zod"; -export const ZGetInputSchema = z.object({ +export const ZGetSchema = z.object({ teamId: z.number(), isOrg: z.boolean().optional(), }); -export type TGetInputSchema = z.infer; +export type TGetInputSchema = z.infer; diff --git a/packages/trpc/server/routers/viewer/teams/getMinimal.handler.ts b/packages/trpc/server/routers/viewer/teams/getMinimal.handler.ts deleted file mode 100644 index f3b44e322007d0..00000000000000 --- a/packages/trpc/server/routers/viewer/teams/getMinimal.handler.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { getMinimalTeam } from "@calcom/lib/server/queries/teams"; -import { MembershipRepository } from "@calcom/lib/server/repository/membership"; - -import { TRPCError } from "@trpc/server"; - -import type { TrpcSessionUser } from "../../../trpc"; -import type { TGetMinimalInputSchema } from "./getMinimal.schema"; - -type GetMinimalDataOptions = { - ctx: { - user: NonNullable; - }; - input: TGetMinimalInputSchema; -}; - -export const getMinimal = async ({ ctx, input }: GetMinimalDataOptions) => { - const teamMembership = await MembershipRepository.findFirstByUserIdAndTeamId({ - userId: ctx.user.id, - teamId: input.teamId, - }); - - if (!teamMembership) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "You are not a member of this team.", - }); - } - - const team = await getMinimalTeam({ - id: input.teamId, - userId: ctx.user.organization?.isOrgAdmin ? undefined : ctx.user.id, - isOrgView: input?.isOrg, - }); - - if (!team) { - throw new TRPCError({ - code: "NOT_FOUND", - message: "Team not found", - }); - } - - const membership = { - role: teamMembership.role, - accepted: teamMembership.accepted, - }; - return { ...team, membership }; -}; - -export default getMinimal; diff --git a/packages/trpc/server/routers/viewer/teams/getMinimal.schema.ts b/packages/trpc/server/routers/viewer/teams/getMinimal.schema.ts deleted file mode 100644 index 0237b1fef09a77..00000000000000 --- a/packages/trpc/server/routers/viewer/teams/getMinimal.schema.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { z } from "zod"; - -export const ZGetMinimalSchema = z.object({ - teamId: z.number(), - isOrg: z.boolean().optional(), -}); - -export type TGetMinimalInputSchema = z.infer; diff --git a/packages/trpc/server/routers/viewer/teams/lazyLoadMembers.handler.ts b/packages/trpc/server/routers/viewer/teams/lazyLoadMembers.handler.ts deleted file mode 100644 index 1d3e4bf4e9b8a2..00000000000000 --- a/packages/trpc/server/routers/viewer/teams/lazyLoadMembers.handler.ts +++ /dev/null @@ -1,162 +0,0 @@ -import { Prisma } from "@prisma/client"; - -// import { getAppFromSlug } from "@calcom/app-store/utils"; -import { getBookerBaseUrlSync } from "@calcom/lib/getBookerUrl/client"; -import { UserRepository } from "@calcom/lib/server/repository/user"; -import prisma from "@calcom/prisma"; -import { MembershipRole } from "@calcom/prisma/enums"; -import type { TrpcSessionUser } from "@calcom/trpc/server/trpc"; - -import { TRPCError } from "@trpc/server"; - -import type { TLazyLoadMembersInputSchema } from "./lazyLoadMembers.schema"; - -type LazyLoadMembersHandlerOptions = { - ctx: { - user: NonNullable; - }; - input: TLazyLoadMembersInputSchema; -}; - -const userSelect = Prisma.validator()({ - username: true, - email: true, - name: true, - avatarUrl: true, - id: true, - bio: true, - disableImpersonation: true, -}); - -export const lazyLoadMembersHandler = async ({ ctx, input }: LazyLoadMembersHandlerOptions) => { - const { cursor, limit, teamId, searchTerm } = input; - - const canAccessMembers = await checkCanAccessMembers(ctx, teamId); - - if (!canAccessMembers) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "You are not authorized to see members of the team", - }); - } - - const getTotalMembers = await prisma.membership.count({ - where: { - teamId: teamId, - }, - }); - - const teamMembers = await prisma.membership.findMany({ - where: { - teamId, - ...(searchTerm && { - user: { - OR: [ - { - email: { - contains: searchTerm, - mode: "insensitive", - }, - }, - { - username: { - contains: searchTerm, - mode: "insensitive", - }, - }, - { - name: { - contains: searchTerm, - mode: "insensitive", - }, - }, - ], - }, - }), - }, - select: { - id: true, - role: true, - accepted: true, - user: { - select: userSelect, - }, - }, - cursor: cursor ? { id: cursor } : undefined, - take: limit + 1, // We take +1 as itll be used for the next cursor - orderBy: { - id: "asc", - }, - }); - - let nextCursor: typeof cursor | undefined = undefined; - if (teamMembers && teamMembers.length > limit) { - const nextItem = teamMembers.pop(); - nextCursor = nextItem?.id; - } - - const membersWithApps = await Promise.all( - teamMembers.map(async (member) => { - const user = await UserRepository.enrichUserWithItsProfile({ - user: member.user, - }); - const { profile, ...restUser } = user; - return { - ...restUser, - username: profile?.username ?? restUser.username, - role: member.role, - profile: profile, - organizationId: profile?.organizationId ?? null, - organization: profile?.organization, - accepted: member.accepted, - disableImpersonation: user.disableImpersonation, - bookerUrl: getBookerBaseUrlSync(profile?.organization?.slug || ""), - }; - }) - ); - - return { - members: membersWithApps, - nextCursor, - meta: { - totalRowCount: getTotalMembers || 0, - }, - }; -}; - -const checkCanAccessMembers = async (ctx: LazyLoadMembersHandlerOptions["ctx"], teamId: number) => { - const isOrgPrivate = ctx.user.profile?.organization?.isPrivate; - const isOrgAdminOrOwner = ctx.user.organization?.isOrgAdmin; - const orgId = ctx.user.organizationId; - const isTargetingOrg = teamId === ctx.user.organizationId; - - if (isTargetingOrg) { - return isOrgPrivate && !isOrgAdminOrOwner; - } - const team = await prisma.team.findUnique({ - where: { - id: teamId, - }, - }); - - if (isOrgAdminOrOwner && team?.parentId === orgId) { - return true; - } - - const membership = await prisma.membership.findFirst({ - where: { - teamId, - userId: ctx.user.id, - }, - }); - - const isTeamAdminOrOwner = - membership?.role === MembershipRole.OWNER || membership?.role === MembershipRole.ADMIN; - - if (team?.isPrivate && !isTeamAdminOrOwner) { - return false; - } - return true; -}; - -export default lazyLoadMembersHandler; diff --git a/packages/trpc/server/routers/viewer/teams/lazyLoadMembers.schema.ts b/packages/trpc/server/routers/viewer/teams/lazyLoadMembers.schema.ts deleted file mode 100644 index a19c8a28ecab1e..00000000000000 --- a/packages/trpc/server/routers/viewer/teams/lazyLoadMembers.schema.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { z } from "zod"; - -export const ZLazyLoadMembersInputSchema = z.object({ - teamId: z.number(), - limit: z.number().default(10), - searchTerm: z.string().optional(), - cursor: z.number().optional().nullable(), -}); - -export type TLazyLoadMembersInputSchema = z.infer; diff --git a/packages/trpc/server/routers/viewer/teams/legacyListMembers.handler.ts b/packages/trpc/server/routers/viewer/teams/legacyListMembers.handler.ts new file mode 100644 index 00000000000000..7341f2acb986de --- /dev/null +++ b/packages/trpc/server/routers/viewer/teams/legacyListMembers.handler.ts @@ -0,0 +1,69 @@ +import { UserRepository } from "@calcom/lib/server/repository/user"; +import type { PrismaClient } from "@calcom/prisma"; +import type { TrpcSessionUser } from "@calcom/trpc/server/trpc"; + +import type { TListMembersInputSchema } from "./legacyListMembers.schema"; + +type ListMembersOptions = { + ctx: { + user: NonNullable; + prisma: PrismaClient; + }; + input: TListMembersInputSchema; +}; + +export const legacyListMembers = async ({ ctx, input }: ListMembersOptions) => { + const { prisma } = ctx; + const { isOrgAdmin } = ctx.user.organization; + const hasPermsToView = !ctx.user.organization.isPrivate || isOrgAdmin; + + if (!hasPermsToView) { + return []; + } + + const teams = await prisma.team.findMany({ + where: { + id: { + in: input.teamIds, + }, + members: { + some: { + user: { + id: ctx.user.id, + }, + accepted: true, + }, + }, + }, + select: { + members: { + select: { + user: { + select: { + id: true, + name: true, + username: true, + avatarUrl: true, + }, + }, + accepted: true, + }, + }, + }, + }); + + type UserMap = Record; + // flatten users to be unique by id + const users = teams + .flatMap((t) => t.members) + .reduce( + (acc, m) => (m.user.id in acc ? acc : { ...acc, [m.user.id]: { ...m.user, accepted: m.accepted } }), + {} as UserMap + ); + + return await Promise.all( + Object.values(users).map(async (u) => UserRepository.enrichUserWithItsProfile({ user: u })) + ); +}; + +export default legacyListMembers; diff --git a/packages/trpc/server/routers/viewer/teams/legacyListMembers.schema.ts b/packages/trpc/server/routers/viewer/teams/legacyListMembers.schema.ts new file mode 100644 index 00000000000000..ff83f6c100cb14 --- /dev/null +++ b/packages/trpc/server/routers/viewer/teams/legacyListMembers.schema.ts @@ -0,0 +1,7 @@ +import { z } from "zod"; + +export const ZListMembersInputSchema = z.object({ + teamIds: z.number().array().optional(), +}); + +export type TListMembersInputSchema = z.infer; diff --git a/packages/trpc/server/routers/viewer/teams/listMembers.handler.ts b/packages/trpc/server/routers/viewer/teams/listMembers.handler.ts index fce0a112a92ac3..f1dd2ae68d29ea 100644 --- a/packages/trpc/server/routers/viewer/teams/listMembers.handler.ts +++ b/packages/trpc/server/routers/viewer/teams/listMembers.handler.ts @@ -1,69 +1,148 @@ +import { Prisma } from "@prisma/client"; + +import { getBookerBaseUrlSync } from "@calcom/lib/getBookerUrl/client"; import { UserRepository } from "@calcom/lib/server/repository/user"; -import type { PrismaClient } from "@calcom/prisma"; +import { prisma } from "@calcom/prisma"; +import { MembershipRole } from "@calcom/prisma/enums"; import type { TrpcSessionUser } from "@calcom/trpc/server/trpc"; +import { TRPCError } from "@trpc/server"; + import type { TListMembersInputSchema } from "./listMembers.schema"; -type ListMembersOptions = { +type ListMembersHandlerOptions = { ctx: { user: NonNullable; - prisma: PrismaClient; }; input: TListMembersInputSchema; }; -export const listMembersHandler = async ({ ctx, input }: ListMembersOptions) => { - const { prisma } = ctx; - const { isOrgAdmin } = ctx.user.organization; - const hasPermsToView = !ctx.user.organization.isPrivate || isOrgAdmin; +const userSelect = Prisma.validator()({ + username: true, + email: true, + name: true, + avatarUrl: true, + id: true, + bio: true, + disableImpersonation: true, +}); + +export const listMembersHandler = async ({ ctx, input }: ListMembersHandlerOptions) => { + const { cursor, limit, teamId, searchTerm } = input; - if (!hasPermsToView) { - return []; + const canAccessMembers = await checkCanAccessMembers(ctx, teamId); + + if (!canAccessMembers) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to see members of any teams", + }); } - const teams = await prisma.team.findMany({ - where: { - id: { - in: input.teamIds, - }, - members: { - some: { - user: { - id: ctx.user.id, - }, - accepted: true, - }, - }, - }, + const whereCondition: Prisma.MembershipWhereInput = { + teamId, + }; + + if (searchTerm) { + whereCondition.user = { + OR: [ + { email: { contains: searchTerm, mode: "insensitive" } }, + { username: { contains: searchTerm, mode: "insensitive" } }, + { name: { contains: searchTerm, mode: "insensitive" } }, + ], + }; + } + + const totalMembers = await prisma.membership.count({ where: whereCondition }); + + const teamMembers = await prisma.membership.findMany({ + where: whereCondition, select: { - members: { - select: { - user: { - select: { - id: true, - name: true, - username: true, - avatarUrl: true, - }, - }, - accepted: true, - }, - }, + id: true, + role: true, + accepted: true, + teamId: true, + user: { select: userSelect }, }, + cursor: cursor ? { id: cursor } : undefined, + take: limit + 1, + orderBy: { id: "asc" }, }); - type UserMap = Record; - // flatten users to be unique by id - const users = teams - .flatMap((t) => t.members) - .reduce( - (acc, m) => (m.user.id in acc ? acc : { ...acc, [m.user.id]: { ...m.user, accepted: m.accepted } }), - {} as UserMap - ); - - return await Promise.all( - Object.values(users).map(async (u) => UserRepository.enrichUserWithItsProfile({ user: u })) + let nextCursor: typeof cursor | undefined = undefined; + if (teamMembers.length > limit) { + const nextItem = teamMembers.pop(); + nextCursor = nextItem?.id; + } + + const membersWithApps = await Promise.all( + teamMembers.map(async (member) => { + const user = await UserRepository.enrichUserWithItsProfile({ + user: member.user, + }); + const { profile, ...restUser } = user; + return { + ...restUser, + username: profile?.username ?? restUser.username, + role: member.role, + profile: profile, + organizationId: profile?.organizationId ?? null, + organization: profile?.organization, + accepted: member.accepted, + disableImpersonation: user.disableImpersonation, + bookerUrl: getBookerBaseUrlSync(profile?.organization?.slug || ""), + teamId: member.teamId, + }; + }) ); + + return { + members: membersWithApps, + nextCursor, + meta: { + totalRowCount: totalMembers, + }, + }; +}; + +const checkCanAccessMembers = async (ctx: ListMembersHandlerOptions["ctx"], teamId: number) => { + const isOrgPrivate = ctx.user.profile?.organization?.isPrivate; + const isOrgAdminOrOwner = ctx.user.organization?.isOrgAdmin; + const orgId = ctx.user.organizationId; + const isTargetingOrg = teamId === ctx.user.organizationId; + + if (isTargetingOrg) { + return isOrgAdminOrOwner || !isOrgPrivate; + } + const team = await prisma.team.findUnique({ + where: { + id: teamId, + }, + }); + + if (!team) return false; + + if (isOrgAdminOrOwner && team?.parentId === orgId) { + return true; + } + + const membership = await prisma.membership.findFirst({ + where: { + teamId, + userId: ctx.user.id, + accepted: true, + }, + }); + + if (!membership) return false; + + const isTeamAdminOrOwner = + membership?.role === MembershipRole.OWNER || membership?.role === MembershipRole.ADMIN; + + if (team?.isPrivate && !isTeamAdminOrOwner) { + return false; + } + return true; }; export default listMembersHandler; diff --git a/packages/trpc/server/routers/viewer/teams/listMembers.schema.ts b/packages/trpc/server/routers/viewer/teams/listMembers.schema.ts index ff83f6c100cb14..c8b78ad41fb02e 100644 --- a/packages/trpc/server/routers/viewer/teams/listMembers.schema.ts +++ b/packages/trpc/server/routers/viewer/teams/listMembers.schema.ts @@ -1,7 +1,10 @@ import { z } from "zod"; export const ZListMembersInputSchema = z.object({ - teamIds: z.number().array().optional(), + teamId: z.number(), + limit: z.number().default(10), + searchTerm: z.string().optional(), + cursor: z.number().optional().nullable(), }); export type TListMembersInputSchema = z.infer; diff --git a/packages/trpc/server/routers/viewer/teams/lazyLoadMembers.test.ts b/packages/trpc/server/routers/viewer/teams/listMembers.test.ts similarity index 94% rename from packages/trpc/server/routers/viewer/teams/lazyLoadMembers.test.ts rename to packages/trpc/server/routers/viewer/teams/listMembers.test.ts index 7da07844faf1a5..93b8bb4652818c 100644 --- a/packages/trpc/server/routers/viewer/teams/lazyLoadMembers.test.ts +++ b/packages/trpc/server/routers/viewer/teams/listMembers.test.ts @@ -9,7 +9,7 @@ import { import { describe, it, beforeEach, vi, expect } from "vitest"; import type { TrpcSessionUser } from "../../../trpc"; -import lazyLoadMembers from "./lazyLoadMembers.handler"; +import listMembers from "./listMembers.handler"; const createTeamWithMembers = async ({ isPrivate = false }: { isPrivate?: boolean }) => { const team = { @@ -94,7 +94,7 @@ const createTeamWithMembers = async ({ isPrivate = false }: { isPrivate?: boolea }; }; -describe("lazyLoadMembers", () => { +describe("listMembers", () => { beforeEach(() => { // Reset all mocks before each test vi.clearAllMocks(); @@ -110,7 +110,7 @@ describe("lazyLoadMembers", () => { } as NonNullable, }; - const result = await lazyLoadMembers({ + const result = await listMembers({ ctx, input: { teamId: team.id, @@ -148,7 +148,7 @@ describe("lazyLoadMembers", () => { } as NonNullable, }; - const result = await lazyLoadMembers({ + const result = await listMembers({ ctx, input: { teamId: team.id, @@ -187,14 +187,14 @@ describe("lazyLoadMembers", () => { }; await expect( - lazyLoadMembers({ + listMembers({ ctx: nonAdminUserCtx, input: { teamId: team.id, limit: 10, }, }) - ).rejects.toThrowError("You are not authorized to see members of the team"); + ).rejects.toThrowError("You are not authorized to see members of any teams"); }); it("should throw error if user is not part of the private team", async () => { @@ -218,14 +218,14 @@ describe("lazyLoadMembers", () => { }; await expect( - lazyLoadMembers({ + listMembers({ ctx: nonAdminUserCtx, input: { teamId: team.id, limit: 10, }, }) - ).rejects.toThrowError("You are not authorized to see members of the team"); + ).rejects.toThrowError("You are not authorized to see members of any teams"); }); it("can search by name or email", async () => { @@ -239,7 +239,7 @@ describe("lazyLoadMembers", () => { }; // Search by email - const searchByEmail = await lazyLoadMembers({ + const searchByEmail = await listMembers({ ctx, input: { teamId: team.id, @@ -257,7 +257,7 @@ describe("lazyLoadMembers", () => { ]); // Search by name - const searchByName = await lazyLoadMembers({ + const searchByName = await listMembers({ ctx, input: { teamId: team.id, diff --git a/packages/trpc/server/routers/viewer/webhook/create.schema.ts b/packages/trpc/server/routers/viewer/webhook/create.schema.ts index ad0616e66c12ff..661e0f9144ac2d 100644 --- a/packages/trpc/server/routers/viewer/webhook/create.schema.ts +++ b/packages/trpc/server/routers/viewer/webhook/create.schema.ts @@ -1,5 +1,6 @@ import { z } from "zod"; +import { TIME_UNIT } from "@calcom/features/ee/workflows/lib/constants"; import { WEBHOOK_TRIGGER_EVENTS } from "@calcom/features/webhooks/lib/constants"; import { webhookIdAndEventTypeIdSchema } from "./types"; @@ -14,6 +15,8 @@ export const ZCreateInputSchema = webhookIdAndEventTypeIdSchema.extend({ secret: z.string().optional().nullable(), teamId: z.number().optional(), platform: z.boolean().optional(), + time: z.number().nullable().optional(), + timeUnit: z.enum(TIME_UNIT).nullable().optional(), }); export type TCreateInputSchema = z.infer; diff --git a/packages/trpc/server/routers/viewer/webhook/edit.schema.ts b/packages/trpc/server/routers/viewer/webhook/edit.schema.ts index 183df2f74b50d1..1bb505b43835a7 100644 --- a/packages/trpc/server/routers/viewer/webhook/edit.schema.ts +++ b/packages/trpc/server/routers/viewer/webhook/edit.schema.ts @@ -1,5 +1,6 @@ import { z } from "zod"; +import { TIME_UNIT } from "@calcom/features/ee/workflows/lib/constants"; import { WEBHOOK_TRIGGER_EVENTS } from "@calcom/features/webhooks/lib/constants"; import { webhookIdAndEventTypeIdSchema } from "./types"; @@ -13,6 +14,8 @@ export const ZEditInputSchema = webhookIdAndEventTypeIdSchema.extend({ eventTypeId: z.number().optional(), appId: z.string().optional().nullable(), secret: z.string().optional().nullable(), + time: z.number().nullable().optional(), + timeUnit: z.enum(TIME_UNIT).nullable().optional(), }); export type TEditInputSchema = z.infer; diff --git a/packages/types/CrmService.d.ts b/packages/types/CrmService.d.ts index e3bf894a48b74f..029bc59a600d13 100644 --- a/packages/types/CrmService.d.ts +++ b/packages/types/CrmService.d.ts @@ -25,9 +25,18 @@ export interface CrmEvent { } export interface CRM { - createEvent: (event: CalendarEvent, contacts: Contact[]) => Promise; + createEvent: (event: CalendarEvent, contacts: Contact[]) => Promise; updateEvent: (uid: string, event: CalendarEvent) => Promise; deleteEvent: (uid: string) => Promise; - getContacts: (emails: string | string[], includeOwner?: boolean) => Promise; + getContacts: ({ + emails, + includeOwner, + forRoundRobinSkip, + }: { + emails: string | string[]; + includeOwner?: boolean; + forRoundRobinSkip?: boolean; + }) => Promise; createContacts: (contactsToCreate: ContactCreateInput[], organizerEmail?: string) => Promise; + getAppOptions: () => any; } diff --git a/packages/ui/components/button/Button.tsx b/packages/ui/components/button/Button.tsx index 4faa22569ffe40..e8376591ec30ed 100644 --- a/packages/ui/components/button/Button.tsx +++ b/packages/ui/components/button/Button.tsx @@ -25,6 +25,7 @@ export type ButtonBaseProps = { tooltip?: string | React.ReactNode; tooltipSide?: "top" | "right" | "bottom" | "left"; tooltipOffset?: number; + tooltipClassName?: string; disabled?: boolean; flex?: boolean; } & Omit & { @@ -127,6 +128,7 @@ export const Button = forwardRef + tooltipOffset={tooltipOffset} + tooltipClassName={tooltipClassName}> {element} ); @@ -239,18 +242,25 @@ const Wrapper = ({ tooltip, tooltipSide, tooltipOffset, + tooltipClassName, }: { tooltip?: string | React.ReactNode; children: React.ReactNode; tooltipSide?: "top" | "right" | "bottom" | "left"; tooltipOffset?: number; + tooltipClassName?: string; }) => { if (!tooltip) { return <>{children}; } return ( - + {children} ); diff --git a/packages/ui/components/form/date-range-picker/DateRangePicker.tsx b/packages/ui/components/form/date-range-picker/DateRangePicker.tsx index addd2e981ea2b2..e8fa5638111e67 100644 --- a/packages/ui/components/form/date-range-picker/DateRangePicker.tsx +++ b/packages/ui/components/form/date-range-picker/DateRangePicker.tsx @@ -1,5 +1,6 @@ "use client"; +import * as Popover from "@radix-ui/react-popover"; import { format } from "date-fns"; import * as React from "react"; import type { DateRange } from "react-day-picker"; @@ -7,7 +8,6 @@ import type { DateRange } from "react-day-picker"; import { classNames as cn } from "@calcom/lib"; import { Button } from "../../button"; -import { Popover, PopoverContent, PopoverTrigger } from "../../popover"; import { Calendar } from "./Calendar"; type DatePickerWithRangeProps = { @@ -37,8 +37,8 @@ export function DatePickerWithRange({ return (
          - - + + - - + + - - + +
          ); } diff --git a/packages/ui/components/navigation/tabs/HorizontalTabItem.tsx b/packages/ui/components/navigation/tabs/HorizontalTabItem.tsx index f00b33689ab57c..7d2ba86a3d187e 100644 --- a/packages/ui/components/navigation/tabs/HorizontalTabItem.tsx +++ b/packages/ui/components/navigation/tabs/HorizontalTabItem.tsx @@ -18,6 +18,8 @@ export type HorizontalTabItemProps = { linkScroll?: boolean; icon?: IconName; avatar?: string; + onClick?: (name: string) => void; + isActive?: boolean; }; const HorizontalTabItem = function ({ @@ -30,10 +32,16 @@ const HorizontalTabItem = function ({ }: HorizontalTabItemProps) { const { t, isLocaleReady } = useLocale(); - const isCurrent = useUrlMatchesCurrentUrl(href); + const isCurrent = useUrlMatchesCurrentUrl(href) || props?.isActive; return ( { + if (props.onClick) { + e.preventDefault(); + props.onClick(name); + } + }} key={name} href={href} shallow={linkShallow} diff --git a/packages/ui/components/navigation/tabs/VerticalTabItem.tsx b/packages/ui/components/navigation/tabs/VerticalTabItem.tsx index 87549258132208..408551167455ff 100644 --- a/packages/ui/components/navigation/tabs/VerticalTabItem.tsx +++ b/packages/ui/components/navigation/tabs/VerticalTabItem.tsx @@ -26,6 +26,7 @@ export type VerticalTabItemProps = { avatar?: string; iconClassName?: string; onClick?: (name: string) => void; + isActive?: boolean; }; const VerticalTabItem = ({ @@ -39,7 +40,7 @@ const VerticalTabItem = ({ ...props }: VerticalTabItemProps) => { const { t } = useLocale(); - const isCurrent = useUrlMatchesCurrentUrl(href); + const isCurrent = useUrlMatchesCurrentUrl(href) || props?.isActive; return ( diff --git a/packages/ui/components/tooltip/Tooltip.tsx b/packages/ui/components/tooltip/Tooltip.tsx index 0ea983c1d3cfcb..edb222b012165a 100644 --- a/packages/ui/components/tooltip/Tooltip.tsx +++ b/packages/ui/components/tooltip/Tooltip.tsx @@ -32,8 +32,7 @@ export function Tooltip({ "calcom-tooltip", side === "top" && "-mt-7", side === "right" && "ml-2", - "relative z-50 rounded-md text-xs font-semibold shadow-lg", - !isPlatform && "bg-inverted text-inverted px-2 py-1", + "bg-inverted text-inverted relative z-50 rounded-md px-2 py-1 text-xs font-semibold shadow-lg", props.className && `${props.className}` )} side={side} diff --git a/packages/ui/package.json b/packages/ui/package.json index 58fd091feea904..de3c65587e67a5 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -43,7 +43,7 @@ "cmk": "^0.1.1", "date-fns": "^3.6.0", "downshift": "^6.1.9", - "next": "^13.5.4", + "next": "^13.5.6", "next-seo": "^6.0.0", "react": "^18.2.0", "react-colorful": "^5.6.0", diff --git a/yarn.lock b/yarn.lock index 620261400f4582..3d43af0bb13545 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3762,15 +3762,6 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.23.8, @babel/runtime@npm:^7.6.2": - version: 7.24.0 - resolution: "@babel/runtime@npm:7.24.0" - dependencies: - regenerator-runtime: ^0.14.0 - checksum: 7a6a5d40fbdd68491ec183ba2e631c07415119960083b4fd76564cce3751e9acd2f12ab89575e38496fa389fa06d458732776e69ee1858e366cc3fbdb049f847 - languageName: node - linkType: hard - "@babel/template@npm:^7.18.10, @babel/template@npm:^7.20.7, @babel/template@npm:^7.25.0": version: 7.25.0 resolution: "@babel/template@npm:7.25.0" @@ -4134,7 +4125,7 @@ __metadata: dependencies: "@calcom/platform-constants": "*" "@calcom/platform-enums": "*" - "@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.44" + "@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.45" "@calcom/platform-libraries-0.0.2": "npm:@calcom/platform-libraries@0.0.2" "@calcom/platform-types": "*" "@calcom/platform-utils": "*" @@ -4215,7 +4206,7 @@ __metadata: "@sentry/nextjs": ^8.8.0 bcryptjs: ^2.4.3 memory-cache: ^0.2.0 - next: ^13.5.4 + next: ^13.5.6 next-api-middleware: ^1.0.1 next-axiom: ^0.17.0 next-swagger-doc: ^0.3.6 @@ -4327,6 +4318,28 @@ __metadata: languageName: unknown linkType: soft +"@calcom/atoms@npm:1.0.60": + version: 1.0.60 + resolution: "@calcom/atoms@npm:1.0.60" + dependencies: + "@radix-ui/react-dialog": ^1.0.4 + "@radix-ui/react-slot": ^1.0.2 + "@radix-ui/react-switch": ^1.1.0 + "@radix-ui/react-toast": ^1.1.5 + "@tanstack/react-query": ^5.17.15 + class-variance-authority: ^0.7.0 + clsx: ^2.0.0 + react-use: ^17.4.2 + tailwind-merge: ^1.13.2 + tailwindcss: ^3.3.3 + tailwindcss-animate: ^1.0.6 + peerDependencies: + react: ">=18.0.0" + typescript: ">=5.4.5" + checksum: b216d40948ca1a96d8374c0f9878c1c9b5776b2b6cc569ba7fb344fec360fe4a43f23f97a4d82e4c5ad75c83ea6c8b63de079088598594564bf44d00d7cb9b42 + languageName: node + linkType: hard + "@calcom/autocheckin@workspace:packages/app-store/autocheckin": version: 0.0.0-use.local resolution: "@calcom/autocheckin@workspace:packages/app-store/autocheckin" @@ -4484,7 +4497,7 @@ __metadata: chart.js: ^3.7.1 client-only: ^0.0.1 eslint: ^8.34.0 - next: ^13.5.4 + next: ^13.5.6 next-auth: ^4.22.1 next-i18next: ^13.2.2 postcss: ^8.4.18 @@ -4743,7 +4756,7 @@ __metadata: "@calcom/lib": "*" "@calcom/prisma": "*" "@calcom/types": "*" - "@ewsjs/xhr": ^1.4.4 + "@ewsjs/xhr": ^3.1.2 ews-javascript-api: ^0.11.0 languageName: unknown linkType: soft @@ -5141,14 +5154,14 @@ __metadata: languageName: node linkType: hard -"@calcom/platform-libraries@npm:@calcom/platform-libraries@0.0.44": - version: 0.0.44 - resolution: "@calcom/platform-libraries@npm:0.0.44" +"@calcom/platform-libraries@npm:@calcom/platform-libraries@0.0.45": + version: 0.0.45 + resolution: "@calcom/platform-libraries@npm:0.0.45" dependencies: "@calcom/core": "*" "@calcom/features": "*" "@calcom/lib": "*" - checksum: 0d46c2c695a8a776f7401e298d0f7d0b3227c9fe38e1746aaf747c22fe28d881939c31c54613e696a595b72af21fe14b342dabe99c59b44d6576f4e2f37bf76f + checksum: 69f3513cd389d328153ba6704db3eb6251a005618f4d71de7b6102e553393004da9c420c3685370c8a4daa255a0964d2f2f6979079e66036e0be2e4c2277c8ce languageName: node linkType: hard @@ -5409,7 +5422,7 @@ __metadata: autoprefixer: ^10.4.12 babel-loader: ^8.2.5 fs: ^0.0.1-security - next: ^13.5.4 + next: ^13.5.6 postcss: ^8.4.18 postcss-pseudo-companion-classes: ^0.1.1 react: ^18.2.0 @@ -5454,7 +5467,7 @@ __metadata: "@types/swagger-ui-react": ^4.18.3 highlight.js: ^11.6.0 isarray: 2.0.5 - next: ^13.5.4 + next: ^13.5.6 openapi-snippet: ^0.13.0 react: ^18.2.0 react-dom: ^18.2.0 @@ -5577,7 +5590,7 @@ __metadata: fast-glob: ^3.3.2 fs-extra: ^11.2.0 lucide-static: ^0.424.0 - next: ^13.5.4 + next: ^13.5.6 next-seo: ^6.0.0 node-html-parser: ^6.1.13 react: ^18.2.0 @@ -5685,6 +5698,7 @@ __metadata: "@types/async": ^3.2.15 "@types/bcryptjs": ^2.4.2 "@types/detect-port": ^1.3.2 + "@types/dompurify": ^3.0.5 "@types/glidejs__glide": ^3.4.2 "@types/lodash": ^4.14.182 "@types/markdown-it": ^12.2.3 @@ -5715,7 +5729,10 @@ __metadata: bcryptjs: ^2.4.3 classnames: ^2.3.1 copy-webpack-plugin: ^11.0.0 + cron: ^3.1.7 + deasync: ^0.1.30 detect-port: ^1.3.0 + dompurify: ^3.1.7 dotenv-cli: ^6.0.0 entities: ^4.4.0 env-cmd: ^10.1.0 @@ -5737,7 +5754,7 @@ __metadata: mime-types: ^2.1.35 module-alias: ^2.2.2 msw: ^0.42.3 - next: ^13.5.4 + next: ^13.5.6 next-auth: ^4.22.1 next-axiom: ^0.17.0 next-collect: ^0.2.1 @@ -5747,6 +5764,7 @@ __metadata: node-html-parser: ^6.1.10 node-mocks-http: ^1.11.0 nodemailer: ^6.7.8 + nuqs: ^1.20.0 otplib: ^12.0.1 postcss: ^8.4.18 qrcode: ^1.5.1 @@ -5764,7 +5782,6 @@ __metadata: react-multi-email: ^0.5.3 react-phone-input-2: ^2.15.1 react-phone-number-input: ^3.2.7 - react-query: ^3.39.3 react-schemaorg: ^2.0.0 react-select: ^5.7.0 react-timezone-select: ^1.4.0 @@ -5804,6 +5821,7 @@ __metadata: dependencies: "@algora/sdk": ^0.1.2 "@calcom/app-store": "*" + "@calcom/atoms": 1.0.60 "@calcom/config": "*" "@calcom/dayjs": "*" "@calcom/embed-react": "workspace:^" @@ -5813,6 +5831,8 @@ __metadata: "@calcom/tsconfig": "*" "@calcom/ui": "*" "@datocms/cma-client-node": ^2.0.0 + "@dub/analytics": ^0.0.15 + "@eslint/js": ^9.9.0 "@floating-ui/react-dom": ^1.0.0 "@flodlc/nebula": ^1.0.56 "@graphql-codegen/cli": ^5.0.0 @@ -5830,6 +5850,7 @@ __metadata: "@radix-ui/react-dropdown-menu": ^2.0.5 "@radix-ui/react-navigation-menu": ^1.0.0 "@radix-ui/react-portal": ^1.0.0 + "@radix-ui/react-select": ^2.1.1 "@radix-ui/react-slider": ^1.0.0 "@radix-ui/react-tabs": ^1.0.0 "@radix-ui/react-tooltip": ^1.0.0 @@ -5849,6 +5870,7 @@ __metadata: "@vercel/og": ^0.5.0 autoprefixer: ^10.4.12 bcryptjs: ^2.4.3 + class-variance-authority: ^0.7.0 clsx: ^1.2.1 cobe: ^0.4.1 concurrently: ^7.6.0 @@ -5857,10 +5879,14 @@ __metadata: datocms-structured-text-utils: ^2.0.4 debounce: ^1.2.1 dotenv: ^16.3.1 + embla-carousel-react: ^8.1.8 enquirer: ^2.4.1 env-cmd: ^10.1.0 - eslint: ^8.34.0 + eslint: ^9.9.0 + eslint-plugin-react: ^7.35.0 fathom-client: ^3.5.0 + framer-motion: ^11.0.25 + globals: ^15.9.0 globby: ^13.1.3 graphql: ^16.8.0 graphql-codegen: ^0.4.0 @@ -5870,7 +5896,7 @@ __metadata: i18n-unused: ^0.13.0 iframe-resizer-react: ^1.1.0 keen-slider: ^6.8.0 - lucide-react: ^0.171.0 + lucide-react: ^0.364.0 micro: ^10.0.1 next: ^14.1.3 next-auth: ^4.22.1 @@ -5879,10 +5905,11 @@ __metadata: next-seo: ^6.0.0 playwright-core: ^1.38.1 postcss: ^8.4.18 + prettier: 3.3.3 prism-react-renderer: ^1.3.5 react: ^18.2.0 react-confetti: ^6.0.1 - react-datocms: ^3.1.0 + react-datocms: ^5.0.3 react-device-detect: ^2.2.2 react-dom: ^18.2.0 react-fast-marquee: ^1.6.4 @@ -5892,8 +5919,10 @@ __metadata: react-live-chat-loader: ^2.8.1 react-markdown: ^9.0.1 react-merge-refs: 1.1.0 + react-parallax-tilt: ^1.7.226 react-resize-detector: ^9.1.0 react-twemoji: ^0.3.0 + react-twitter-embed: ^4.0.4 react-use-measure: ^2.1.1 react-wrap-balancer: ^1.0.0 remark: ^14.0.2 @@ -5903,7 +5932,8 @@ __metadata: tailwind-merge: ^1.13.2 tailwindcss: ^3.3.3 ts-node: ^10.9.1 - typescript: ^4.9.4 + typescript: ^4.4.4 + typescript-eslint: ^8.2.0 wait-on: ^7.0.1 xml2js: ^0.6.0 zod: ^3.22.2 @@ -7004,7 +7034,7 @@ __metadata: languageName: node linkType: hard -"@eslint-community/eslint-utils@npm:^4.2.0": +"@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0": version: 4.4.0 resolution: "@eslint-community/eslint-utils@npm:4.4.0" dependencies: @@ -7015,6 +7045,13 @@ __metadata: languageName: node linkType: hard +"@eslint-community/regexpp@npm:^4.10.0, @eslint-community/regexpp@npm:^4.11.0": + version: 4.11.1 + resolution: "@eslint-community/regexpp@npm:4.11.1" + checksum: 6986685529d30e33c2640973c3d8e7ddd31bef3cc8cb10ad54ddc1dea12680779a2c23a45562aa1462c488137a3570e672d122fac7da22d82294382d915cec70 + languageName: node + linkType: hard + "@eslint-community/regexpp@npm:^4.6.1": version: 4.10.0 resolution: "@eslint-community/regexpp@npm:4.10.0" @@ -7022,6 +7059,24 @@ __metadata: languageName: node linkType: hard +"@eslint/config-array@npm:^0.18.0": + version: 0.18.0 + resolution: "@eslint/config-array@npm:0.18.0" + dependencies: + "@eslint/object-schema": ^2.1.4 + debug: ^4.3.1 + minimatch: ^3.1.2 + checksum: 5ff748e1788745bfb3160c3b3151d62a7c054e336e9fe8069e86cfa6106f3abbd59b24f1253122268295f98c66803e9a7b23d7f947a8c00f62d2060cc44bc7fc + languageName: node + linkType: hard + +"@eslint/core@npm:^0.6.0": + version: 0.6.0 + resolution: "@eslint/core@npm:0.6.0" + checksum: bf6a285d8cfb7f76524041991832fcc1573c7fc4bdfa091a14972bdb719d5a735330efb88ec453dd33930f49bcc9bb2737b40c43fb1220933781ebb712667265 + languageName: node + linkType: hard + "@eslint/eslintrc@npm:^1.4.1": version: 1.4.1 resolution: "@eslint/eslintrc@npm:1.4.1" @@ -7056,6 +7111,23 @@ __metadata: languageName: node linkType: hard +"@eslint/eslintrc@npm:^3.1.0": + version: 3.1.0 + resolution: "@eslint/eslintrc@npm:3.1.0" + dependencies: + ajv: ^6.12.4 + debug: ^4.3.2 + espree: ^10.0.1 + globals: ^14.0.0 + ignore: ^5.2.0 + import-fresh: ^3.2.1 + js-yaml: ^4.1.0 + minimatch: ^3.1.2 + strip-json-comments: ^3.1.1 + checksum: b0a9bbd98c8b9e0f4d975b042ff9b874dde722b20834ea2ff46551c3de740d4f10f56c449b790ef34d7f82147cbddfc22b004a43cc885dbc2664bb134766b5e4 + languageName: node + linkType: hard + "@eslint/js@npm:8.57.0": version: 8.57.0 resolution: "@eslint/js@npm:8.57.0" @@ -7063,25 +7135,52 @@ __metadata: languageName: node linkType: hard -"@ewsjs/ntlm-client@npm:^1.0.0": - version: 1.0.0 - resolution: "@ewsjs/ntlm-client@npm:1.0.0" +"@eslint/js@npm:9.12.0, @eslint/js@npm:^9.9.0": + version: 9.12.0 + resolution: "@eslint/js@npm:9.12.0" + checksum: cad2ee0d3080a3e507e18f1846e343d4dac00cb83b0c56355fa165b05fa0780ad746e0b93540666036e50b4cf4a4ee496a730417e500dc217c201902edd7ab5b + languageName: node + linkType: hard + +"@eslint/object-schema@npm:^2.1.4": + version: 2.1.4 + resolution: "@eslint/object-schema@npm:2.1.4" + checksum: 5a03094115bcdab7991dbbc5d17a9713f394cebb4b44d3eaf990d7487b9b8e1877b817997334ab40be52e299a0384595c6f6ba91b389901e5e1d21efda779271 + languageName: node + linkType: hard + +"@eslint/plugin-kit@npm:^0.2.0": + version: 0.2.0 + resolution: "@eslint/plugin-kit@npm:0.2.0" dependencies: - extend: ^3.0.0 - request: ^2.66.0 - checksum: 8a7e76485d3493a6b0f05dbda4382f0f680d618513930a8e0b72cc75fdd500cf3e386dcf915a3eef0f7ae534913a96d1c0673006727446271f27912ccec01055 + levn: ^0.4.1 + checksum: 2c358c816575b8338e017cff59bf8b7a186510bc0e6c1b234e889156bfea9e00ce588ce424a0aa5d322e316f1ad08e8fdc7450a7fd966c64cbb911e64eaffbb9 languageName: node linkType: hard -"@ewsjs/xhr@npm:^1.4.4": - version: 1.4.4 - resolution: "@ewsjs/xhr@npm:1.4.4" +"@ewsjs/ntlm-client@npm:^3.0.1": + version: 3.0.1 + resolution: "@ewsjs/ntlm-client@npm:3.0.1" dependencies: - "@ewsjs/ntlm-client": ^1.0.0 - bluebird: ^3.4.6 - fetch: ^1.0.1 - request: ^2.88.0 - checksum: 399e4e8590cfca8d99c3e3efd15b5449a30cd40b2253769bda1c7ab26fdb009216f0ef61e4098616635dab78ba5a5483d59e6a705458279865f8f3b417679f0a + des.js: ^1.1.0 + extend: ^3.0.2 + js-md4: ^0.3.2 + dependenciesMeta: + extend: + optional: true + checksum: 64c5c5782a58a80a5053632ff7b874bb05c8fbe7142d46be802aa0b64feb7e4250600a353cc7b00d43a1f5cc7be898c04f7ac73576275e43ff0fd5eed9f30872 + languageName: node + linkType: hard + +"@ewsjs/xhr@npm:^3.1.2": + version: 3.1.3 + resolution: "@ewsjs/xhr@npm:3.1.3" + dependencies: + "@ewsjs/ntlm-client": ^3.0.1 + axios: ^1.6.8 + http-cookie-agent: ^5.0.4 + tough-cookie: ^4.1.3 + checksum: 6563d307517e19cc6e3b1b8a986c95606b9cbfa0a826c62a0ef255777540843e638b770ff69b125b4eb43aa05158707ccd9c07e6c1afaf0dc1731e0997ad83ea languageName: node linkType: hard @@ -8062,6 +8161,23 @@ __metadata: languageName: node linkType: hard +"@humanfs/core@npm:^0.19.0": + version: 0.19.0 + resolution: "@humanfs/core@npm:0.19.0" + checksum: d73c153e9a41efce401cdf8eaa831e5b01630b45a46678eded3803347251a24446f1500b0074750fcab0a88d947609b164a0d5bba57f58ec18167bea01c69ac5 + languageName: node + linkType: hard + +"@humanfs/node@npm:^0.16.5": + version: 0.16.5 + resolution: "@humanfs/node@npm:0.16.5" + dependencies: + "@humanfs/core": ^0.19.0 + "@humanwhocodes/retry": ^0.3.0 + checksum: ae4799c6bf436450e1b1836f23fdb4ce0eb862df8e02fd498ee7d8ebe552d85fe36ccac81fcfbe39bf43cb49b302ae438d94699a451d1cfc78f64198d4b45674 + languageName: node + linkType: hard + "@humanwhocodes/config-array@npm:^0.11.14": version: 0.11.14 resolution: "@humanwhocodes/config-array@npm:0.11.14" @@ -8105,6 +8221,13 @@ __metadata: languageName: node linkType: hard +"@humanwhocodes/retry@npm:^0.3.0, @humanwhocodes/retry@npm:^0.3.1": + version: 0.3.1 + resolution: "@humanwhocodes/retry@npm:0.3.1" + checksum: 7e5517bb51dbea3e02ab6cacef59a8f4b0ca023fc4b0b8cbc40de0ad29f46edd50b897c6e7fba79366a0217e3f48e2da8975056f6c35cfe19d9cc48f1d03c1dd + languageName: node + linkType: hard + "@iarna/toml@npm:2.2.5": version: 2.2.5 resolution: "@iarna/toml@npm:2.2.5" @@ -9499,6 +9622,60 @@ __metadata: languageName: node linkType: hard +"@mux/mux-player-react@npm:*": + version: 3.0.0 + resolution: "@mux/mux-player-react@npm:3.0.0" + dependencies: + "@mux/mux-player": 3.0.0 + "@mux/playback-core": 0.26.0 + prop-types: ^15.7.2 + peerDependencies: + "@types/react": ^17.0.0 || ^18 || ^19 + react: ^17.0.2 || ^18 || ^19 + react-dom: ^17.0.2 || ^18 || ^19 + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: ab399677b9f044e74f1c56b02bf75e02154886b2b4a778073d8179440c6ac2fee51692f4ad75ba25d6fe7c35a5a1b2ebe2ae807b7a36e3669bea65392b373b10 + languageName: node + linkType: hard + +"@mux/mux-player@npm:3.0.0": + version: 3.0.0 + resolution: "@mux/mux-player@npm:3.0.0" + dependencies: + "@mux/mux-video": 0.21.0 + "@mux/playback-core": 0.26.0 + media-chrome: ~4.1.1 + player.style: ^0.0.8 + checksum: f2110d03eb49e2468b964cda2f70ea201cefafc35b738f6247637711d97f93f2a0828d51e0da04439a131ee6cdb530fc6ebaec228d268013cc6d30e68a6fda2f + languageName: node + linkType: hard + +"@mux/mux-video@npm:0.21.0": + version: 0.21.0 + resolution: "@mux/mux-video@npm:0.21.0" + dependencies: + "@mux/playback-core": 0.26.0 + castable-video: ~1.1.0 + custom-media-element: ~1.3.1 + media-tracks: ~0.3.2 + checksum: 33b9083c84ea3ad0f7c59e545790b605f4cdc47714f488fa6ab269dd8531060deac6c4a1237d132722d706f68c786561b712b83b5581398ffaa7f0a3fc642c31 + languageName: node + linkType: hard + +"@mux/playback-core@npm:0.26.0": + version: 0.26.0 + resolution: "@mux/playback-core@npm:0.26.0" + dependencies: + hls.js: ~1.5.11 + mux-embed: ^5.3.0 + checksum: 648300310eee8038654c6f2aa5be2ab0bf6ad281a6bb01ea5ffe84e501230959655917a4800d96841aa5342e1e06cc97c32228b0eeb462f57264e5dd524f1b95 + languageName: node + linkType: hard + "@ndelangen/get-tarball@npm:^3.0.7": version: 3.0.9 resolution: "@ndelangen/get-tarball@npm:3.0.9" @@ -9813,10 +9990,10 @@ __metadata: languageName: node linkType: hard -"@next/env@npm:13.5.5": - version: 13.5.5 - resolution: "@next/env@npm:13.5.5" - checksum: 4e3a92f2bd60189d81eb0437bf8141de26dec371edc125553c2d93b1de4c40ce99e8c81f60d8450961fab5c8880a6bcfccd23d9ef9c86aceab2f5380776def9f +"@next/env@npm:13.5.7": + version: 13.5.7 + resolution: "@next/env@npm:13.5.7" + checksum: 7703ba37a5ad9c280fb8a04af43231b41bec2ed0bcf182a7e9e147b12e9d710ef96bbdc8e67aa27d2cf1abd4b57951d1c12018ba6ff03fbd87f31876362f5f58 languageName: node linkType: hard @@ -9852,9 +10029,9 @@ __metadata: languageName: node linkType: hard -"@next/swc-darwin-arm64@npm:13.5.5": - version: 13.5.5 - resolution: "@next/swc-darwin-arm64@npm:13.5.5" +"@next/swc-darwin-arm64@npm:13.5.7": + version: 13.5.7 + resolution: "@next/swc-darwin-arm64@npm:13.5.7" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard @@ -9873,9 +10050,9 @@ __metadata: languageName: node linkType: hard -"@next/swc-darwin-x64@npm:13.5.5": - version: 13.5.5 - resolution: "@next/swc-darwin-x64@npm:13.5.5" +"@next/swc-darwin-x64@npm:13.5.7": + version: 13.5.7 + resolution: "@next/swc-darwin-x64@npm:13.5.7" conditions: os=darwin & cpu=x64 languageName: node linkType: hard @@ -9894,9 +10071,9 @@ __metadata: languageName: node linkType: hard -"@next/swc-linux-arm64-gnu@npm:13.5.5": - version: 13.5.5 - resolution: "@next/swc-linux-arm64-gnu@npm:13.5.5" +"@next/swc-linux-arm64-gnu@npm:13.5.7": + version: 13.5.7 + resolution: "@next/swc-linux-arm64-gnu@npm:13.5.7" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard @@ -9915,9 +10092,9 @@ __metadata: languageName: node linkType: hard -"@next/swc-linux-arm64-musl@npm:13.5.5": - version: 13.5.5 - resolution: "@next/swc-linux-arm64-musl@npm:13.5.5" +"@next/swc-linux-arm64-musl@npm:13.5.7": + version: 13.5.7 + resolution: "@next/swc-linux-arm64-musl@npm:13.5.7" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard @@ -9936,9 +10113,9 @@ __metadata: languageName: node linkType: hard -"@next/swc-linux-x64-gnu@npm:13.5.5": - version: 13.5.5 - resolution: "@next/swc-linux-x64-gnu@npm:13.5.5" +"@next/swc-linux-x64-gnu@npm:13.5.7": + version: 13.5.7 + resolution: "@next/swc-linux-x64-gnu@npm:13.5.7" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard @@ -9957,9 +10134,9 @@ __metadata: languageName: node linkType: hard -"@next/swc-linux-x64-musl@npm:13.5.5": - version: 13.5.5 - resolution: "@next/swc-linux-x64-musl@npm:13.5.5" +"@next/swc-linux-x64-musl@npm:13.5.7": + version: 13.5.7 + resolution: "@next/swc-linux-x64-musl@npm:13.5.7" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard @@ -9978,9 +10155,9 @@ __metadata: languageName: node linkType: hard -"@next/swc-win32-arm64-msvc@npm:13.5.5": - version: 13.5.5 - resolution: "@next/swc-win32-arm64-msvc@npm:13.5.5" +"@next/swc-win32-arm64-msvc@npm:13.5.7": + version: 13.5.7 + resolution: "@next/swc-win32-arm64-msvc@npm:13.5.7" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard @@ -9999,9 +10176,9 @@ __metadata: languageName: node linkType: hard -"@next/swc-win32-ia32-msvc@npm:13.5.5": - version: 13.5.5 - resolution: "@next/swc-win32-ia32-msvc@npm:13.5.5" +"@next/swc-win32-ia32-msvc@npm:13.5.7": + version: 13.5.7 + resolution: "@next/swc-win32-ia32-msvc@npm:13.5.7" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard @@ -10020,9 +10197,9 @@ __metadata: languageName: node linkType: hard -"@next/swc-win32-x64-msvc@npm:13.5.5": - version: 13.5.5 - resolution: "@next/swc-win32-x64-msvc@npm:13.5.5" +"@next/swc-win32-x64-msvc@npm:13.5.7": + version: 13.5.7 + resolution: "@next/swc-win32-x64-msvc@npm:13.5.7" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -11694,6 +11871,13 @@ __metadata: languageName: node linkType: hard +"@radix-ui/number@npm:1.1.0": + version: 1.1.0 + resolution: "@radix-ui/number@npm:1.1.0" + checksum: e4fc7483c19141c25dbaf3d140b75e2b7fed0bfa3ad969f4441f0266ed34b35413f57a35df7b025e2a977152bbe6131849d3444fc6f15a73345dfc2bfdc105fa + languageName: node + linkType: hard + "@radix-ui/primitive@npm:0.1.0": version: 0.1.0 resolution: "@radix-ui/primitive@npm:0.1.0" @@ -11775,6 +11959,25 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-arrow@npm:1.1.0": + version: 1.1.0 + resolution: "@radix-ui/react-arrow@npm:1.1.0" + dependencies: + "@radix-ui/react-primitive": 2.0.0 + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 8522e0a8095ecc32d3a719f9c3bc0514c677a9c9d5ac26985d5416576dbc487c2a49ba2484397d9de502b54657856cb41ca3ea0b2165563eeeae45a83750885b + languageName: node + linkType: hard + "@radix-ui/react-avatar@npm:^1.0.4": version: 1.0.4 resolution: "@radix-ui/react-avatar@npm:1.0.4" @@ -12038,6 +12241,19 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-context@npm:1.1.1": + version: 1.1.1 + resolution: "@radix-ui/react-context@npm:1.1.1" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 9a04db236685dacc2f5ab2bdcfc4c82b974998e712ab97d79b11d5b4ef073d24aa9392398c876ef6cb3c59f40299285ceee3646187ad818cdad4fe1c74469d3f + languageName: node + linkType: hard + "@radix-ui/react-dialog@npm:1.0.0": version: 1.0.0 resolution: "@radix-ui/react-dialog@npm:1.0.0" @@ -12230,6 +12446,29 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-dismissable-layer@npm:1.1.1": + version: 1.1.1 + resolution: "@radix-ui/react-dismissable-layer@npm:1.1.1" + dependencies: + "@radix-ui/primitive": 1.1.0 + "@radix-ui/react-compose-refs": 1.1.0 + "@radix-ui/react-primitive": 2.0.0 + "@radix-ui/react-use-callback-ref": 1.1.0 + "@radix-ui/react-use-escape-keydown": 1.1.0 + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 18450111de16435a6e98661c8530bf87d8dfe51aa8649fea4f420db389642800792bc454669cab010c35cd402e9ae945c882e78e4cf2ce209d9c701f7a9b940f + languageName: node + linkType: hard + "@radix-ui/react-dropdown-menu@npm:^2.0.5": version: 2.0.5 resolution: "@radix-ui/react-dropdown-menu@npm:2.0.5" @@ -12282,6 +12521,19 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-focus-guards@npm:1.1.1": + version: 1.1.1 + resolution: "@radix-ui/react-focus-guards@npm:1.1.1" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: ac8dd31f48fa0500bafd9368f2f06c5a06918dccefa89fa5dc77ca218dc931a094a81ca57f6b181138029822f7acdd5280dceccf5ba4d9263c754fb8f7961879 + languageName: node + linkType: hard + "@radix-ui/react-focus-scope@npm:0.1.4": version: 0.1.4 resolution: "@radix-ui/react-focus-scope@npm:0.1.4" @@ -12333,6 +12585,27 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-focus-scope@npm:1.1.0": + version: 1.1.0 + resolution: "@radix-ui/react-focus-scope@npm:1.1.0" + dependencies: + "@radix-ui/react-compose-refs": 1.1.0 + "@radix-ui/react-primitive": 2.0.0 + "@radix-ui/react-use-callback-ref": 1.1.0 + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: bea6c993752780c46c69f0c21a0fd96f11b9ed7edac23deb0953fbd8524d90938bf4c8060ccac7cad14caba3eb493f2642be7f8933910f4b6fa184666b7fcb40 + languageName: node + linkType: hard + "@radix-ui/react-hover-card@npm:^1.0.7": version: 1.0.7 resolution: "@radix-ui/react-hover-card@npm:1.0.7" @@ -12592,6 +12865,34 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-popper@npm:1.2.0": + version: 1.2.0 + resolution: "@radix-ui/react-popper@npm:1.2.0" + dependencies: + "@floating-ui/react-dom": ^2.0.0 + "@radix-ui/react-arrow": 1.1.0 + "@radix-ui/react-compose-refs": 1.1.0 + "@radix-ui/react-context": 1.1.0 + "@radix-ui/react-primitive": 2.0.0 + "@radix-ui/react-use-callback-ref": 1.1.0 + "@radix-ui/react-use-layout-effect": 1.1.0 + "@radix-ui/react-use-rect": 1.1.0 + "@radix-ui/react-use-size": 1.1.0 + "@radix-ui/rect": 1.1.0 + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 95b2390181abe3296274b3e3836d295dc7b1624462ca88cc283b70c4efa25b1a640ff56cfe2cc8606bfe493f81b57a86345f962d86a027ad673aed58390545c6 + languageName: node + linkType: hard + "@radix-ui/react-portal@npm:0.1.4": version: 0.1.4 resolution: "@radix-ui/react-portal@npm:0.1.4" @@ -12659,6 +12960,26 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-portal@npm:1.1.2": + version: 1.1.2 + resolution: "@radix-ui/react-portal@npm:1.1.2" + dependencies: + "@radix-ui/react-primitive": 2.0.0 + "@radix-ui/react-use-layout-effect": 1.1.0 + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 2f737dc0445f02f512f814ba140227e1a049b3d215d79e22ead412c9befe830292c48a559a8ad1514a474ae8f0c4c43954dfbe294b93a0279d8747d08f7b7924 + languageName: node + linkType: hard + "@radix-ui/react-presence@npm:1.0.0": version: 1.0.0 resolution: "@radix-ui/react-presence@npm:1.0.0" @@ -12932,6 +13253,45 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-select@npm:^2.1.1": + version: 2.1.2 + resolution: "@radix-ui/react-select@npm:2.1.2" + dependencies: + "@radix-ui/number": 1.1.0 + "@radix-ui/primitive": 1.1.0 + "@radix-ui/react-collection": 1.1.0 + "@radix-ui/react-compose-refs": 1.1.0 + "@radix-ui/react-context": 1.1.1 + "@radix-ui/react-direction": 1.1.0 + "@radix-ui/react-dismissable-layer": 1.1.1 + "@radix-ui/react-focus-guards": 1.1.1 + "@radix-ui/react-focus-scope": 1.1.0 + "@radix-ui/react-id": 1.1.0 + "@radix-ui/react-popper": 1.2.0 + "@radix-ui/react-portal": 1.1.2 + "@radix-ui/react-primitive": 2.0.0 + "@radix-ui/react-slot": 1.1.0 + "@radix-ui/react-use-callback-ref": 1.1.0 + "@radix-ui/react-use-controllable-state": 1.1.0 + "@radix-ui/react-use-layout-effect": 1.1.0 + "@radix-ui/react-use-previous": 1.1.0 + "@radix-ui/react-visually-hidden": 1.1.0 + aria-hidden: ^1.1.1 + react-remove-scroll: 2.6.0 + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: cd662a5f0b1cc77dd81df51997ddc1dd47cc0025551e4ffa0c2675c056b3609257096d4f4e27189ddac98771a0191d68323c97d61fa0991d6fae78e708650959 + languageName: node + linkType: hard + "@radix-ui/react-separator@npm:1.0.3": version: 1.0.3 resolution: "@radix-ui/react-separator@npm:1.0.3" @@ -13527,6 +13887,21 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-use-rect@npm:1.1.0": + version: 1.1.0 + resolution: "@radix-ui/react-use-rect@npm:1.1.0" + dependencies: + "@radix-ui/rect": 1.1.0 + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: facc9528af43df3b01952dbb915ff751b5924db2c31d41f053ddea19a7cc5cac5b096c4d7a2059e8f564a3f0d4a95bcd909df8faed52fa01709af27337628e2c + languageName: node + linkType: hard + "@radix-ui/react-use-size@npm:1.0.1": version: 1.0.1 resolution: "@radix-ui/react-use-size@npm:1.0.1" @@ -13618,6 +13993,13 @@ __metadata: languageName: node linkType: hard +"@radix-ui/rect@npm:1.1.0": + version: 1.1.0 + resolution: "@radix-ui/rect@npm:1.1.0" + checksum: 1ad93efbc9fc3b878bae5e8bb26ffa1005235d8b5b9fca8339eb5dbcf7bf53abc9ccd2a8ce128557820168c8600521e48e0ea4dda96aa5f116381f66f46aeda3 + languageName: node + linkType: hard + "@reach/observe-rect@npm:^1.1.0": version: 1.2.0 resolution: "@reach/observe-rect@npm:1.2.0" @@ -17338,6 +17720,15 @@ __metadata: languageName: node linkType: hard +"@types/dompurify@npm:^3.0.5": + version: 3.0.5 + resolution: "@types/dompurify@npm:3.0.5" + dependencies: + "@types/trusted-types": "*" + checksum: ffc34eca6a4536e1c8c16a47cce2623c5a118a9785492e71230052d92933ff096d14326ff449031e8dfaac509413222372d8f2b28786a13159de6241df716185 + languageName: node + linkType: hard + "@types/ejs@npm:^3.1.1": version: 3.1.5 resolution: "@types/ejs@npm:3.1.5" @@ -17416,6 +17807,13 @@ __metadata: languageName: node linkType: hard +"@types/estree@npm:^1.0.6": + version: 1.0.6 + resolution: "@types/estree@npm:1.0.6" + checksum: 8825d6e729e16445d9a1dd2fb1db2edc5ed400799064cd4d028150701031af012ba30d6d03fe9df40f4d7a437d0de6d2b256020152b7b09bde9f2e420afdffd9 + languageName: node + linkType: hard + "@types/express-jwt@npm:0.0.42": version: 0.0.42 resolution: "@types/express-jwt@npm:0.0.42" @@ -17696,6 +18094,13 @@ __metadata: languageName: node linkType: hard +"@types/json-schema@npm:^7.0.15": + version: 7.0.15 + resolution: "@types/json-schema@npm:7.0.15" + checksum: 97ed0cb44d4070aecea772b7b2e2ed971e10c81ec87dd4ecc160322ffa55ff330dace1793489540e3e318d90942064bb697cc0f8989391797792d919737b3b98 + languageName: node + linkType: hard + "@types/json5@npm:^0.0.29": version: 0.0.29 resolution: "@types/json5@npm:0.0.29" @@ -17826,7 +18231,7 @@ __metadata: languageName: node linkType: hard -"@types/luxon@npm:^3.3.7": +"@types/luxon@npm:^3.3.7, @types/luxon@npm:~3.4.0": version: 3.4.2 resolution: "@types/luxon@npm:3.4.2" checksum: 6f92d5bd02e89f310395753506bcd9cef3a56f5940f7a50db2a2b9822bce753553ac767d143cb5b4f9ed5ddd4a84e64f89ff538082ceb4d18739af7781b56925 @@ -18379,6 +18784,13 @@ __metadata: languageName: node linkType: hard +"@types/trusted-types@npm:*": + version: 2.0.7 + resolution: "@types/trusted-types@npm:2.0.7" + checksum: 8e4202766a65877efcf5d5a41b7dd458480b36195e580a3b1085ad21e948bc417d55d6f8af1fd2a7ad008015d4117d5fdfe432731157da3c68678487174e4ba3 + languageName: node + linkType: hard + "@types/trusted-types@npm:^2.0.2": version: 2.0.2 resolution: "@types/trusted-types@npm:2.0.2" @@ -18510,6 +18922,29 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/eslint-plugin@npm:8.8.1": + version: 8.8.1 + resolution: "@typescript-eslint/eslint-plugin@npm:8.8.1" + dependencies: + "@eslint-community/regexpp": ^4.10.0 + "@typescript-eslint/scope-manager": 8.8.1 + "@typescript-eslint/type-utils": 8.8.1 + "@typescript-eslint/utils": 8.8.1 + "@typescript-eslint/visitor-keys": 8.8.1 + graphemer: ^1.4.0 + ignore: ^5.3.1 + natural-compare: ^1.4.0 + ts-api-utils: ^1.3.0 + peerDependencies: + "@typescript-eslint/parser": ^8.0.0 || ^8.0.0-alpha.0 + eslint: ^8.57.0 || ^9.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 1f68a48a98ccf9a97674a4f58ed43624b9eb57b8d99440ecd35f1dfeeb4905d18bc044bd0857f7dbea354d49562ee66f8639133dc273edfc65d3b34ddd58036d + languageName: node + linkType: hard + "@typescript-eslint/eslint-plugin@npm:^5.52.0": version: 5.52.0 resolution: "@typescript-eslint/eslint-plugin@npm:5.52.0" @@ -18534,6 +18969,24 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/parser@npm:8.8.1": + version: 8.8.1 + resolution: "@typescript-eslint/parser@npm:8.8.1" + dependencies: + "@typescript-eslint/scope-manager": 8.8.1 + "@typescript-eslint/types": 8.8.1 + "@typescript-eslint/typescript-estree": 8.8.1 + "@typescript-eslint/visitor-keys": 8.8.1 + debug: ^4.3.4 + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: d3b6d5549533a09826a1b13be281c9af2d222bd41087d9bdafffe6db0cd65c74dba2a799486cb4d42b39c114eee734f989b13966a1d84a42c453701ed4da5095 + languageName: node + linkType: hard + "@typescript-eslint/parser@npm:^5.4.2 || ^6.0.0": version: 6.21.0 resolution: "@typescript-eslint/parser@npm:6.21.0" @@ -18616,6 +19069,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/scope-manager@npm:8.8.1": + version: 8.8.1 + resolution: "@typescript-eslint/scope-manager@npm:8.8.1" + dependencies: + "@typescript-eslint/types": 8.8.1 + "@typescript-eslint/visitor-keys": 8.8.1 + checksum: 08527c75ac99192d86e4c93bf3c0628f0ec63f2337a4f7e7f9fab17a6a37b396dc1a3589ea291fcdd0f2c7c0874b4d18e16ace977e16234b4bcc27926796ea4d + languageName: node + linkType: hard + "@typescript-eslint/type-utils@npm:5.52.0": version: 5.52.0 resolution: "@typescript-eslint/type-utils@npm:5.52.0" @@ -18633,6 +19096,21 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/type-utils@npm:8.8.1": + version: 8.8.1 + resolution: "@typescript-eslint/type-utils@npm:8.8.1" + dependencies: + "@typescript-eslint/typescript-estree": 8.8.1 + "@typescript-eslint/utils": 8.8.1 + debug: ^4.3.4 + ts-api-utils: ^1.3.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 2674288fcf99bda0439ec60b42da8fbc9cc2f827c41bbef7f4687beeb3d24a09fbc50897d7f090743830a00cf4e018a3cec7847842bf58d83b70a42203898278 + languageName: node + linkType: hard + "@typescript-eslint/types@npm:5.48.0": version: 5.48.0 resolution: "@typescript-eslint/types@npm:5.48.0" @@ -18661,6 +19139,13 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/types@npm:8.8.1": + version: 8.8.1 + resolution: "@typescript-eslint/types@npm:8.8.1" + checksum: 271d0dc55743d63e038c1476b47aee28db96029138bd1ace5cd16a12e1c32819b3fa0e53a9a26fd548e463ed6cdb3caf4dfd643cb7c7fc2004a624efd6e9d17e + languageName: node + linkType: hard + "@typescript-eslint/typescript-estree@npm:5.48.0": version: 5.48.0 resolution: "@typescript-eslint/typescript-estree@npm:5.48.0" @@ -18734,6 +19219,25 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/typescript-estree@npm:8.8.1": + version: 8.8.1 + resolution: "@typescript-eslint/typescript-estree@npm:8.8.1" + dependencies: + "@typescript-eslint/types": 8.8.1 + "@typescript-eslint/visitor-keys": 8.8.1 + debug: ^4.3.4 + fast-glob: ^3.3.2 + is-glob: ^4.0.3 + minimatch: ^9.0.4 + semver: ^7.6.0 + ts-api-utils: ^1.3.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 893795fd562da8babcf6eca36e1ea1a39920200dbd15e826120a3482458be6648f0d138c71c4c840aded0feb7528272c0b9033d57fba978756a6d2730cec5ca6 + languageName: node + linkType: hard + "@typescript-eslint/utils@npm:5.52.0, @typescript-eslint/utils@npm:^5.52.0": version: 5.52.0 resolution: "@typescript-eslint/utils@npm:5.52.0" @@ -18752,6 +19256,20 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/utils@npm:8.8.1": + version: 8.8.1 + resolution: "@typescript-eslint/utils@npm:8.8.1" + dependencies: + "@eslint-community/eslint-utils": ^4.4.0 + "@typescript-eslint/scope-manager": 8.8.1 + "@typescript-eslint/types": 8.8.1 + "@typescript-eslint/typescript-estree": 8.8.1 + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + checksum: cf31d18edb646f6c864239f591fcff322ae315c27337d2f07f71f1a859e58102467923810ef165acc6fb147be857b319087fb82622d93c9ca49042872f576f80 + languageName: node + linkType: hard + "@typescript-eslint/visitor-keys@npm:5.48.0": version: 5.48.0 resolution: "@typescript-eslint/visitor-keys@npm:5.48.0" @@ -18792,6 +19310,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/visitor-keys@npm:8.8.1": + version: 8.8.1 + resolution: "@typescript-eslint/visitor-keys@npm:8.8.1" + dependencies: + "@typescript-eslint/types": 8.8.1 + eslint-visitor-keys: ^3.4.3 + checksum: c5861ae79fb3f190e7882dcdf7735799249c73804f0e52e2ac5a5000bc33cbc44c4e3a0800db7aa8d5ee5c43393495eec7a7c7c963ceafc122e8472b479b32f5 + languageName: node + linkType: hard + "@ungap/structured-clone@npm:^1.0.0, @ungap/structured-clone@npm:^1.2.0": version: 1.2.0 resolution: "@ungap/structured-clone@npm:1.2.0" @@ -19596,6 +20124,15 @@ __metadata: languageName: node linkType: hard +"acorn@npm:^8.12.0": + version: 8.12.1 + resolution: "acorn@npm:8.12.1" + bin: + acorn: bin/acorn + checksum: 677880034aee5bdf7434cc2d25b641d7bedb0b5ef47868a78dadabedccf58e1c5457526d9d8249cd253f2df087e081c3fe7d903b448d8e19e5131a3065b83c07 + languageName: node + linkType: hard + "acorn@npm:^8.5.0": version: 8.7.1 resolution: "acorn@npm:8.7.1" @@ -20191,6 +20728,20 @@ __metadata: languageName: node linkType: hard +"array-includes@npm:^3.1.8": + version: 3.1.8 + resolution: "array-includes@npm:3.1.8" + dependencies: + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-object-atoms: ^1.0.0 + get-intrinsic: ^1.2.4 + is-string: ^1.0.7 + checksum: eb39ba5530f64e4d8acab39297c11c1c5be2a4ea188ab2b34aba5fb7224d918f77717a9d57a3e2900caaa8440e59431bdaf5c974d5212ef65d97f132e38e2d91 + languageName: node + linkType: hard + "array-timsort@npm:^1.0.3": version: 1.0.3 resolution: "array-timsort@npm:1.0.3" @@ -20231,6 +20782,20 @@ __metadata: languageName: node linkType: hard +"array.prototype.findlast@npm:^1.2.5": + version: 1.2.5 + resolution: "array.prototype.findlast@npm:1.2.5" + dependencies: + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-errors: ^1.3.0 + es-object-atoms: ^1.0.0 + es-shim-unscopables: ^1.0.2 + checksum: 83ce4ad95bae07f136d316f5a7c3a5b911ac3296c3476abe60225bc4a17938bf37541972fcc37dd5adbc99cbb9c928c70bbbfc1c1ce549d41a415144030bb446 + languageName: node + linkType: hard + "array.prototype.findlastindex@npm:^1.2.3": version: 1.2.4 resolution: "array.prototype.findlastindex@npm:1.2.4" @@ -20367,6 +20932,19 @@ __metadata: languageName: node linkType: hard +"array.prototype.tosorted@npm:^1.1.4": + version: 1.1.4 + resolution: "array.prototype.tosorted@npm:1.1.4" + dependencies: + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.3 + es-errors: ^1.3.0 + es-shim-unscopables: ^1.0.2 + checksum: e4142d6f556bcbb4f393c02e7dbaea9af8f620c040450c2be137c9cbbd1a17f216b9c688c5f2c08fbb038ab83f55993fa6efdd9a05881d84693c7bcb5422127a + languageName: node + linkType: hard + "arraybuffer.prototype.slice@npm:^1.0.2": version: 1.0.2 resolution: "arraybuffer.prototype.slice@npm:1.0.2" @@ -20785,7 +21363,7 @@ __metadata: languageName: node linkType: hard -"axios@npm:^1.6.1": +"axios@npm:^1.6.1, axios@npm:^1.6.8": version: 1.7.7 resolution: "axios@npm:1.7.7" dependencies: @@ -21148,7 +21726,7 @@ __metadata: languageName: node linkType: hard -"big-integer@npm:^1.6.16, big-integer@npm:^1.6.44": +"big-integer@npm:^1.6.44": version: 1.6.52 resolution: "big-integer@npm:1.6.52" checksum: 6e86885787a20fed96521958ae9086960e4e4b5e74d04f3ef7513d4d0ad631a9f3bde2730fc8aaa4b00419fc865f6ec573e5320234531ef37505da7da192c40b @@ -21176,6 +21754,15 @@ __metadata: languageName: node linkType: hard +"bindings@npm:^1.5.0": + version: 1.5.0 + resolution: "bindings@npm:1.5.0" + dependencies: + file-uri-to-path: 1.0.0 + checksum: 65b6b48095717c2e6105a021a7da4ea435aa8d3d3cd085cb9e85bcb6e5773cf318c4745c3f7c504412855940b585bdf9b918236612a1c7a7942491de176f1ae7 + languageName: node + linkType: hard + "biskviit@npm:1.0.1": version: 1.0.1 resolution: "biskviit@npm:1.0.1" @@ -21216,7 +21803,7 @@ __metadata: languageName: node linkType: hard -"bluebird@npm:^3.4.6, bluebird@npm:^3.7.2": +"bluebird@npm:^3.7.2": version: 3.7.2 resolution: "bluebird@npm:3.7.2" checksum: 869417503c722e7dc54ca46715f70e15f4d9c602a423a02c825570862d12935be59ed9c7ba34a9b31f186c017c23cac6b54e35446f8353059c101da73eac22ef @@ -21367,22 +21954,6 @@ __metadata: languageName: node linkType: hard -"broadcast-channel@npm:^3.4.1": - version: 3.7.0 - resolution: "broadcast-channel@npm:3.7.0" - dependencies: - "@babel/runtime": ^7.7.2 - detect-node: ^2.1.0 - js-sha3: 0.8.0 - microseconds: 0.2.0 - nano-time: 1.0.0 - oblivious-set: 1.0.0 - rimraf: 3.0.2 - unload: 2.2.0 - checksum: 803794c48dcce7f03aca69797430bd8b1c4cfd70b7de22079cd89567eeffaa126a1db98c7c2d86af8131d9bb41ed367c0fef96dfb446151c927b831572c621fc - languageName: node - linkType: hard - "brorand@npm:^1.0.1, brorand@npm:^1.1.0": version: 1.1.0 resolution: "brorand@npm:1.1.0" @@ -21857,6 +22428,7 @@ __metadata: "@snaplet/copycat": ^4.1.0 "@testing-library/jest-dom": ^5.16.5 "@testing-library/react": ^16.0.1 + "@types/dompurify": ^3.0.5 "@types/jsdom": ^21.1.3 "@types/jsonwebtoken": ^9.0.3 "@vercel/functions": ^1.4.0 @@ -22104,6 +22676,15 @@ __metadata: languageName: node linkType: hard +"castable-video@npm:~1.1.0": + version: 1.1.0 + resolution: "castable-video@npm:1.1.0" + dependencies: + custom-media-element: ~1.3.2 + checksum: 0b7280140e2e855f66ad824c8352d8422695f3a0195757341e8c0b5828df9c0279af70154d7ef514e9d7849814b74625c4df7a652853bd624ecb205a232c295e + languageName: node + linkType: hard + "ccount@npm:^2.0.0": version: 2.0.1 resolution: "ccount@npm:2.0.1" @@ -22564,6 +23145,15 @@ __metadata: languageName: node linkType: hard +"class-variance-authority@npm:^0.7.0": + version: 0.7.0 + resolution: "class-variance-authority@npm:0.7.0" + dependencies: + clsx: 2.0.0 + checksum: e7fd1fab433ef06f52a1b7b241b70b4a185864deef199d3b0a2c3412f1cc179517288264c383f3b971a00d76811625fc8f7ffe709e6170219e88cd7368f08a20 + languageName: node + linkType: hard + "classnames@npm:^2.2.5, classnames@npm:^2.2.6": version: 2.3.2 resolution: "classnames@npm:2.3.2" @@ -22836,6 +23426,13 @@ __metadata: languageName: node linkType: hard +"clsx@npm:2.0.0": + version: 2.0.0 + resolution: "clsx@npm:2.0.0" + checksum: a2cfb2351b254611acf92faa0daf15220f4cd648bdf96ce369d729813b85336993871a4bf6978ddea2b81b5a130478339c20d9d0b5c6fc287e5147f0c059276e + languageName: node + linkType: hard + "clsx@npm:^1.1.1": version: 1.1.1 resolution: "clsx@npm:1.1.1" @@ -23797,6 +24394,16 @@ __metadata: languageName: node linkType: hard +"cron@npm:^3.1.7": + version: 3.1.7 + resolution: "cron@npm:3.1.7" + dependencies: + "@types/luxon": ~3.4.0 + luxon: ~3.4.0 + checksum: d98ee5297543c138221d96dd49270bf6576db80134e6041f4ce4a3c0cb6060863d76910209b34fee66fbf134461449ec3bd283d6a76d1c50da220cde7fc10c65 + languageName: node + linkType: hard + "cross-env@npm:^7.0.3": version: 7.0.3 resolution: "cross-env@npm:7.0.3" @@ -24143,6 +24750,13 @@ __metadata: languageName: node linkType: hard +"custom-media-element@npm:~1.3.1, custom-media-element@npm:~1.3.2": + version: 1.3.2 + resolution: "custom-media-element@npm:1.3.2" + checksum: 9ec2ff88c3c5ba7d20b9484c0359b4cfe08ad6804f3116934ffbae2f2e0e04d2a832beb6f0bec56027a969ab366727d217406f750890613c988de6de5330cb4f + languageName: node + linkType: hard + "d3-array@npm:2 - 3, d3-array@npm:2.10.0 - 3, d3-array@npm:^3.1.6": version: 3.2.3 resolution: "d3-array@npm:3.2.3" @@ -24405,6 +25019,16 @@ __metadata: languageName: node linkType: hard +"deasync@npm:^0.1.30": + version: 0.1.30 + resolution: "deasync@npm:0.1.30" + dependencies: + bindings: ^1.5.0 + node-addon-api: ^1.7.1 + checksum: 1faeb20e1ec1c6ebde35a44f309e1b544804c782b25b513536e5a7313f89a45eb1565f228d06a1a233b285673137731822f81c6629a52a729f4fffb94f433549 + languageName: node + linkType: hard + "debounce-fn@npm:^4.0.0": version: 4.0.0 resolution: "debounce-fn@npm:4.0.0" @@ -24810,6 +25434,16 @@ __metadata: languageName: node linkType: hard +"des.js@npm:^1.1.0": + version: 1.1.0 + resolution: "des.js@npm:1.1.0" + dependencies: + inherits: ^2.0.1 + minimalistic-assert: ^1.0.0 + checksum: 0e9c1584b70d31e20f20a613fc9ef60fbc6a147dfec9e448a168794a4b97ac04d8dc47ea008f1fa93b0f8aaf7c1ead632a5e59ce1913a6079d2d244c9f5ebe33 + languageName: node + linkType: hard + "destroy@npm:1.2.0": version: 1.2.0 resolution: "destroy@npm:1.2.0" @@ -24859,13 +25493,6 @@ __metadata: languageName: node linkType: hard -"detect-node@npm:^2.0.4, detect-node@npm:^2.1.0": - version: 2.1.0 - resolution: "detect-node@npm:2.1.0" - checksum: 832184ec458353e41533ac9c622f16c19f7c02d8b10c303dfd3a756f56be93e903616c0bb2d4226183c9351c15fc0b3dba41a17a2308262afabcfa3776e6ae6e - languageName: node - linkType: hard - "detect-package-manager@npm:^2.0.1": version: 2.0.1 resolution: "detect-package-manager@npm:2.0.1" @@ -25113,6 +25740,13 @@ __metadata: languageName: node linkType: hard +"dompurify@npm:^3.1.7": + version: 3.1.7 + resolution: "dompurify@npm:3.1.7" + checksum: 0a9b811bbc94f3dba60cf6486962362b0f1a5b4ab789f5e1cbd4749b6ba1a1fad190a677a962dc8850ce28764424765fe425e9d6508e4e93ba648ef15d54bc24 + languageName: node + linkType: hard + "domutils@npm:^2.5.2, domutils@npm:^2.8.0": version: 2.8.0 resolution: "domutils@npm:2.8.0" @@ -25414,6 +26048,34 @@ __metadata: languageName: node linkType: hard +"embla-carousel-react@npm:^8.1.8": + version: 8.3.0 + resolution: "embla-carousel-react@npm:8.3.0" + dependencies: + embla-carousel: 8.3.0 + embla-carousel-reactive-utils: 8.3.0 + peerDependencies: + react: ^16.8.0 || ^17.0.1 || ^18.0.0 + checksum: 414bf10ea5b983fdf2f64aeb7806ebaf69b2790617c8ff13b13e7bb6cc4671f243544a786fc6be33dde18965513402e4c4d78474ca928f4031af7db9e276be26 + languageName: node + linkType: hard + +"embla-carousel-reactive-utils@npm:8.3.0": + version: 8.3.0 + resolution: "embla-carousel-reactive-utils@npm:8.3.0" + peerDependencies: + embla-carousel: 8.3.0 + checksum: 687eb69c5db4bf1c9fc09090ea4441e60ab94dd04de7b8e69139eff26fed3d9ba62e6804cc1c44616838c14924fe1b07e31864222a6106365c7129fd95d7d741 + languageName: node + linkType: hard + +"embla-carousel@npm:8.3.0": + version: 8.3.0 + resolution: "embla-carousel@npm:8.3.0" + checksum: c2d3c89c93e105133e6931dfdba5899f44f01b32ea0fa331999030150819a2a51c4699df49b69540bc935b63def219f7484f6ca363becaacaf7609e863e39b72 + languageName: node + linkType: hard + "emittery@npm:^0.13.1": version: 0.13.1 resolution: "emittery@npm:0.13.1" @@ -25673,6 +26335,60 @@ __metadata: languageName: node linkType: hard +"es-abstract@npm:^1.17.5, es-abstract@npm:^1.23.3": + version: 1.23.3 + resolution: "es-abstract@npm:1.23.3" + dependencies: + array-buffer-byte-length: ^1.0.1 + arraybuffer.prototype.slice: ^1.0.3 + available-typed-arrays: ^1.0.7 + call-bind: ^1.0.7 + data-view-buffer: ^1.0.1 + data-view-byte-length: ^1.0.1 + data-view-byte-offset: ^1.0.0 + es-define-property: ^1.0.0 + es-errors: ^1.3.0 + es-object-atoms: ^1.0.0 + es-set-tostringtag: ^2.0.3 + es-to-primitive: ^1.2.1 + function.prototype.name: ^1.1.6 + get-intrinsic: ^1.2.4 + get-symbol-description: ^1.0.2 + globalthis: ^1.0.3 + gopd: ^1.0.1 + has-property-descriptors: ^1.0.2 + has-proto: ^1.0.3 + has-symbols: ^1.0.3 + hasown: ^2.0.2 + internal-slot: ^1.0.7 + is-array-buffer: ^3.0.4 + is-callable: ^1.2.7 + is-data-view: ^1.0.1 + is-negative-zero: ^2.0.3 + is-regex: ^1.1.4 + is-shared-array-buffer: ^1.0.3 + is-string: ^1.0.7 + is-typed-array: ^1.1.13 + is-weakref: ^1.0.2 + object-inspect: ^1.13.1 + object-keys: ^1.1.1 + object.assign: ^4.1.5 + regexp.prototype.flags: ^1.5.2 + safe-array-concat: ^1.1.2 + safe-regex-test: ^1.0.3 + string.prototype.trim: ^1.2.9 + string.prototype.trimend: ^1.0.8 + string.prototype.trimstart: ^1.0.8 + typed-array-buffer: ^1.0.2 + typed-array-byte-length: ^1.0.1 + typed-array-byte-offset: ^1.0.2 + typed-array-length: ^1.0.6 + unbox-primitive: ^1.0.2 + which-typed-array: ^1.1.15 + checksum: f840cf161224252512f9527306b57117192696571e07920f777cb893454e32999206198b4f075516112af6459daca282826d1735c450528470356d09eff3a9ae + languageName: node + linkType: hard + "es-abstract@npm:^1.19.0, es-abstract@npm:^1.19.1": version: 1.19.2 resolution: "es-abstract@npm:1.19.2" @@ -25997,6 +26713,28 @@ __metadata: languageName: node linkType: hard +"es-iterator-helpers@npm:^1.0.19": + version: 1.1.0 + resolution: "es-iterator-helpers@npm:1.1.0" + dependencies: + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.3 + es-errors: ^1.3.0 + es-set-tostringtag: ^2.0.3 + function-bind: ^1.1.2 + get-intrinsic: ^1.2.4 + globalthis: ^1.0.4 + has-property-descriptors: ^1.0.2 + has-proto: ^1.0.3 + has-symbols: ^1.0.3 + internal-slot: ^1.0.7 + iterator.prototype: ^1.1.3 + safe-array-concat: ^1.1.2 + checksum: 4ba3a32ab7ba05b85f0ae30604feeb8ffd801fe762e9df9577bd220a96b9eaa2e90af8e6bdc498e523051f293955e2f7d2bddd34de71e1428a1b8ff3fd961016 + languageName: node + linkType: hard + "es-module-lexer@npm:^1.2.1, es-module-lexer@npm:^1.4.1": version: 1.4.1 resolution: "es-module-lexer@npm:1.4.1" @@ -26756,6 +27494,34 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-react@npm:^7.35.0": + version: 7.37.1 + resolution: "eslint-plugin-react@npm:7.37.1" + dependencies: + array-includes: ^3.1.8 + array.prototype.findlast: ^1.2.5 + array.prototype.flatmap: ^1.3.2 + array.prototype.tosorted: ^1.1.4 + doctrine: ^2.1.0 + es-iterator-helpers: ^1.0.19 + estraverse: ^5.3.0 + hasown: ^2.0.2 + jsx-ast-utils: ^2.4.1 || ^3.0.0 + minimatch: ^3.1.2 + object.entries: ^1.1.8 + object.fromentries: ^2.0.8 + object.values: ^1.2.0 + prop-types: ^15.8.1 + resolve: ^2.0.0-next.5 + semver: ^6.3.1 + string.prototype.matchall: ^4.0.11 + string.prototype.repeat: ^1.0.0 + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 + checksum: 22d1bdf0dd4cdbf8c57ce563c58d43c5f5e1da0b08d27d0a69d7126d9e8afcb74a5befae97dab4019b4c6029ae617b6a0af1709cb9e0439d5757b01b392d2ca7 + languageName: node + linkType: hard + "eslint-plugin-turbo@npm:0.0.7": version: 0.0.7 resolution: "eslint-plugin-turbo@npm:0.0.7" @@ -26826,6 +27592,16 @@ __metadata: languageName: node linkType: hard +"eslint-scope@npm:^8.1.0": + version: 8.1.0 + resolution: "eslint-scope@npm:8.1.0" + dependencies: + esrecurse: ^4.3.0 + estraverse: ^5.2.0 + checksum: 3ce9392ec74f35f84eddad7755941cb5f7e3a1bc53cf902e95e541384ef78b604bec1489933f37c663e4686b36c31533d06cf0842be9a729a680c489efce7acb + languageName: node + linkType: hard + "eslint-utils@npm:^3.0.0": version: 3.0.0 resolution: "eslint-utils@npm:3.0.0" @@ -26858,6 +27634,13 @@ __metadata: languageName: node linkType: hard +"eslint-visitor-keys@npm:^4.1.0": + version: 4.1.0 + resolution: "eslint-visitor-keys@npm:4.1.0" + checksum: b5d53725df14a6a225fd74d5e687f5f0547b0aaa3e1963ab6f4acb8dc80f99ad0bec11148e14b4a67de024dde7b4449e7e4c0b1524de605955dee7eefcdd7824 + languageName: node + linkType: hard + "eslint@npm:^8": version: 8.57.0 resolution: "eslint@npm:8.57.0" @@ -26955,6 +27738,56 @@ __metadata: languageName: node linkType: hard +"eslint@npm:^9.9.0": + version: 9.12.0 + resolution: "eslint@npm:9.12.0" + dependencies: + "@eslint-community/eslint-utils": ^4.2.0 + "@eslint-community/regexpp": ^4.11.0 + "@eslint/config-array": ^0.18.0 + "@eslint/core": ^0.6.0 + "@eslint/eslintrc": ^3.1.0 + "@eslint/js": 9.12.0 + "@eslint/plugin-kit": ^0.2.0 + "@humanfs/node": ^0.16.5 + "@humanwhocodes/module-importer": ^1.0.1 + "@humanwhocodes/retry": ^0.3.1 + "@types/estree": ^1.0.6 + "@types/json-schema": ^7.0.15 + ajv: ^6.12.4 + chalk: ^4.0.0 + cross-spawn: ^7.0.2 + debug: ^4.3.2 + escape-string-regexp: ^4.0.0 + eslint-scope: ^8.1.0 + eslint-visitor-keys: ^4.1.0 + espree: ^10.2.0 + esquery: ^1.5.0 + esutils: ^2.0.2 + fast-deep-equal: ^3.1.3 + file-entry-cache: ^8.0.0 + find-up: ^5.0.0 + glob-parent: ^6.0.2 + ignore: ^5.2.0 + imurmurhash: ^0.1.4 + is-glob: ^4.0.0 + json-stable-stringify-without-jsonify: ^1.0.1 + lodash.merge: ^4.6.2 + minimatch: ^3.1.2 + natural-compare: ^1.4.0 + optionator: ^0.9.3 + text-table: ^0.2.0 + peerDependencies: + jiti: "*" + peerDependenciesMeta: + jiti: + optional: true + bin: + eslint: bin/eslint.js + checksum: cf0dbe242268ede8cc13c04566973077c4feea21cf94a2eacba7ad43f566b2dee0d8f1af32ccb46d30dbcd78a7274828199b8aa9a7b1c708d7a71085b686385c + languageName: node + linkType: hard + "esm@npm:^3.2.25": version: 3.2.25 resolution: "esm@npm:3.2.25" @@ -26962,6 +27795,17 @@ __metadata: languageName: node linkType: hard +"espree@npm:^10.0.1, espree@npm:^10.2.0": + version: 10.2.0 + resolution: "espree@npm:10.2.0" + dependencies: + acorn: ^8.12.0 + acorn-jsx: ^5.3.2 + eslint-visitor-keys: ^4.1.0 + checksum: 16ee75c2f6029622a70a675ad8989fffc6f7199265d07af516a11e4adc9eb2d03866fceff33f1a081c42621df79871e508f8fc8fe5855eac2de925b58196711b + languageName: node + linkType: hard + "espree@npm:^9.4.0": version: 9.4.1 resolution: "espree@npm:9.4.1" @@ -27012,6 +27856,15 @@ __metadata: languageName: node linkType: hard +"esquery@npm:^1.5.0": + version: 1.6.0 + resolution: "esquery@npm:1.6.0" + dependencies: + estraverse: ^5.1.0 + checksum: 08ec4fe446d9ab27186da274d979558557fbdbbd10968fa9758552482720c54152a5640e08b9009e5a30706b66aba510692054d4129d32d0e12e05bbc0b96fb2 + languageName: node + linkType: hard + "esrecurse@npm:^4.3.0": version: 4.3.0 resolution: "esrecurse@npm:4.3.0" @@ -27690,7 +28543,7 @@ __metadata: languageName: node linkType: hard -"fetch@npm:^1.0.1, fetch@npm:^1.1.0": +"fetch@npm:^1.1.0": version: 1.1.0 resolution: "fetch@npm:1.1.0" dependencies: @@ -27773,6 +28626,15 @@ __metadata: languageName: node linkType: hard +"file-entry-cache@npm:^8.0.0": + version: 8.0.0 + resolution: "file-entry-cache@npm:8.0.0" + dependencies: + flat-cache: ^4.0.0 + checksum: f67802d3334809048c69b3d458f672e1b6d26daefda701761c81f203b80149c35dea04d78ea4238969dd617678e530876722a0634c43031a0957f10cc3ed190f + languageName: node + linkType: hard + "file-system-cache@npm:2.3.0": version: 2.3.0 resolution: "file-system-cache@npm:2.3.0" @@ -27790,6 +28652,13 @@ __metadata: languageName: node linkType: hard +"file-uri-to-path@npm:1.0.0": + version: 1.0.0 + resolution: "file-uri-to-path@npm:1.0.0" + checksum: b648580bdd893a008c92c7ecc96c3ee57a5e7b6c4c18a9a09b44fb5d36d79146f8e442578bc0e173dc027adf3987e254ba1dfd6e3ec998b7c282873010502144 + languageName: node + linkType: hard + "filelist@npm:^1.0.4": version: 1.0.4 resolution: "filelist@npm:1.0.4" @@ -27962,6 +28831,16 @@ __metadata: languageName: node linkType: hard +"flat-cache@npm:^4.0.0": + version: 4.0.1 + resolution: "flat-cache@npm:4.0.1" + dependencies: + flatted: ^3.2.9 + keyv: ^4.5.4 + checksum: 899fc86bf6df093547d76e7bfaeb900824b869d7d457d02e9b8aae24836f0a99fbad79328cfd6415ee8908f180699bf259dc7614f793447cb14f707caf5996f6 + languageName: node + linkType: hard + "flatted@npm:^3.1.0": version: 3.2.5 resolution: "flatted@npm:3.2.5" @@ -27969,7 +28848,7 @@ __metadata: languageName: node linkType: hard -"flatted@npm:^3.3.1": +"flatted@npm:^3.2.9, flatted@npm:^3.3.1": version: 3.3.1 resolution: "flatted@npm:3.3.1" checksum: 85ae7181650bb728c221e7644cbc9f4bf28bc556f2fc89bb21266962bdf0ce1029cc7acc44bb646cd469d9baac7c317f64e841c4c4c00516afa97320cdac7f94 @@ -28320,6 +29199,26 @@ __metadata: languageName: node linkType: hard +"framer-motion@npm:^11.0.25": + version: 11.11.7 + resolution: "framer-motion@npm:11.11.7" + dependencies: + tslib: ^2.4.0 + peerDependencies: + "@emotion/is-prop-valid": "*" + react: ^18.0.0 + react-dom: ^18.0.0 + peerDependenciesMeta: + "@emotion/is-prop-valid": + optional: true + react: + optional: true + react-dom: + optional: true + checksum: dc8d97a75c15a785238d78e5c2e6a405c7d9c6b88aee04f94e944cfaee34f247241ff3ad9eb05ceca16add095c618665a6e7a2b4820c8c34c51ad3bcb6c6955b + languageName: node + linkType: hard + "fresh@npm:0.5.2, fresh@npm:^0.5.2": version: 0.5.2 resolution: "fresh@npm:0.5.2" @@ -29088,6 +29987,20 @@ __metadata: languageName: node linkType: hard +"globals@npm:^14.0.0": + version: 14.0.0 + resolution: "globals@npm:14.0.0" + checksum: 534b8216736a5425737f59f6e6a5c7f386254560c9f41d24a9227d60ee3ad4a9e82c5b85def0e212e9d92162f83a92544be4c7fd4c902cb913736c10e08237ac + languageName: node + linkType: hard + +"globals@npm:^15.9.0": + version: 15.11.0 + resolution: "globals@npm:15.11.0" + checksum: ef32d5ef987f3d4b47fc2e389a0b235f6a46f605160c4e405722fd7b576106ca407cb867e66fd1e0fc43b631800e2e2e71847f37691026d813f96f40339da702 + languageName: node + linkType: hard + "globalthis@npm:^1.0.3": version: 1.0.3 resolution: "globalthis@npm:1.0.3" @@ -29097,6 +30010,16 @@ __metadata: languageName: node linkType: hard +"globalthis@npm:^1.0.4": + version: 1.0.4 + resolution: "globalthis@npm:1.0.4" + dependencies: + define-properties: ^1.2.1 + gopd: ^1.0.1 + checksum: 39ad667ad9f01476474633a1834a70842041f70a55571e8dcef5fb957980a92da5022db5430fca8aecc5d47704ae30618c0bc877a579c70710c904e9ef06108a + languageName: node + linkType: hard + "globalyzer@npm:0.1.0": version: 0.1.0 resolution: "globalyzer@npm:0.1.0" @@ -29995,6 +30918,13 @@ __metadata: languageName: node linkType: hard +"hls.js@npm:~1.5.11": + version: 1.5.16 + resolution: "hls.js@npm:1.5.16" + checksum: 0121feee70837006f75c6e7a42dbfff63fe83b85a932fb8c9b4f186098f1cd0d72868dd1e5cd168e797e4e92a4afc889f8efb141fd2de8b35c98f9fa29340a39 + languageName: node + linkType: hard + "hmac-drbg@npm:^1.0.1": version: 1.0.1 resolution: "hmac-drbg@npm:1.0.1" @@ -30161,6 +31091,24 @@ __metadata: languageName: node linkType: hard +"http-cookie-agent@npm:^5.0.4": + version: 5.0.4 + resolution: "http-cookie-agent@npm:5.0.4" + dependencies: + agent-base: ^7.1.0 + peerDependencies: + deasync: ^0.1.26 + tough-cookie: ^4.0.0 + undici: ^5.11.0 + peerDependenciesMeta: + deasync: + optional: true + undici: + optional: true + checksum: c136529cc402d0d7b8d3ae644a41f6ebc986951e0add60efbb7faf6cee74bf0895a25f8827fc362e4dc9238f937bb64d0c144e0236fd5af6cbb48849bbf327cc + languageName: node + linkType: hard + "http-errors@npm:1.7.3": version: 1.7.3 resolution: "http-errors@npm:1.7.3" @@ -30598,6 +31546,13 @@ __metadata: languageName: node linkType: hard +"ignore@npm:^5.3.1": + version: 5.3.2 + resolution: "ignore@npm:5.3.2" + checksum: 2acfd32a573260ea522ea0bfeff880af426d68f6831f973129e2ba7363f422923cf53aab62f8369cbf4667c7b25b6f8a3761b34ecdb284ea18e87a5262a865be + languageName: node + linkType: hard + "image-q@npm:^4.0.0": version: 4.0.0 resolution: "image-q@npm:4.0.0" @@ -32238,6 +33193,19 @@ __metadata: languageName: node linkType: hard +"iterator.prototype@npm:^1.1.3": + version: 1.1.3 + resolution: "iterator.prototype@npm:1.1.3" + dependencies: + define-properties: ^1.2.1 + get-intrinsic: ^1.2.1 + has-symbols: ^1.0.3 + reflect.getprototypeof: ^1.0.4 + set-function-name: ^2.0.1 + checksum: 7d2a1f8bcbba7b76f72e956faaf7b25405f4de54430c9d099992e6fb9d571717c3044604e8cdfb8e624cb881337d648030ee8b1541d544af8b338835e3f47ebe + languageName: node + linkType: hard + "jackspeak@npm:^2.0.3, jackspeak@npm:^2.3.5": version: 2.3.6 resolution: "jackspeak@npm:2.3.6" @@ -32950,13 +33918,6 @@ __metadata: languageName: node linkType: hard -"js-sha3@npm:0.8.0": - version: 0.8.0 - resolution: "js-sha3@npm:0.8.0" - checksum: 75df77c1fc266973f06cce8309ce010e9e9f07ec35ab12022ed29b7f0d9c8757f5a73e1b35aa24840dced0dea7059085aa143d817aea9e188e2a80d569d9adce - languageName: node - linkType: hard - "js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": version: 4.0.0 resolution: "js-tokens@npm:4.0.0" @@ -33475,7 +34436,7 @@ __metadata: languageName: node linkType: hard -"keyv@npm:^4.0.0, keyv@npm:^4.5.3": +"keyv@npm:^4.0.0, keyv@npm:^4.5.3, keyv@npm:^4.5.4": version: 4.5.4 resolution: "keyv@npm:4.5.4" dependencies: @@ -34523,12 +35484,12 @@ __metadata: languageName: node linkType: hard -"lucide-react@npm:^0.171.0": - version: 0.171.0 - resolution: "lucide-react@npm:0.171.0" +"lucide-react@npm:^0.364.0": + version: 0.364.0 + resolution: "lucide-react@npm:0.364.0" peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 - checksum: 768ffe368c52a518ee339203d86ff4479989ab4d79c0716f721900c4bb7392ef6ff7a14807f6a685abd74d27f4c1778170bff77a0ab4c3e06c17944b557d8300 + checksum: 954f6274df46ffa172130d9e60eb630a377435c7dbf0ddb5ceebf284602dde3b99755dcd5c0757e697ee734a32c808a3cd2c25ad88fec1d8f627a2317f00e3e6 languageName: node linkType: hard @@ -34560,7 +35521,7 @@ __metadata: languageName: node linkType: hard -"luxon@npm:^3.2.1, luxon@npm:^3.4.4": +"luxon@npm:^3.2.1, luxon@npm:^3.4.4, luxon@npm:~3.4.0": version: 3.4.4 resolution: "luxon@npm:3.4.4" checksum: 36c1f99c4796ee4bfddf7dc94fa87815add43ebc44c8934c924946260a58512f0fd2743a629302885df7f35ccbd2d13f178c15df046d0e3b6eb71db178f1c60c @@ -34792,16 +35753,6 @@ __metadata: languageName: node linkType: hard -"match-sorter@npm:^6.0.2": - version: 6.3.4 - resolution: "match-sorter@npm:6.3.4" - dependencies: - "@babel/runtime": ^7.23.8 - remove-accents: 0.5.0 - checksum: 950c1600173a639e216947559a389b64258d52f33aea3a6ddb97500589888b83c976a028f731f40bc08d9d8af20de7916992fabb403f38330183a1df44c7634b - languageName: node - linkType: hard - "maxmin@npm:^2.1.0": version: 2.1.0 resolution: "maxmin@npm:2.1.0" @@ -35069,6 +36020,27 @@ __metadata: languageName: node linkType: hard +"media-chrome@npm:^4.1.0": + version: 4.2.0 + resolution: "media-chrome@npm:4.2.0" + checksum: 16a60926adb5e29ba1da3114af72bf842d6187620239e6a4c0a249c15dc09413c85171a5658a28f80c44d19f0c534855931b4d9fba2477803f373e97e578a324 + languageName: node + linkType: hard + +"media-chrome@npm:~4.1.1": + version: 4.1.5 + resolution: "media-chrome@npm:4.1.5" + checksum: 50ba8416f5e6f35dc22f2c30d102a2a8659f7b888919392d511be80e2cd0dd097b0e9eb339ec21d4f6f9ced6d2c81a91c130419977d42b1b928e7e93c9d2ceb1 + languageName: node + linkType: hard + +"media-tracks@npm:~0.3.2": + version: 0.3.3 + resolution: "media-tracks@npm:0.3.3" + checksum: 4795af3f171d7ad3a68d1ac1c1e8166a735244fe57d3fc0ec53b1c7410799e524756fc0bfb389632aebb148436b03baade36ca34a3f5377776c3968f6d2cc580 + languageName: node + linkType: hard + "media-typer@npm:0.3.0": version: 0.3.0 resolution: "media-typer@npm:0.3.0" @@ -35710,13 +36682,6 @@ __metadata: languageName: node linkType: hard -"microseconds@npm:0.2.0": - version: 0.2.0 - resolution: "microseconds@npm:0.2.0" - checksum: 22bfa8553f92c7d95afff6de0aeb2aecf750680d41b8c72b02098ccc5bbbb0a384380ff539292dbd3788f5dfc298682f9d38a2b4c101f5ee2c9471d53934c5fa - languageName: node - linkType: hard - "miller-rabin@npm:^4.0.0": version: 4.0.1 resolution: "miller-rabin@npm:4.0.1" @@ -35880,7 +36845,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^9.0.5": +"minimatch@npm:^9.0.4, minimatch@npm:^9.0.5": version: 9.0.5 resolution: "minimatch@npm:9.0.5" dependencies: @@ -36028,6 +36993,13 @@ __metadata: languageName: node linkType: hard +"mitt@npm:^3.0.1": + version: 3.0.1 + resolution: "mitt@npm:3.0.1" + checksum: b55a489ac9c2949ab166b7f060601d3b6d893a852515ae9eca4e11df01c013876df777ea109317622b5c1c60e8aae252558e33c8c94e14124db38f64a39614b1 + languageName: node + linkType: hard + "mixme@npm:^0.5.1": version: 0.5.9 resolution: "mixme@npm:0.5.9" @@ -36410,6 +37382,13 @@ __metadata: languageName: node linkType: hard +"mux-embed@npm:^5.3.0": + version: 5.3.2 + resolution: "mux-embed@npm:5.3.2" + checksum: e56dd70b22916c106425fa252fe3d0438fe69dc8e3c01628a53cdb0199f406be79be33c8102044d04c9f50e3d533b3ddc615f7f9ab498b291ef21d4f65922e33 + languageName: node + linkType: hard + "mysql2@npm:3.9.1": version: 3.9.1 resolution: "mysql2@npm:3.9.1" @@ -36465,15 +37444,6 @@ __metadata: languageName: node linkType: hard -"nano-time@npm:1.0.0": - version: 1.0.0 - resolution: "nano-time@npm:1.0.0" - dependencies: - big-integer: ^1.6.16 - checksum: eef8548546cc1020625f8e44751a7263e9eddf0412a6a1a6c80a8d2be2ea7973622804a977cdfe796807b85b20ff6c8ba340e8dd20effcc7078193ed5edbb5d4 - languageName: node - linkType: hard - "nanoclone@npm:^0.2.1": version: 0.2.1 resolution: "nanoclone@npm:0.2.1" @@ -36819,20 +37789,20 @@ __metadata: languageName: node linkType: hard -"next@npm:^13.5.4": - version: 13.5.5 - resolution: "next@npm:13.5.5" +"next@npm:^13.5.6": + version: 13.5.7 + resolution: "next@npm:13.5.7" dependencies: - "@next/env": 13.5.5 - "@next/swc-darwin-arm64": 13.5.5 - "@next/swc-darwin-x64": 13.5.5 - "@next/swc-linux-arm64-gnu": 13.5.5 - "@next/swc-linux-arm64-musl": 13.5.5 - "@next/swc-linux-x64-gnu": 13.5.5 - "@next/swc-linux-x64-musl": 13.5.5 - "@next/swc-win32-arm64-msvc": 13.5.5 - "@next/swc-win32-ia32-msvc": 13.5.5 - "@next/swc-win32-x64-msvc": 13.5.5 + "@next/env": 13.5.7 + "@next/swc-darwin-arm64": 13.5.7 + "@next/swc-darwin-x64": 13.5.7 + "@next/swc-linux-arm64-gnu": 13.5.7 + "@next/swc-linux-arm64-musl": 13.5.7 + "@next/swc-linux-x64-gnu": 13.5.7 + "@next/swc-linux-x64-musl": 13.5.7 + "@next/swc-win32-arm64-msvc": 13.5.7 + "@next/swc-win32-ia32-msvc": 13.5.7 + "@next/swc-win32-x64-msvc": 13.5.7 "@swc/helpers": 0.5.2 busboy: 1.6.0 caniuse-lite: ^1.0.30001406 @@ -36870,7 +37840,7 @@ __metadata: optional: true bin: next: dist/bin/next - checksum: 034a52cf9a5df79912ad67467e00ab98e6505a7544514a12d6310d67fea760764f6b04ade344d457aadecb6170dd50eb0709346fd97a9e6659fcabd5e510fb97 + checksum: 056a0126fbb2197ee3c397c5599e5dafe57cb23d8420ab4ebd8c62a9a73f06305b8d323315097fa772408f11791106896e714fdccc8dae7f02064531ecc52a20 languageName: node linkType: hard @@ -36981,6 +37951,15 @@ __metadata: languageName: node linkType: hard +"node-addon-api@npm:^1.7.1": + version: 1.7.2 + resolution: "node-addon-api@npm:1.7.2" + dependencies: + node-gyp: latest + checksum: 938922b3d7cb34ee137c5ec39df6289a3965e8cab9061c6848863324c21a778a81ae3bc955554c56b6b86962f6ccab2043dd5fa3f33deab633636bd28039333f + languageName: node + linkType: hard + "node-addon-api@npm:^6.1.0": version: 6.1.0 resolution: "node-addon-api@npm:6.1.0" @@ -37504,6 +38483,17 @@ __metadata: languageName: node linkType: hard +"nuqs@npm:^1.20.0": + version: 1.20.0 + resolution: "nuqs@npm:1.20.0" + dependencies: + mitt: ^3.0.1 + peerDependencies: + next: ">=13.4 <14.0.2 || ^14.0.3" + checksum: 9b92c9c0bac2ad96fcd6337bad1cbbafc3ebf47a73adabcf3e19005c2654fc484329bf9a51b83f3547181c4c3138a7c32fc14f51b45d527f4e9784120e27f365 + languageName: node + linkType: hard + "nwsapi@npm:^2.2.4": version: 2.2.4 resolution: "nwsapi@npm:2.2.4" @@ -37685,6 +38675,17 @@ __metadata: languageName: node linkType: hard +"object.entries@npm:^1.1.8": + version: 1.1.8 + resolution: "object.entries@npm:1.1.8" + dependencies: + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-object-atoms: ^1.0.0 + checksum: 5314877cb637ef3437a30bba61d9bacdb3ce74bf73ac101518be0633c37840c8cc67407edb341f766e8093b3d7516d5c3358f25adfee4a2c697c0ec4c8491907 + languageName: node + linkType: hard + "object.fromentries@npm:^2.0.5": version: 2.0.5 resolution: "object.fromentries@npm:2.0.5" @@ -37718,6 +38719,18 @@ __metadata: languageName: node linkType: hard +"object.fromentries@npm:^2.0.8": + version: 2.0.8 + resolution: "object.fromentries@npm:2.0.8" + dependencies: + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-object-atoms: ^1.0.0 + checksum: 29b2207a2db2782d7ced83f93b3ff5d425f901945f3665ffda1821e30a7253cd1fd6b891a64279976098137ddfa883d748787a6fea53ecdb51f8df8b8cec0ae1 + languageName: node + linkType: hard + "object.groupby@npm:^1.0.1": version: 1.0.2 resolution: "object.groupby@npm:1.0.2" @@ -37794,6 +38807,17 @@ __metadata: languageName: node linkType: hard +"object.values@npm:^1.2.0": + version: 1.2.0 + resolution: "object.values@npm:1.2.0" + dependencies: + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-object-atoms: ^1.0.0 + checksum: 51fef456c2a544275cb1766897f34ded968b22adfc13ba13b5e4815fdaf4304a90d42a3aee114b1f1ede048a4890381d47a5594d84296f2767c6a0364b9da8fa + languageName: node + linkType: hard + "objectorarray@npm:^1.0.5": version: 1.0.5 resolution: "objectorarray@npm:1.0.5" @@ -37808,13 +38832,6 @@ __metadata: languageName: node linkType: hard -"oblivious-set@npm:1.0.0": - version: 1.0.0 - resolution: "oblivious-set@npm:1.0.0" - checksum: f31740ea9c3a8242ad2324e4ebb9a35359fbc2e6e7131731a0fc1c8b7b1238eb07e4c8c631a38535243a7b8e3042b7e89f7dc2a95d2989afd6f80bd5793b0aab - languageName: node - linkType: hard - "obuf@npm:~1.1.2": version: 1.1.2 resolution: "obuf@npm:1.1.2" @@ -39276,6 +40293,15 @@ __metadata: languageName: node linkType: hard +"player.style@npm:^0.0.8": + version: 0.0.8 + resolution: "player.style@npm:0.0.8" + dependencies: + media-chrome: ^4.1.0 + checksum: 009f59bc8e7f84e82adcacec4df3ea11094d7097413a5755bb6a586150c9aa6114f7d7840f215b8b98c20f3eabbf40b7eb1d20731384253fea3122bd62b9512e + languageName: node + linkType: hard + "playwright-core@npm:1.45.3": version: 1.45.3 resolution: "playwright-core@npm:1.45.3" @@ -39838,6 +40864,15 @@ __metadata: languageName: node linkType: hard +"prettier@npm:3.3.3": + version: 3.3.3 + resolution: "prettier@npm:3.3.3" + bin: + prettier: bin/prettier.cjs + checksum: bc8604354805acfdde6106852d14b045bb20827ad76a5ffc2455b71a8257f94de93f17f14e463fe844808d2ccc87248364a5691488a3304f1031326e62d9276e + languageName: node + linkType: hard + "prettier@npm:^2.7.1": version: 2.8.7 resolution: "prettier@npm:2.8.7" @@ -40755,20 +41790,21 @@ __metadata: languageName: node linkType: hard -"react-datocms@npm:^3.1.0": - version: 3.1.4 - resolution: "react-datocms@npm:3.1.4" +"react-datocms@npm:^5.0.3": + version: 5.0.3 + resolution: "react-datocms@npm:5.0.3" dependencies: + "@mux/mux-player-react": "*" datocms-listen: ^0.1.9 datocms-structured-text-generic-html-renderer: ^2.0.1 datocms-structured-text-utils: ^2.0.1 - react-intersection-observer: ^8.33.1 + react-intersection-observer: ^9.4.3 react-string-replace: ^1.1.0 universal-base64: ^2.1.0 use-deep-compare-effect: ^1.6.1 peerDependencies: react: ">= 16.12.0" - checksum: 54aba12aef4937175c2011548a8a576c96c8d8a596e84d191826910624c1d596e76a49782689dc236388a10803b02e700ac820cb7500cca7fd147a81f6c544c3 + checksum: 22c20152afb54424acfe967a2c8c525cd9f132a33374f2aba0231f16ea64dade389b096e2dac8de9ffded612bc32e9891d725609ee947639fe1cef907cb143f5 languageName: node linkType: hard @@ -41029,12 +42065,16 @@ __metadata: languageName: node linkType: hard -"react-intersection-observer@npm:^8.33.1": - version: 8.34.0 - resolution: "react-intersection-observer@npm:8.34.0" +"react-intersection-observer@npm:^9.4.3": + version: 9.13.1 + resolution: "react-intersection-observer@npm:9.13.1" peerDependencies: - react: ^15.0.0 || ^16.0.0 || ^17.0.0|| ^18.0.0 - checksum: 7713fecfd1512c7f5a60f9f0bf15403b8f8bbd4110bcafaeaea6de36a0e0eb60368c3638f99e9c97b75ad8fc787ea48c241dcb5c694f821d7f2976f709082cc5 + react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + react-dom: + optional: true + checksum: 92b3e7d9293365635bf5ede89b912a670030c6244879dce36fa9437e6749c637151087fbcaa72cc160b2fa7045bd5ac861a8535e0a2b7b8f230f11f2e0391005 languageName: node linkType: hard @@ -41144,6 +42184,16 @@ __metadata: languageName: node linkType: hard +"react-parallax-tilt@npm:^1.7.226": + version: 1.7.245 + resolution: "react-parallax-tilt@npm:1.7.245" + peerDependencies: + react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 + react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 + checksum: 32b56fdb46e993c769f8458e3f9cdd9edd4711c6f95ecfaa4ac004775ea9653f0487232dd010179e45348fd34a61ccdf8026baaf439685ae2450914471de1fb9 + languageName: node + linkType: hard + "react-phone-input-2@npm:^2.15.1": version: 2.15.1 resolution: "react-phone-input-2@npm:2.15.1" @@ -41193,24 +42243,6 @@ __metadata: languageName: node linkType: hard -"react-query@npm:^3.39.3": - version: 3.39.3 - resolution: "react-query@npm:3.39.3" - dependencies: - "@babel/runtime": ^7.5.5 - broadcast-channel: ^3.4.1 - match-sorter: ^6.0.2 - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react-dom: - optional: true - react-native: - optional: true - checksum: d2de6a0992dbf039ff2de564de1ae6361f8ac7310159dae42ec16f833b79c05caedced187235c42373ac331cc5f2fe9e2b31b14ae75a815e86d86e30ca9887ad - languageName: node - linkType: hard - "react-reconciler@npm:^0.26.2": version: 0.26.2 resolution: "react-reconciler@npm:0.26.2" @@ -41284,6 +42316,22 @@ __metadata: languageName: node linkType: hard +"react-remove-scroll-bar@npm:^2.3.6": + version: 2.3.6 + resolution: "react-remove-scroll-bar@npm:2.3.6" + dependencies: + react-style-singleton: ^2.2.1 + tslib: ^2.0.0 + peerDependencies: + "@types/react": ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: e793fe110e2ea60d5724d0b60f09de1f6cd1b080df00df9e68bb9a1b985895830e703194647059fdc22402a67a89b7673a5260773b89bcd98031fd99bc91aefa + languageName: node + linkType: hard + "react-remove-scroll@npm:2.5.4": version: 2.5.4 resolution: "react-remove-scroll@npm:2.5.4" @@ -41322,6 +42370,25 @@ __metadata: languageName: node linkType: hard +"react-remove-scroll@npm:2.6.0": + version: 2.6.0 + resolution: "react-remove-scroll@npm:2.6.0" + dependencies: + react-remove-scroll-bar: ^2.3.6 + react-style-singleton: ^2.2.1 + tslib: ^2.1.0 + use-callback-ref: ^1.3.0 + use-sidecar: ^1.1.2 + peerDependencies: + "@types/react": ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: e7ad2383ce20d63cf28f3ed14e63f684e139301fc4a5c1573da330d4465b733e6084c33b2bfcaee448c9b1df0e37993a15d6cba8a1dd80fe631f803e48e9f798 + languageName: node + linkType: hard + "react-remove-scroll@npm:^2.4.0": version: 2.4.4 resolution: "react-remove-scroll@npm:2.4.4" @@ -41578,6 +42645,18 @@ __metadata: languageName: node linkType: hard +"react-twitter-embed@npm:^4.0.4": + version: 4.0.4 + resolution: "react-twitter-embed@npm:4.0.4" + dependencies: + scriptjs: ^2.5.9 + peerDependencies: + react: ^16.0.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 + checksum: cdb3c5bd04c4da0efa767476be47c0a3865fb6335f2a1b9e242170167b51615c38164223278cef60c77143c4bac27ba582cbea054d0af3f138104fa5ec537c4c + languageName: node + linkType: hard + "react-universal-interface@npm:^0.6.2": version: 0.6.2 resolution: "react-universal-interface@npm:0.6.2" @@ -42377,13 +43456,6 @@ __metadata: languageName: node linkType: hard -"remove-accents@npm:0.5.0": - version: 0.5.0 - resolution: "remove-accents@npm:0.5.0" - checksum: 7045b37015acb03df406d21f9cbe93c3fcf2034189f5d2e33b1dace9c7d6bdcd839929905ced21a5d76c58553557e1a42651930728702312a5774179d5b9147b - languageName: node - linkType: hard - "remove-markdown@npm:^0.5.0": version: 0.5.0 resolution: "remove-markdown@npm:0.5.0" @@ -42432,7 +43504,7 @@ __metadata: languageName: node linkType: hard -"request@npm:^2.66.0, request@npm:^2.72.0, request@npm:^2.88.0": +"request@npm:^2.72.0": version: 2.88.2 resolution: "request@npm:2.88.2" dependencies: @@ -43465,6 +44537,13 @@ __metadata: languageName: node linkType: hard +"scriptjs@npm:^2.5.9": + version: 2.5.9 + resolution: "scriptjs@npm:2.5.9" + checksum: fc84cb6b60b6fb9aa6f1b3bc59fc94b233bd5241ed3a04233579014382b5eb60640269c87d8657902acc09f9b785ee33230c218627cea00e653564bda8f5acb6 + languageName: node + linkType: hard + "scuid@npm:^1.1.0": version: 1.1.0 resolution: "scuid@npm:1.1.0" @@ -43571,6 +44650,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.6.0": + version: 7.6.3 + resolution: "semver@npm:7.6.3" + bin: + semver: bin/semver.js + checksum: 4110ec5d015c9438f322257b1c51fe30276e5f766a3f64c09edd1d7ea7118ecbc3f379f3b69032bacf13116dc7abc4ad8ce0d7e2bd642e26b0d271b56b61a7d8 + languageName: node + linkType: hard + "semver@npm:~2.3.1": version: 2.3.2 resolution: "semver@npm:2.3.2" @@ -43742,6 +44830,18 @@ __metadata: languageName: node linkType: hard +"set-function-name@npm:^2.0.2": + version: 2.0.2 + resolution: "set-function-name@npm:2.0.2" + dependencies: + define-data-property: ^1.1.4 + es-errors: ^1.3.0 + functions-have-names: ^1.2.3 + has-property-descriptors: ^1.0.2 + checksum: d6229a71527fd0404399fc6227e0ff0652800362510822a291925c9d7b48a1ca1a468b11b281471c34cd5a2da0db4f5d7ff315a61d26655e77f6e971e6d0c80f + languageName: node + linkType: hard + "set-harmonic-interval@npm:^1.0.1": version: 1.0.1 resolution: "set-harmonic-interval@npm:1.0.1" @@ -44814,6 +45914,26 @@ __metadata: languageName: node linkType: hard +"string.prototype.matchall@npm:^4.0.11": + version: 4.0.11 + resolution: "string.prototype.matchall@npm:4.0.11" + dependencies: + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-errors: ^1.3.0 + es-object-atoms: ^1.0.0 + get-intrinsic: ^1.2.4 + gopd: ^1.0.1 + has-symbols: ^1.0.3 + internal-slot: ^1.0.7 + regexp.prototype.flags: ^1.5.2 + set-function-name: ^2.0.2 + side-channel: ^1.0.6 + checksum: 6ac6566ed065c0c8489c91156078ca077db8ff64d683fda97ae652d00c52dfa5f39aaab0a710d8243031a857fd2c7c511e38b45524796764d25472d10d7075ae + languageName: node + linkType: hard + "string.prototype.matchall@npm:^4.0.7": version: 4.0.7 resolution: "string.prototype.matchall@npm:4.0.7" @@ -44857,6 +45977,16 @@ __metadata: languageName: node linkType: hard +"string.prototype.repeat@npm:^1.0.0": + version: 1.0.0 + resolution: "string.prototype.repeat@npm:1.0.0" + dependencies: + define-properties: ^1.1.3 + es-abstract: ^1.17.5 + checksum: 95dfc514ed7f328d80a066dabbfbbb1615c3e51490351085409db2eb7cbfed7ea29fdadaf277647fbf9f4a1e10e6dd9e95e78c0fd2c4e6bb6723ea6e59401004 + languageName: node + linkType: hard + "string.prototype.trim@npm:^1.2.8": version: 1.2.8 resolution: "string.prototype.trim@npm:1.2.8" @@ -44955,6 +46085,17 @@ __metadata: languageName: node linkType: hard +"string.prototype.trimstart@npm:^1.0.8": + version: 1.0.8 + resolution: "string.prototype.trimstart@npm:1.0.8" + dependencies: + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-object-atoms: ^1.0.0 + checksum: df1007a7f580a49d692375d996521dc14fd103acda7f3034b3c558a60b82beeed3a64fa91e494e164581793a8ab0ae2f59578a49896a7af6583c1f20472bce96 + languageName: node + linkType: hard + "string_decoder@npm:^1.0.0, string_decoder@npm:^1.1.1, string_decoder@npm:^1.3.0": version: 1.3.0 resolution: "string_decoder@npm:1.3.0" @@ -46284,6 +47425,18 @@ __metadata: languageName: node linkType: hard +"tough-cookie@npm:^4.1.3": + version: 4.1.4 + resolution: "tough-cookie@npm:4.1.4" + dependencies: + psl: ^1.1.33 + punycode: ^2.1.1 + universalify: ^0.2.0 + url-parse: ^1.5.3 + checksum: 5815059f014c31179a303c673f753f7899a6fce94ac93712c88ea5f3c26e0c042b5f0c7a599a00f8e0feeca4615dba75c3dffc54f3c1a489978aa8205e09307c + languageName: node + linkType: hard + "tough-cookie@npm:~2.5.0": version: 2.5.0 resolution: "tough-cookie@npm:2.5.0" @@ -46363,6 +47516,15 @@ __metadata: languageName: node linkType: hard +"ts-api-utils@npm:^1.3.0": + version: 1.3.0 + resolution: "ts-api-utils@npm:1.3.0" + peerDependencies: + typescript: ">=4.2.0" + checksum: c746ddabfdffbf16cb0b0db32bb287236a19e583057f8649ee7c49995bb776e1d3ef384685181c11a1a480369e022ca97512cb08c517b2d2bd82c83754c97012 + languageName: node + linkType: hard + "ts-dedent@npm:^2.0.0, ts-dedent@npm:^2.2.0": version: 2.2.0 resolution: "ts-dedent@npm:2.2.0" @@ -47143,6 +48305,20 @@ __metadata: languageName: node linkType: hard +"typed-array-length@npm:^1.0.6": + version: 1.0.6 + resolution: "typed-array-length@npm:1.0.6" + dependencies: + call-bind: ^1.0.7 + for-each: ^0.3.3 + gopd: ^1.0.1 + has-proto: ^1.0.3 + is-typed-array: ^1.1.13 + possible-typed-array-names: ^1.0.0 + checksum: f0315e5b8f0168c29d390ff410ad13e4d511c78e6006df4a104576844812ee447fcc32daab1f3a76c9ef4f64eff808e134528b5b2439de335586b392e9750e5c + languageName: node + linkType: hard + "typedarray-to-buffer@npm:^3.1.5": version: 3.1.5 resolution: "typedarray-to-buffer@npm:3.1.5" @@ -47246,6 +48422,20 @@ __metadata: languageName: node linkType: hard +"typescript-eslint@npm:^8.2.0": + version: 8.8.1 + resolution: "typescript-eslint@npm:8.8.1" + dependencies: + "@typescript-eslint/eslint-plugin": 8.8.1 + "@typescript-eslint/parser": 8.8.1 + "@typescript-eslint/utils": 8.8.1 + peerDependenciesMeta: + typescript: + optional: true + checksum: b55739c826b5b58d606ad3261e892c24ee1b33221e53f2e5279ae195deb9afb5962d9acc9db36f7ee2add2392bfcc6a1641ec8a1814d93458959e4991015d4d4 + languageName: node + linkType: hard + "typescript@npm:5.3.3": version: 5.3.3 resolution: "typescript@npm:5.3.3" @@ -47256,7 +48446,7 @@ __metadata: languageName: node linkType: hard -"typescript@npm:^4.9.4": +"typescript@npm:^4.4.4, typescript@npm:^4.9.4": version: 4.9.5 resolution: "typescript@npm:4.9.5" bin: @@ -47286,7 +48476,7 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@^4.9.4#~builtin": +"typescript@patch:typescript@^4.4.4#~builtin, typescript@patch:typescript@^4.9.4#~builtin": version: 4.9.5 resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=23ec76" bin: @@ -47685,16 +48875,6 @@ __metadata: languageName: node linkType: hard -"unload@npm:2.2.0": - version: 2.2.0 - resolution: "unload@npm:2.2.0" - dependencies: - "@babel/runtime": ^7.6.2 - detect-node: ^2.0.4 - checksum: 88ba950c5ff83ab4f9bbd8f63bbf19ba09687ed3c434efd43b7338cc595bc574df8f9b155ee6eee7a435de3d3a4a226726988428977a68ba4907045f1fac5d41 - languageName: node - linkType: hard - "unpipe@npm:1.0.0, unpipe@npm:~1.0.0": version: 1.0.0 resolution: "unpipe@npm:1.0.0"