Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a2da017ff | ||
|
|
2f8280a6ee | ||
|
|
4e1e2577eb | ||
|
|
84da528d4d | ||
|
|
29ceaee8d2 | ||
|
|
d28c914d3c | ||
|
|
34d3bdf868 | ||
|
|
58836eefbf | ||
|
|
4ab6c2b3da | ||
|
|
e1601960df | ||
|
|
c97fecf436 | ||
|
|
804ba04983 | ||
|
|
163444a0f9 | ||
|
|
b0da827483 | ||
|
|
1b468b9ae7 | ||
|
|
2fa83bd512 | ||
|
|
7eecc311e0 | ||
|
|
6c8b428577 | ||
|
|
699c55da18 | ||
|
|
74a30a180e | ||
|
|
ce8e1d52da | ||
|
|
6f8ea490d0 | ||
|
|
a2fd5ba2a2 | ||
|
|
48c8b749ce | ||
|
|
faaf935724 | ||
|
|
0c94b0a30a | ||
|
|
a25195cf20 |
@@ -39,6 +39,8 @@ SAML_DATABASE_URL=
|
||||
SAML_ADMINS=
|
||||
# NEXT_PUBLIC_HOSTED_CAL_FEATURES=1
|
||||
NEXT_PUBLIC_HOSTED_CAL_FEATURES=
|
||||
# For additional security set to a random secret and use that value as the client_secret during the OAuth 2.0 flow.
|
||||
SAML_CLIENT_SECRET_VERIFIER=
|
||||
|
||||
# If you use Heroku to deploy Postgres (or use self-signed certs for Postgres) then uncomment the follow line.
|
||||
# @see https://devcenter.heroku.com/articles/connecting-heroku-postgres#connecting-in-node-js
|
||||
@@ -76,6 +78,10 @@ NEXT_PUBLIC_ZENDESK_KEY=
|
||||
# Help Scout Config
|
||||
NEXT_PUBLIC_HELPSCOUT_KEY=
|
||||
|
||||
# Fresh Chat Config
|
||||
NEXT_PUBLIC_FRESHCHAT_TOKEN=
|
||||
NEXT_PUBLIC_FRESHCHAT_HOST=
|
||||
|
||||
# Inbox to send user feedback
|
||||
SEND_FEEDBACK_EMAIL=
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { getEventLocationType, locationKeyToString } from "@calcom/app-store/locations";
|
||||
import { classNames } from "@calcom/lib";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
@@ -17,6 +19,23 @@ export function AvailableEventLocations({ locations }: { locations: Props["event
|
||||
// It's possible that the location app got uninstalled
|
||||
return null;
|
||||
}
|
||||
|
||||
const translateAbleKeys = [
|
||||
"attendee_in_person",
|
||||
"in_person",
|
||||
"attendee_phone_number",
|
||||
"link_meeting",
|
||||
"organizer_phone_number",
|
||||
];
|
||||
|
||||
const locationKey = z.string().default("").parse(locationKeyToString(location));
|
||||
|
||||
const translatedLocation = location.type.startsWith("integrations:")
|
||||
? eventLocationType.label
|
||||
: translateAbleKeys.includes(locationKey)
|
||||
? t(locationKey)
|
||||
: locationKey;
|
||||
|
||||
return (
|
||||
<div key={`${location.type}-${index}`} className="flex flex-row items-center text-sm font-medium">
|
||||
{eventLocationType.iconUrl === "/link.svg" ? (
|
||||
@@ -31,14 +50,12 @@ export function AvailableEventLocations({ locations }: { locations: Props["event
|
||||
alt={`${eventLocationType.label} icon`}
|
||||
/>
|
||||
)}
|
||||
<Tooltip content={t(locationKeyToString(location) ?? "")}>
|
||||
<p className="line-clamp-1">{t(locationKeyToString(location) ?? "")}</p>
|
||||
<Tooltip content={translatedLocation}>
|
||||
<p className="line-clamp-1">{translatedLocation}</p>
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
);
|
||||
) : null;
|
||||
}
|
||||
|
||||
@@ -481,7 +481,7 @@ const BookingPage = ({
|
||||
)}>
|
||||
<div
|
||||
className={classNames(
|
||||
"main overflow-hidden",
|
||||
"main",
|
||||
isBackgroundTransparent ? "" : "dark:bg-darkgray-100 bg-white dark:border",
|
||||
"dark:border-darkgray-300 rounded-md sm:border"
|
||||
)}>
|
||||
|
||||
@@ -288,16 +288,13 @@ export const EditLocationDialog = (props: ISetLocationDialog) => {
|
||||
}}>
|
||||
<QueryCell
|
||||
query={locationsQuery}
|
||||
success={({ data: locationOptions }) => {
|
||||
if (!locationOptions.length) return null;
|
||||
success={({ data }) => {
|
||||
if (!data.length) return null;
|
||||
const locationOptions = [...data];
|
||||
if (booking) {
|
||||
locationOptions.forEach((location) => {
|
||||
if (location.label === "phone") {
|
||||
location.options.filter((l) => l.value !== "phone");
|
||||
} else if (location.label === "in person") {
|
||||
location.options.filter((l) => l.value !== "attendeeInPerson");
|
||||
}
|
||||
});
|
||||
locationOptions.map((location) =>
|
||||
location.options.filter((l) => !["phone", "attendeeInPerson"].includes(l.value))
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Controller
|
||||
|
||||
@@ -192,11 +192,9 @@ export const EventSetupTab = (
|
||||
if (!eventLocationType) {
|
||||
return null;
|
||||
}
|
||||
// We dont want to translate the string link - it doesnt exist in common.json and it gets prefixed/suffixed with __ or //
|
||||
|
||||
const eventLabel =
|
||||
eventLocationType.defaultValueVariable === "link"
|
||||
? eventLocationType.label
|
||||
: t(location[eventLocationType.defaultValueVariable] || eventLocationType.label);
|
||||
location[eventLocationType.defaultValueVariable] || t(eventLocationType.label);
|
||||
|
||||
return (
|
||||
<li
|
||||
|
||||
@@ -220,6 +220,7 @@ function EventTypeSingleLayout({
|
||||
<Tooltip content={t("preview")}>
|
||||
<Button
|
||||
color="secondary"
|
||||
data-testid="preview-button"
|
||||
target="_blank"
|
||||
variant="icon"
|
||||
href={permalink}
|
||||
|
||||
@@ -9,7 +9,7 @@ import type z from "zod";
|
||||
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import type { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
|
||||
import { Alert, Input, Label, SettingsToggle } from "@calcom/ui";
|
||||
import { Input, Label, SettingsToggle } from "@calcom/ui";
|
||||
|
||||
type RequiresConfirmationControllerProps = {
|
||||
metadata: z.infer<typeof EventTypeMetaDataSchema>;
|
||||
@@ -39,118 +39,116 @@ export default function RequiresConfirmationController({
|
||||
|
||||
return (
|
||||
<div className="block items-start sm:flex">
|
||||
<div className={!seatsEnabled ? "w-full" : ""}>
|
||||
{seatsEnabled ? (
|
||||
<Alert severity="warning" title="Seats option doesn't support confirmation requirement" />
|
||||
) : (
|
||||
<Controller
|
||||
name="requiresConfirmation"
|
||||
control={formMethods.control}
|
||||
render={() => (
|
||||
<SettingsToggle
|
||||
title={t("requires_confirmation")}
|
||||
description={t("requires_confirmation_description")}
|
||||
checked={requiresConfirmation}
|
||||
onCheckedChange={(val) => {
|
||||
formMethods.setValue("requiresConfirmation", val);
|
||||
onRequiresConfirmation(val);
|
||||
}}>
|
||||
<RadioGroup.Root
|
||||
defaultValue={
|
||||
requiresConfirmation
|
||||
? requiresConfirmationSetup === undefined
|
||||
? "always"
|
||||
: "notice"
|
||||
: undefined
|
||||
<div className="w-full">
|
||||
<Controller
|
||||
name="requiresConfirmation"
|
||||
control={formMethods.control}
|
||||
render={() => (
|
||||
<SettingsToggle
|
||||
title={t("requires_confirmation")}
|
||||
disabled={seatsEnabled}
|
||||
tooltip={seatsEnabled ? t("seat_options_doesnt_support_confirmation") : undefined}
|
||||
description={t("requires_confirmation_description")}
|
||||
checked={requiresConfirmation}
|
||||
onCheckedChange={(val) => {
|
||||
formMethods.setValue("requiresConfirmation", val);
|
||||
onRequiresConfirmation(val);
|
||||
}}>
|
||||
<RadioGroup.Root
|
||||
defaultValue={
|
||||
requiresConfirmation
|
||||
? requiresConfirmationSetup === undefined
|
||||
? "always"
|
||||
: "notice"
|
||||
: undefined
|
||||
}
|
||||
onValueChange={(val) => {
|
||||
if (val === "always") {
|
||||
formMethods.setValue("requiresConfirmation", true);
|
||||
onRequiresConfirmation(true);
|
||||
formMethods.setValue("metadata.requiresConfirmationThreshold", undefined);
|
||||
setRequiresConfirmationSetup(undefined);
|
||||
} else if (val === "notice") {
|
||||
formMethods.setValue("requiresConfirmation", true);
|
||||
onRequiresConfirmation(true);
|
||||
formMethods.setValue(
|
||||
"metadata.requiresConfirmationThreshold",
|
||||
requiresConfirmationSetup || defaultRequiresConfirmationSetup
|
||||
);
|
||||
}
|
||||
onValueChange={(val) => {
|
||||
if (val === "always") {
|
||||
formMethods.setValue("requiresConfirmation", true);
|
||||
onRequiresConfirmation(true);
|
||||
formMethods.setValue("metadata.requiresConfirmationThreshold", undefined);
|
||||
setRequiresConfirmationSetup(undefined);
|
||||
} else if (val === "notice") {
|
||||
formMethods.setValue("requiresConfirmation", true);
|
||||
onRequiresConfirmation(true);
|
||||
formMethods.setValue(
|
||||
"metadata.requiresConfirmationThreshold",
|
||||
requiresConfirmationSetup || defaultRequiresConfirmationSetup
|
||||
);
|
||||
}
|
||||
}}>
|
||||
<div className="-ml-2 flex flex-col flex-wrap justify-start gap-y-2 space-y-2">
|
||||
<div className="flex items-center">
|
||||
<RadioGroup.Item
|
||||
id="always"
|
||||
value="always"
|
||||
className="min-w-4 flex h-4 w-4 cursor-pointer items-center rounded-full border border-black bg-white focus:border-2 focus:outline-none ltr:mr-2 rtl:ml-2">
|
||||
<RadioGroup.Indicator className="relative flex h-4 w-4 items-center justify-center after:block after:h-2 after:w-2 after:rounded-full after:bg-black" />
|
||||
</RadioGroup.Item>
|
||||
<Label htmlFor="always" className="!m-0 flex items-center">
|
||||
{t("always_requires_confirmation")}
|
||||
</Label>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<RadioGroup.Item
|
||||
id="notice"
|
||||
value="notice"
|
||||
className="min-w-4 flex h-4 w-4 cursor-pointer items-center rounded-full border border-black bg-white focus:border-2 focus:outline-none ltr:mr-2 rtl:ml-2">
|
||||
<RadioGroup.Indicator className="relative flex h-4 w-4 items-center justify-center after:block after:h-2 after:w-2 after:rounded-full after:bg-black" />
|
||||
</RadioGroup.Item>
|
||||
<Label htmlFor="notice" className="!m-0 flex items-center">
|
||||
<Trans
|
||||
i18nKey="when_booked_with_less_than_notice"
|
||||
defaults="When booked with less than <time></time> notice"
|
||||
components={{
|
||||
time: (
|
||||
<div className="mx-2 flex">
|
||||
<Input
|
||||
type="number"
|
||||
min={1}
|
||||
onChange={(evt) => {
|
||||
const val = Number(evt.target?.value);
|
||||
setRequiresConfirmationSetup({
|
||||
unit:
|
||||
requiresConfirmationSetup?.unit ??
|
||||
defaultRequiresConfirmationSetup.unit,
|
||||
time: val,
|
||||
});
|
||||
formMethods.setValue("metadata.requiresConfirmationThreshold.time", val);
|
||||
}}
|
||||
className="!m-0 block w-16 rounded-md border-gray-300 text-sm [appearance:textfield]"
|
||||
defaultValue={metadata?.requiresConfirmationThreshold?.time || 30}
|
||||
/>
|
||||
<select
|
||||
onChange={(evt) => {
|
||||
const val = evt.target.value as UnitTypeLongPlural;
|
||||
setRequiresConfirmationSetup({
|
||||
time:
|
||||
requiresConfirmationSetup?.time ??
|
||||
defaultRequiresConfirmationSetup.time,
|
||||
unit: val,
|
||||
});
|
||||
formMethods.setValue("metadata.requiresConfirmationThreshold.unit", val);
|
||||
}}
|
||||
className="ml-2 block h-9 rounded-md border-gray-300 py-2 pl-3 pr-10 text-sm focus:outline-none"
|
||||
defaultValue={
|
||||
metadata?.requiresConfirmationThreshold?.unit ||
|
||||
defaultRequiresConfirmationSetup.unit
|
||||
}>
|
||||
<option value="minutes">{t("minute_timeUnit")}</option>
|
||||
<option value="hours">{t("hour_timeUnit")}</option>
|
||||
</select>
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</Label>
|
||||
</div>
|
||||
}}>
|
||||
<div className="-ml-2 flex flex-col flex-wrap justify-start gap-y-2 space-y-2">
|
||||
<div className="flex items-center">
|
||||
<RadioGroup.Item
|
||||
id="always"
|
||||
value="always"
|
||||
className="min-w-4 flex h-4 w-4 cursor-pointer items-center rounded-full border border-black bg-white focus:border-2 focus:outline-none ltr:mr-2 rtl:ml-2">
|
||||
<RadioGroup.Indicator className="relative flex h-4 w-4 items-center justify-center after:block after:h-2 after:w-2 after:rounded-full after:bg-black" />
|
||||
</RadioGroup.Item>
|
||||
<Label htmlFor="always" className="!m-0 flex items-center">
|
||||
{t("always_requires_confirmation")}
|
||||
</Label>
|
||||
</div>
|
||||
</RadioGroup.Root>
|
||||
</SettingsToggle>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
<div className="flex items-center">
|
||||
<RadioGroup.Item
|
||||
id="notice"
|
||||
value="notice"
|
||||
className="min-w-4 flex h-4 w-4 cursor-pointer items-center rounded-full border border-black bg-white focus:border-2 focus:outline-none ltr:mr-2 rtl:ml-2">
|
||||
<RadioGroup.Indicator className="relative flex h-4 w-4 items-center justify-center after:block after:h-2 after:w-2 after:rounded-full after:bg-black" />
|
||||
</RadioGroup.Item>
|
||||
<Label htmlFor="notice" className="!m-0 flex items-center">
|
||||
<Trans
|
||||
i18nKey="when_booked_with_less_than_notice"
|
||||
defaults="When booked with less than <time></time> notice"
|
||||
components={{
|
||||
time: (
|
||||
<div className="mx-2 flex">
|
||||
<Input
|
||||
type="number"
|
||||
min={1}
|
||||
onChange={(evt) => {
|
||||
const val = Number(evt.target?.value);
|
||||
setRequiresConfirmationSetup({
|
||||
unit:
|
||||
requiresConfirmationSetup?.unit ??
|
||||
defaultRequiresConfirmationSetup.unit,
|
||||
time: val,
|
||||
});
|
||||
formMethods.setValue("metadata.requiresConfirmationThreshold.time", val);
|
||||
}}
|
||||
className="!m-0 block w-16 rounded-md border-gray-300 text-sm [appearance:textfield]"
|
||||
defaultValue={metadata?.requiresConfirmationThreshold?.time || 30}
|
||||
/>
|
||||
<select
|
||||
onChange={(evt) => {
|
||||
const val = evt.target.value as UnitTypeLongPlural;
|
||||
setRequiresConfirmationSetup({
|
||||
time:
|
||||
requiresConfirmationSetup?.time ??
|
||||
defaultRequiresConfirmationSetup.time,
|
||||
unit: val,
|
||||
});
|
||||
formMethods.setValue("metadata.requiresConfirmationThreshold.unit", val);
|
||||
}}
|
||||
className="ml-2 block h-9 rounded-md border-gray-300 py-2 pl-3 pr-10 text-sm focus:outline-none"
|
||||
defaultValue={
|
||||
metadata?.requiresConfirmationThreshold?.unit ||
|
||||
defaultRequiresConfirmationSetup.unit
|
||||
}>
|
||||
<option value="minutes">{t("minute_timeUnit")}</option>
|
||||
<option value="hours">{t("hour_timeUnit")}</option>
|
||||
</select>
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</Label>
|
||||
</div>
|
||||
</div>
|
||||
</RadioGroup.Root>
|
||||
</SettingsToggle>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@calcom/web",
|
||||
"version": "2.6.7",
|
||||
"version": "2.6.8",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"analyze": "ANALYZE=true next build",
|
||||
|
||||
@@ -17,7 +17,8 @@ import path from "path";
|
||||
|
||||
import checkLicense from "@calcom/features/ee/common/server/checkLicense";
|
||||
import ImpersonationProvider from "@calcom/features/ee/impersonation/lib/ImpersonationProvider";
|
||||
import { hostedCal, isSAMLLoginEnabled } from "@calcom/features/ee/sso/lib/saml";
|
||||
import jackson from "@calcom/features/ee/sso/lib/jackson";
|
||||
import { hostedCal, isSAMLLoginEnabled, clientSecretVerifier } from "@calcom/features/ee/sso/lib/saml";
|
||||
import { ErrorCode, isPasswordValid, verifyPassword } from "@calcom/lib/auth";
|
||||
import { APP_NAME, IS_TEAM_BILLING_ENABLED, WEBAPP_URL, WEBSITE_URL } from "@calcom/lib/constants";
|
||||
import { symmetricDecrypt } from "@calcom/lib/crypto";
|
||||
@@ -222,10 +223,65 @@ if (isSAMLLoginEnabled) {
|
||||
},
|
||||
options: {
|
||||
clientId: "dummy",
|
||||
clientSecret: "dummy",
|
||||
clientSecret: clientSecretVerifier,
|
||||
},
|
||||
allowDangerousEmailAccountLinking: true,
|
||||
});
|
||||
|
||||
// Idp initiated login
|
||||
providers.push(
|
||||
CredentialsProvider({
|
||||
id: "saml-idp",
|
||||
name: "IdP Login",
|
||||
credentials: {
|
||||
code: {},
|
||||
},
|
||||
async authorize(credentials) {
|
||||
if (!credentials) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { code } = credentials;
|
||||
|
||||
if (!code) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { oauthController } = await jackson();
|
||||
|
||||
// Fetch access token
|
||||
const { access_token } = await oauthController.token({
|
||||
code,
|
||||
grant_type: "authorization_code",
|
||||
redirect_uri: `${process.env.NEXTAUTH_URL}`,
|
||||
client_id: "dummy",
|
||||
client_secret: clientSecretVerifier,
|
||||
});
|
||||
|
||||
if (!access_token) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Fetch user info
|
||||
const userInfo = await oauthController.userInfo(access_token);
|
||||
|
||||
if (!userInfo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { id, firstName, lastName, email } = userInfo;
|
||||
|
||||
return {
|
||||
id: id as unknown as number,
|
||||
firstName,
|
||||
lastName,
|
||||
email,
|
||||
name: `${firstName} ${lastName}`.trim(),
|
||||
email_verified: true,
|
||||
};
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (true) {
|
||||
@@ -326,12 +382,18 @@ export default NextAuth({
|
||||
...token,
|
||||
};
|
||||
};
|
||||
|
||||
if (!user) {
|
||||
return await autoMergeIdentities();
|
||||
}
|
||||
|
||||
if (account && account.type === "credentials") {
|
||||
if (!account) {
|
||||
return token;
|
||||
}
|
||||
if (account.type === "credentials") {
|
||||
// return token if credentials,saml-idp
|
||||
if (account.provider === "saml-idp") {
|
||||
return token;
|
||||
}
|
||||
// any other credentials, add user info
|
||||
return {
|
||||
...token,
|
||||
id: user.id,
|
||||
@@ -346,11 +408,12 @@ export default NextAuth({
|
||||
|
||||
// The arguments above are from the provider so we need to look up the
|
||||
// user based on those values in order to construct a JWT.
|
||||
if (account && account.type === "oauth" && account.provider && account.providerAccountId) {
|
||||
let idP: IdentityProvider = IdentityProvider.GOOGLE;
|
||||
if (account.provider === "saml") {
|
||||
idP = IdentityProvider.SAML;
|
||||
if (account.type === "oauth") {
|
||||
if (!account.provider || !account.providerAccountId) {
|
||||
return token;
|
||||
}
|
||||
const idP = account.provider === "saml" ? IdentityProvider.SAML : IdentityProvider.GOOGLE;
|
||||
|
||||
const existingUser = await prisma.user.findFirst({
|
||||
where: {
|
||||
AND: [
|
||||
@@ -405,14 +468,18 @@ export default NextAuth({
|
||||
if (account?.provider === "email") {
|
||||
return true;
|
||||
}
|
||||
|
||||
// In this case we've already verified the credentials in the authorize
|
||||
// callback so we can sign the user in.
|
||||
if (account?.type === "credentials") {
|
||||
return true;
|
||||
}
|
||||
// Only if provider is not saml-idp
|
||||
if (account?.provider !== "saml-idp") {
|
||||
if (account?.type === "credentials") {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (account?.type !== "oauth") {
|
||||
return false;
|
||||
if (account?.type !== "oauth") {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!user.email) {
|
||||
@@ -425,7 +492,7 @@ export default NextAuth({
|
||||
|
||||
if (account?.provider) {
|
||||
let idP: IdentityProvider = IdentityProvider.GOOGLE;
|
||||
if (account.provider === "saml") {
|
||||
if (account.provider === "saml" || account.provider === "saml-idp") {
|
||||
idP = IdentityProvider.SAML;
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
@@ -435,19 +502,18 @@ export default NextAuth({
|
||||
if (!user.email_verified) {
|
||||
return "/auth/error?error=unverified-email";
|
||||
}
|
||||
// Only google oauth on this path
|
||||
const provider = account.provider.toUpperCase() as IdentityProvider;
|
||||
|
||||
// Only google oauth on this path
|
||||
const existingUser = await prisma.user.findFirst({
|
||||
include: {
|
||||
accounts: {
|
||||
where: {
|
||||
provider: account.provider,
|
||||
provider: idP,
|
||||
},
|
||||
},
|
||||
},
|
||||
where: {
|
||||
identityProvider: provider,
|
||||
identityProvider: idP as IdentityProvider,
|
||||
identityProviderId: account.providerAccountId,
|
||||
},
|
||||
});
|
||||
@@ -569,6 +635,7 @@ export default NextAuth({
|
||||
identityProviderId: String(user.id),
|
||||
},
|
||||
});
|
||||
|
||||
const linkAccountNewUserData = { ...account, userId: newUser.id };
|
||||
await calcomAdapter.linkAccount(linkAccountNewUserData);
|
||||
|
||||
|
||||
@@ -5,8 +5,12 @@ import { defaultHandler, defaultResponder } from "@calcom/lib/server";
|
||||
|
||||
async function postHandler(req: NextApiRequest, res: NextApiResponse) {
|
||||
const { oauthController } = await jackson();
|
||||
|
||||
const { redirect_url } = await oauthController.samlResponse(req.body);
|
||||
if (redirect_url) return res.redirect(302, redirect_url);
|
||||
|
||||
if (redirect_url) {
|
||||
res.redirect(302, redirect_url);
|
||||
}
|
||||
}
|
||||
|
||||
export default defaultHandler({
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
import type { NextRequest } from "next/server";
|
||||
|
||||
export const config = {
|
||||
runtime: "edge",
|
||||
};
|
||||
|
||||
export default async function handler(req: NextRequest) {
|
||||
const countryCode = req.headers.get("x-vercel-ip-country") ?? "";
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
countryCode,
|
||||
}),
|
||||
{
|
||||
status: 200,
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { signIn } from "next-auth/react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useEffect } from "react";
|
||||
|
||||
// To handle the IdP initiated login flow callback
|
||||
export default function Page() {
|
||||
const router = useRouter();
|
||||
|
||||
useEffect(() => {
|
||||
if (!router.isReady) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { code } = router.query;
|
||||
|
||||
signIn("saml-idp", {
|
||||
callbackUrl: "/",
|
||||
code,
|
||||
});
|
||||
}, []);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { signIn } from "next-auth/react";
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
import { samlProductID, samlTenantID } from "@calcom/features/ee/sso/lib/saml";
|
||||
import { HOSTED_CAL_FEATURES } from "@calcom/lib/constants";
|
||||
|
||||
import type { inferSSRProps } from "@lib/types/inferSSRProps";
|
||||
|
||||
// This page is used to initiate the SAML authentication flow by redirecting to the SAML provider.
|
||||
// Accessible only on self-hosted Cal.com instances.
|
||||
export default function Page({ samlTenantID, samlProductID }: inferSSRProps<typeof getServerSideProps>) {
|
||||
const router = useRouter();
|
||||
|
||||
if (HOSTED_CAL_FEATURES) {
|
||||
router.push("/auth/login");
|
||||
return;
|
||||
}
|
||||
|
||||
// Initiate SAML authentication flow
|
||||
signIn(
|
||||
"saml",
|
||||
{
|
||||
callbackUrl: "/",
|
||||
},
|
||||
{ tenant: samlTenantID, product: samlProductID }
|
||||
);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export async function getServerSideProps() {
|
||||
return {
|
||||
props: {
|
||||
samlTenantID,
|
||||
samlProductID,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -561,7 +561,12 @@ export default function Success(props: SuccessProps) {
|
||||
<>
|
||||
<div className="mt-9 font-medium">{label}</div>
|
||||
<div className="col-span-2 mb-2 mt-9">
|
||||
<p className="break-words">{response.toString()}</p>
|
||||
<p
|
||||
className="break-words"
|
||||
data-testid="field-response"
|
||||
data-fob-field={field.name}>
|
||||
{response.toString()}
|
||||
</p>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -44,9 +44,6 @@ const createTeamAndAddUser = async (
|
||||
slug: `team-${workerInfo.workerIndex}-${Date.now()}`,
|
||||
},
|
||||
});
|
||||
if (!team) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { role = MembershipRole.OWNER, id: userId } = user;
|
||||
await prisma.membership.create({
|
||||
@@ -54,8 +51,10 @@ const createTeamAndAddUser = async (
|
||||
teamId: team.id,
|
||||
userId,
|
||||
role: role,
|
||||
accepted: true,
|
||||
},
|
||||
});
|
||||
return team;
|
||||
};
|
||||
|
||||
// creates a user fixture instance and stores the collection
|
||||
@@ -246,7 +245,29 @@ export const createUsersFixture = (page: Page, workerInfo: WorkerInfo) => {
|
||||
include: userIncludes,
|
||||
});
|
||||
if (scenario.hasTeam) {
|
||||
await createTeamAndAddUser({ user: { id: user.id, role: "OWNER" } }, workerInfo);
|
||||
const team = await createTeamAndAddUser({ user: { id: user.id, role: "OWNER" } }, workerInfo);
|
||||
await prisma.eventType.create({
|
||||
data: {
|
||||
team: {
|
||||
connect: {
|
||||
id: team.id,
|
||||
},
|
||||
},
|
||||
users: {
|
||||
connect: {
|
||||
id: _user.id,
|
||||
},
|
||||
},
|
||||
owner: {
|
||||
connect: {
|
||||
id: _user.id,
|
||||
},
|
||||
},
|
||||
title: "Team Event - 30min",
|
||||
slug: "team-event-30min",
|
||||
length: 30,
|
||||
},
|
||||
});
|
||||
}
|
||||
const userFixture = createUserFixture(user, store.page!);
|
||||
store.users.push(userFixture);
|
||||
|
||||
@@ -0,0 +1,433 @@
|
||||
import type { Page, PlaywrightTestArgs } from "@playwright/test";
|
||||
import { expect } from "@playwright/test";
|
||||
import { WebhookTriggerEvents } from "@prisma/client";
|
||||
import type { createUsersFixture } from "playwright/fixtures/users";
|
||||
import { uuid } from "short-uuid";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { test } from "./lib/fixtures";
|
||||
import { createHttpServer, waitFor, selectFirstAvailableTimeSlotNextMonth } from "./lib/testUtils";
|
||||
|
||||
test.describe("Manage Booking Questions", () => {
|
||||
test.afterEach(async ({ users }) => {
|
||||
await users.deleteAll();
|
||||
});
|
||||
|
||||
test.describe("For User EventType", () => {
|
||||
test("Do a booking with a user added question and verify a few thing in b/w", async ({
|
||||
page,
|
||||
users,
|
||||
context,
|
||||
}, testInfo) => {
|
||||
// Considering there are many steps in it, it would need more than default test timeout
|
||||
test.setTimeout(testInfo.timeout * 3);
|
||||
const user = await createAndLoginUserWithEventTypes({ users });
|
||||
|
||||
const webhookReceiver = await addWebhook(user);
|
||||
|
||||
await test.step("Go to EventType Page ", async () => {
|
||||
const $eventTypes = page.locator("[data-testid=event-types] > li a");
|
||||
const firstEventTypeElement = $eventTypes.first();
|
||||
|
||||
await firstEventTypeElement.click();
|
||||
});
|
||||
|
||||
await test.step("Add Question and see that it's shown on Booking Page at appropriate position", async () => {
|
||||
await addQuestionAndSave({
|
||||
page,
|
||||
question: {
|
||||
name: "how_are_you",
|
||||
type: "Name",
|
||||
label: "How are you?",
|
||||
placeholder: "I'm fine, thanks",
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
await doOnFreshPreview(page, context, async (page) => {
|
||||
const allFieldsLocator = await expectSystemFieldsToBeThere(page);
|
||||
const userFieldLocator = allFieldsLocator.nth(5);
|
||||
|
||||
await expect(userFieldLocator.locator('[name="how_are_you"]')).toBeVisible();
|
||||
// There are 2 labels right now. Will be one in future. The second one is hidden
|
||||
expect(await userFieldLocator.locator("label").nth(0).innerText()).toBe("How are you?");
|
||||
await expect(userFieldLocator.locator("input[type=text]")).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
await test.step("Hide Question and see that it's not shown on Booking Page", async () => {
|
||||
await toggleQuestionAndSave({
|
||||
name: "how_are_you",
|
||||
page,
|
||||
});
|
||||
await doOnFreshPreview(page, context, async (page) => {
|
||||
const formBuilderFieldLocator = page.locator('[data-fob-field-name="how_are_you"]');
|
||||
await expect(formBuilderFieldLocator).toBeHidden();
|
||||
});
|
||||
});
|
||||
|
||||
await test.step("Show Question Again", async () => {
|
||||
await toggleQuestionAndSave({
|
||||
name: "how_are_you",
|
||||
page,
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('Try to book without providing "How are you?" response', async () => {
|
||||
await doOnFreshPreview(page, context, async (page) => {
|
||||
await bookTimeSlot({ page, name: "Booker", email: "booker@example.com" });
|
||||
await expectErrorToBeThereFor({ page, name: "how_are_you" });
|
||||
});
|
||||
});
|
||||
|
||||
await test.step("Do a booking", async () => {
|
||||
await doOnFreshPreview(page, context, async (page) => {
|
||||
const formBuilderFieldLocator = page.locator('[data-fob-field-name="how_are_you"]');
|
||||
await expect(formBuilderFieldLocator).toBeVisible();
|
||||
expect(
|
||||
await formBuilderFieldLocator.locator('[name="how_are_you"]').getAttribute("placeholder")
|
||||
).toBe("I'm fine, thanks");
|
||||
expect(await formBuilderFieldLocator.locator("label").nth(0).innerText()).toBe("How are you?");
|
||||
await formBuilderFieldLocator.locator('[name="how_are_you"]').fill("I am great!");
|
||||
await bookTimeSlot({ page, name: "Booker", email: "booker@example.com" });
|
||||
await expect(page.locator("[data-testid=success-page]")).toBeVisible();
|
||||
|
||||
expect(
|
||||
await page.locator('[data-testid="field-response"][data-fob-field="how_are_you"]').innerText()
|
||||
).toBe("I am great!");
|
||||
|
||||
await waitFor(() => {
|
||||
expect(webhookReceiver.requestList.length).toBe(1);
|
||||
});
|
||||
|
||||
const [request] = webhookReceiver.requestList;
|
||||
|
||||
const payload = (request.body as any).payload as any;
|
||||
|
||||
expect(payload.responses).toMatchObject({
|
||||
email: {
|
||||
label: "email_address",
|
||||
value: "booker@example.com",
|
||||
},
|
||||
how_are_you: {
|
||||
label: "How are you?",
|
||||
value: "I am great!",
|
||||
},
|
||||
name: {
|
||||
label: "your_name",
|
||||
value: "Booker",
|
||||
},
|
||||
});
|
||||
|
||||
expect(payload.location).toBe("integrations:daily");
|
||||
|
||||
expect(payload.attendees[0]).toMatchObject({
|
||||
name: "Booker",
|
||||
email: "booker@example.com",
|
||||
});
|
||||
|
||||
expect(payload.userFieldsResponses).toMatchObject({
|
||||
how_are_you: {
|
||||
label: "How are you?",
|
||||
value: "I am great!",
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test.describe("For Team EventType", () => {
|
||||
test("Do a booking with a user added question and verify a few thing in b/w", async ({
|
||||
page,
|
||||
users,
|
||||
context,
|
||||
}, testInfo) => {
|
||||
// Considering there are many steps in it, it would need more than default test timeout
|
||||
test.setTimeout(testInfo.timeout * 3);
|
||||
const user = await createAndLoginUserWithEventTypes({ users });
|
||||
|
||||
const webhookReceiver = await addWebhook(user);
|
||||
|
||||
await test.step("Go to First Team Event", async () => {
|
||||
const $eventTypes = page.locator("[data-testid=event-types]").nth(1).locator("li a");
|
||||
const firstEventTypeElement = $eventTypes.first();
|
||||
|
||||
await firstEventTypeElement.click();
|
||||
});
|
||||
|
||||
await runTestStepsCommonForTeamAndUserEventType(page, context, webhookReceiver);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
async function runTestStepsCommonForTeamAndUserEventType(
|
||||
page: Page,
|
||||
context: PlaywrightTestArgs["context"],
|
||||
webhookReceiver: {
|
||||
port: number;
|
||||
close: () => import("http").Server;
|
||||
requestList: (import("http").IncomingMessage & { body?: unknown })[];
|
||||
url: string;
|
||||
}
|
||||
) {
|
||||
await test.step("Add Question and see that it's shown on Booking Page at appropriate position", async () => {
|
||||
await addQuestionAndSave({
|
||||
page,
|
||||
question: {
|
||||
name: "how_are_you",
|
||||
type: "Name",
|
||||
label: "How are you?",
|
||||
placeholder: "I'm fine, thanks",
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
await doOnFreshPreview(page, context, async (page) => {
|
||||
const allFieldsLocator = await expectSystemFieldsToBeThere(page);
|
||||
const userFieldLocator = allFieldsLocator.nth(5);
|
||||
|
||||
await expect(userFieldLocator.locator('[name="how_are_you"]')).toBeVisible();
|
||||
// There are 2 labels right now. Will be one in future. The second one is hidden
|
||||
expect(await userFieldLocator.locator("label").nth(0).innerText()).toBe("How are you?");
|
||||
await expect(userFieldLocator.locator("input[type=text]")).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
await test.step("Hide Question and see that it's not shown on Booking Page", async () => {
|
||||
await toggleQuestionAndSave({
|
||||
name: "how_are_you",
|
||||
page,
|
||||
});
|
||||
await doOnFreshPreview(page, context, async (page) => {
|
||||
const formBuilderFieldLocator = page.locator('[data-fob-field-name="how_are_you"]');
|
||||
await expect(formBuilderFieldLocator).toBeHidden();
|
||||
});
|
||||
});
|
||||
|
||||
await test.step("Show Question Again", async () => {
|
||||
await toggleQuestionAndSave({
|
||||
name: "how_are_you",
|
||||
page,
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('Try to book without providing "How are you?" response', async () => {
|
||||
await doOnFreshPreview(page, context, async (page) => {
|
||||
await bookTimeSlot({ page, name: "Booker", email: "booker@example.com" });
|
||||
await expectErrorToBeThereFor({ page, name: "how_are_you" });
|
||||
});
|
||||
});
|
||||
|
||||
await test.step("Do a booking", async () => {
|
||||
await doOnFreshPreview(page, context, async (page) => {
|
||||
const formBuilderFieldLocator = page.locator('[data-fob-field-name="how_are_you"]');
|
||||
await expect(formBuilderFieldLocator).toBeVisible();
|
||||
expect(await formBuilderFieldLocator.locator('[name="how_are_you"]').getAttribute("placeholder")).toBe(
|
||||
"I'm fine, thanks"
|
||||
);
|
||||
expect(await formBuilderFieldLocator.locator("label").nth(0).innerText()).toBe("How are you?");
|
||||
await formBuilderFieldLocator.locator('[name="how_are_you"]').fill("I am great!");
|
||||
await bookTimeSlot({ page, name: "Booker", email: "booker@example.com" });
|
||||
await expect(page.locator("[data-testid=success-page]")).toBeVisible();
|
||||
|
||||
expect(
|
||||
await page.locator('[data-testid="field-response"][data-fob-field="how_are_you"]').innerText()
|
||||
).toBe("I am great!");
|
||||
|
||||
await waitFor(() => {
|
||||
expect(webhookReceiver.requestList.length).toBe(1);
|
||||
});
|
||||
|
||||
const [request] = webhookReceiver.requestList;
|
||||
|
||||
const payload = (request.body as any).payload as any;
|
||||
|
||||
expect(payload.responses).toMatchObject({
|
||||
email: {
|
||||
label: "email_address",
|
||||
value: "booker@example.com",
|
||||
},
|
||||
how_are_you: {
|
||||
label: "How are you?",
|
||||
value: "I am great!",
|
||||
},
|
||||
name: {
|
||||
label: "your_name",
|
||||
value: "Booker",
|
||||
},
|
||||
});
|
||||
|
||||
expect(payload.location).toBe("integrations:daily");
|
||||
|
||||
expect(payload.attendees[0]).toMatchObject({
|
||||
name: "Booker",
|
||||
email: "booker@example.com",
|
||||
});
|
||||
|
||||
expect(payload.userFieldsResponses).toMatchObject({
|
||||
how_are_you: {
|
||||
label: "How are you?",
|
||||
value: "I am great!",
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function expectSystemFieldsToBeThere(page: Page) {
|
||||
const allFieldsLocator = page.locator("[data-fob-field-name]:not(.hidden)");
|
||||
const nameLocator = allFieldsLocator.nth(0);
|
||||
const emailLocator = allFieldsLocator.nth(1);
|
||||
// Location isn't rendered unless explicitly set which isn't the case here
|
||||
// const locationLocator = allFieldsLocator.nth(2);
|
||||
const additionalNotes = allFieldsLocator.nth(3);
|
||||
const guestsLocator = allFieldsLocator.nth(4);
|
||||
|
||||
await expect(nameLocator.locator('[name="name"]')).toBeVisible();
|
||||
await expect(emailLocator.locator('[name="email"]')).toBeVisible();
|
||||
|
||||
await expect(additionalNotes.locator('[name="notes"]')).toBeVisible();
|
||||
await expect(guestsLocator.locator("button")).toBeVisible();
|
||||
return allFieldsLocator;
|
||||
}
|
||||
|
||||
//TODO: Add one question for each type and see they are rendering labels and only once and are showing appropriate native component
|
||||
// Verify webhook is sent with the correct data, DB is correct (including metadata)
|
||||
|
||||
//TODO: Verify that prefill works
|
||||
async function bookTimeSlot({ page, name, email }: { page: Page; name: string; email: string }) {
|
||||
// --- fill form
|
||||
await page.fill('[name="name"]', name);
|
||||
await page.fill('[name="email"]', email);
|
||||
await page.press('[name="email"]', "Enter");
|
||||
}
|
||||
/**
|
||||
* 'option' starts from 1
|
||||
*/
|
||||
async function selectOption({
|
||||
page,
|
||||
selector,
|
||||
optionText,
|
||||
}: {
|
||||
page: Page;
|
||||
selector: { selector: string; nth: number };
|
||||
optionText: string;
|
||||
}) {
|
||||
const locatorForSelect = page.locator(selector.selector).nth(selector.nth);
|
||||
await locatorForSelect.click();
|
||||
await locatorForSelect.locator(`text="${optionText}"`).click();
|
||||
}
|
||||
|
||||
async function addQuestionAndSave({
|
||||
page,
|
||||
question,
|
||||
}: {
|
||||
page: Page;
|
||||
question: {
|
||||
name?: string;
|
||||
type?: string;
|
||||
label?: string;
|
||||
placeholder?: string;
|
||||
required?: boolean;
|
||||
};
|
||||
}) {
|
||||
await page.click('[href$="tabName=advanced"]');
|
||||
await page.click('[data-testid="add-field"]');
|
||||
|
||||
if (question.type !== undefined) {
|
||||
await selectOption({
|
||||
page,
|
||||
selector: {
|
||||
selector: "[id=test-field-type]",
|
||||
nth: 0,
|
||||
},
|
||||
optionText: question.type,
|
||||
});
|
||||
}
|
||||
|
||||
if (question.name !== undefined) {
|
||||
await page.fill('[name="name"]', question.name);
|
||||
}
|
||||
|
||||
if (question.label !== undefined) {
|
||||
await page.fill('[name="label"]', question.label);
|
||||
}
|
||||
|
||||
if (question.placeholder !== undefined) {
|
||||
await page.fill('[name="placeholder"]', question.placeholder);
|
||||
}
|
||||
|
||||
if (question.required !== undefined) {
|
||||
// await page.fill('[name="name"]', question.required);
|
||||
}
|
||||
|
||||
await page.click('[data-testid="field-add-save"]');
|
||||
await saveEventType(page);
|
||||
}
|
||||
|
||||
async function expectErrorToBeThereFor({ page, name }: { page: Page; name: string }) {
|
||||
await expect(page.locator(`[data-testid=error-message-${name}]`)).toHaveCount(1);
|
||||
// TODO: We should either verify the error message or error code in the test so we know that the correct error is shown
|
||||
// Checking for the error message isn't well maintainable as translation can change and we might want to verify in non english language as well.
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a fresh preview window and runs the callback on it giving it the preview tab's `page`
|
||||
*/
|
||||
async function doOnFreshPreview(
|
||||
page: Page,
|
||||
context: PlaywrightTestArgs["context"],
|
||||
callback: (page: Page) => Promise<void>
|
||||
) {
|
||||
const previewTabPage = await openBookingFormInPreviewTab(context, page);
|
||||
await callback(previewTabPage);
|
||||
await previewTabPage.close();
|
||||
}
|
||||
|
||||
async function toggleQuestionAndSave({ name, page }: { name: string; page: Page }) {
|
||||
await page.locator(`[data-testid="field-${name}"]`).locator('[data-testid="toggle-field"]').click();
|
||||
await saveEventType(page);
|
||||
}
|
||||
|
||||
async function createAndLoginUserWithEventTypes({ users }: { users: ReturnType<typeof createUsersFixture> }) {
|
||||
const user = await users.create(null, {
|
||||
hasTeam: true,
|
||||
});
|
||||
await user.login();
|
||||
return user;
|
||||
}
|
||||
|
||||
async function openBookingFormInPreviewTab(context: PlaywrightTestArgs["context"], page: Page) {
|
||||
const previewTabPromise = context.waitForEvent("page");
|
||||
await page.locator('[data-testid="preview-button"]').click();
|
||||
const previewTabPage = await previewTabPromise;
|
||||
await previewTabPage.waitForLoadState();
|
||||
await selectFirstAvailableTimeSlotNextMonth(previewTabPage);
|
||||
await previewTabPage.waitForNavigation({
|
||||
url: (url) => url.pathname.endsWith("/book"),
|
||||
});
|
||||
return previewTabPage;
|
||||
}
|
||||
|
||||
async function saveEventType(page: Page) {
|
||||
await page.locator("[data-testid=update-eventtype]").click();
|
||||
}
|
||||
|
||||
async function addWebhook(user: Awaited<ReturnType<typeof createAndLoginUserWithEventTypes>>) {
|
||||
const webhookReceiver = createHttpServer();
|
||||
await prisma.webhook.create({
|
||||
data: {
|
||||
id: uuid(),
|
||||
userId: user.id,
|
||||
subscriberUrl: webhookReceiver.url,
|
||||
eventTriggers: [
|
||||
WebhookTriggerEvents.BOOKING_CREATED,
|
||||
WebhookTriggerEvents.BOOKING_CANCELLED,
|
||||
WebhookTriggerEvents.BOOKING_RESCHEDULED,
|
||||
],
|
||||
},
|
||||
});
|
||||
return webhookReceiver;
|
||||
}
|
||||
@@ -90,7 +90,16 @@ test("add webhook & test that creating an event triggers a webhook call", async
|
||||
timeZone: "[redacted/dynamic]",
|
||||
language: "[redacted/dynamic]",
|
||||
},
|
||||
responses: { email: "test@example.com", name: "Test Testson" },
|
||||
responses: {
|
||||
email: {
|
||||
value: "test@example.com",
|
||||
label: "email_address",
|
||||
},
|
||||
name: {
|
||||
value: "Test Testson",
|
||||
label: "your_name",
|
||||
},
|
||||
},
|
||||
userFieldsResponses: {},
|
||||
attendees: [
|
||||
{
|
||||
|
||||
@@ -477,8 +477,8 @@
|
||||
"booking_confirmation": "قم بتأكيد {{eventTypeTitle}} مع {{profileName}}",
|
||||
"booking_reschedule_confirmation": "أعد جدولة {{eventTypeTitle}} مع {{profileName}}",
|
||||
"in_person_meeting": "الرابط أو الاجتماع الشخصي",
|
||||
"attendeeInPerson": "شخصيًا (عنوان من سيحضر)",
|
||||
"inPerson": "شخصيًا (عنوان المنظم)",
|
||||
"attendee_in_person": "شخصيًا (عنوان من سيحضر)",
|
||||
"in_person": "شخصيًا (عنوان المنظم)",
|
||||
"link_meeting": "رابط الاجتماع",
|
||||
"phone_call": "رقم هاتف الحضور",
|
||||
"your_number": "رقم هاتفك",
|
||||
|
||||
@@ -470,8 +470,8 @@
|
||||
"booking_confirmation": "Potvrďte {{eventTypeTitle}} skrz účet {{profileName}}",
|
||||
"booking_reschedule_confirmation": "Přesunout {{eventTypeTitle}} na jindy skrz účet {{profileName}}",
|
||||
"in_person_meeting": "Odkaz nebo osobní schůzka",
|
||||
"attendeeInPerson": "Osobně (adresa účastníka)",
|
||||
"inPerson": "Osobně (adresa organizátora)",
|
||||
"attendee_in_person": "Osobně (adresa účastníka)",
|
||||
"in_person": "Osobně (adresa organizátora)",
|
||||
"link_meeting": "Odkaz na schůzku",
|
||||
"phone_call": "Telefon",
|
||||
"your_number": "Vaše telefonní číslo",
|
||||
|
||||
@@ -477,8 +477,8 @@
|
||||
"booking_confirmation": "Bekræft din {{eventTypeTitle}} med {{profileName}}",
|
||||
"booking_reschedule_confirmation": "Omlæg din {{eventTypeTitle}} med {{profileName}}",
|
||||
"in_person_meeting": "Personligt møde",
|
||||
"attendeeInPerson": "Personlig (Deltageradresse)",
|
||||
"inPerson": "Personlig (Arrangøradresse)",
|
||||
"attendee_in_person": "Personlig (Deltageradresse)",
|
||||
"in_person": "Personlig (Arrangøradresse)",
|
||||
"link_meeting": "Link møde",
|
||||
"phone_call": "Deltagers Telefonnummer",
|
||||
"your_number": "Dit telefonnummer",
|
||||
|
||||
@@ -477,8 +477,8 @@
|
||||
"booking_confirmation": "Bestätigen Sie {{eventTypeTitle}} mit {{profileName}}",
|
||||
"booking_reschedule_confirmation": "Planen Sie Ihr {{eventTypeTitle}} mit {{profileName}} um",
|
||||
"in_person_meeting": "Vor-Ort-Termin",
|
||||
"attendeeInPerson": "Persönlich (Teilnehmeradresse)",
|
||||
"inPerson": "Persönlich (Organisator-Adresse)",
|
||||
"attendee_in_person": "Persönlich (Teilnehmeradresse)",
|
||||
"in_person": "Persönlich (Organisator-Adresse)",
|
||||
"link_meeting": "Termin verknüpfen",
|
||||
"phone_call": "Telefonat",
|
||||
"your_number": "Ihre Telefonnummer",
|
||||
|
||||
@@ -110,6 +110,7 @@
|
||||
"hidden_team_owner_message": "You need a pro account to use teams, you are hidden until you upgrade.",
|
||||
"link_expires": "p.s. It expires in {{expiresIn}} hours.",
|
||||
"upgrade_to_per_seat": "Upgrade to Per-Seat",
|
||||
"seat_options_doesnt_support_confirmation":"Seats option doesn't support confirmation requirement",
|
||||
"team_upgrade_seats_details": "Of the {{memberCount}} members in your team, {{unpaidCount}} seat(s) are unpaid. At ${{seatPrice}}/month per seat the estimated total cost of your membership is ${{totalCost}}/month.",
|
||||
"team_upgrade_banner_description": "Thank you for trialing our new team plan. We noticed your team \"{{teamName}}\" needs to be upgraded.",
|
||||
"team_upgrade_banner_action": "Upgrade here",
|
||||
@@ -477,8 +478,8 @@
|
||||
"booking_confirmation": "Confirm your {{eventTypeTitle}} with {{profileName}}",
|
||||
"booking_reschedule_confirmation": "Reschedule your {{eventTypeTitle}} with {{profileName}}",
|
||||
"in_person_meeting": "In-person meeting",
|
||||
"attendeeInPerson": "In Person (Attendee Address)",
|
||||
"inPerson": "In Person (Organizer Address)",
|
||||
"attendee_in_person": "In Person (Attendee Address)",
|
||||
"in_person": "In Person (Organizer Address)",
|
||||
"link_meeting": "Link meeting",
|
||||
"phone_call": "Attendee Phone Number",
|
||||
"your_number": "Your phone number",
|
||||
@@ -1618,9 +1619,10 @@
|
||||
"keep_me_connected_with_form": "Keep me connected with the form",
|
||||
"fields_in_form_duplicated":"Any changes in Router and Fields of the form being duplicated, would reflect in the duplicate.",
|
||||
"form_deleted": "Form deleted",
|
||||
"delete_form": "Delete Form",
|
||||
"delete_form": "Are you sure you want to delete this form?",
|
||||
"delete_form_action": "Yes, delete Form",
|
||||
"delete_form_confirmation":"Are you sure you want to delete this form? Anyone who you've shared the link with will no longer be able to book using it. Also, all associated responses would be deleted.",
|
||||
"delete_form_confirmation":"Anyone who you've shared the link with will no longer be able to access it.",
|
||||
"delete_form_confirmation_2":"All associated responses will be deleted.",
|
||||
"typeform_redirect_url_copied": "Typeform Redirect URL copied! You can go and set the URL in Typeform form.",
|
||||
"modifications_in_fields_warning": "Modifications in fields and routes of following forms will be reflected in this form.",
|
||||
"connected_forms": "Connected Forms",
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"upgrade_now": "Actualizar ahora",
|
||||
"accept_invitation": "Aceptar invitación",
|
||||
"calcom_explained": "{{appName}} proporciona una infraestructura de programación para absolutamente todo el mundo.",
|
||||
"calcom_explained_new_user": "¡Termine de configurar tu cuenta de {{appName}}! Solo le faltan unos pasos para resolver todos sus problemas de programación.",
|
||||
"have_any_questions": "¿Tienes preguntas? Estamos aquí para ayudar.",
|
||||
"reset_password_subject": "{{appName}}: Instrucciones para restablecer la contraseña",
|
||||
"event_declined_subject": "Rechazado: {{title}} en {{date}}",
|
||||
@@ -23,6 +24,8 @@
|
||||
"rejection_reason_description": "¿Estás seguro de que deseas rechazar la reserva? Le haremos saber a la persona que ha intentado reservar. Puedes indicar una razón a continuación.",
|
||||
"rejection_confirmation": "Rechazar la reserva",
|
||||
"manage_this_event": "Administrar este evento",
|
||||
"invite_team_member": "Invite a un miembro del equipo",
|
||||
"invite_team_notifcation_badge": "Inv.",
|
||||
"your_event_has_been_scheduled": "Tu evento ha sido reprogramado",
|
||||
"your_event_has_been_scheduled_recurring": "Su evento recurrente se ha programado",
|
||||
"accept_our_license": "Acepte nuestra licencia cambiando la variable .env <1>NEXT_PUBLIC_LICENSE_CONSENT</1> a '{{agree}}'.",
|
||||
@@ -410,6 +413,8 @@
|
||||
"password_updated_successfully": "Contraseña Actualizada con Éxito",
|
||||
"password_has_been_changed": "Su contraseña se ha cambiado correctamente.",
|
||||
"error_changing_password": "Error al cambiar la contraseña",
|
||||
"session_timeout_changed": "La configuración de su sesión se ha actualizado correctamente.",
|
||||
"session_timeout_change_error": "Error al actualizar la configuración de sesión",
|
||||
"something_went_wrong": "Algo ha Fallado.",
|
||||
"something_doesnt_look_right": "¿Algo no se ve bien?",
|
||||
"please_try_again": "Por Favor, Inténtalo de Nuevo.",
|
||||
@@ -428,6 +433,7 @@
|
||||
"password_hint_num": "Debe contener al menos 1 número",
|
||||
"invalid_password_hint": "La contraseña debe tener un mínimo de {{passwordLength}} caracteres que contengan al menos un número y una mezcla de letras mayúsculas y minúsculas",
|
||||
"incorrect_password": "La Contraseña es Incorrecta.",
|
||||
"incorrect_username_password": "El nombre de usuario o la contraseña son incorrectos.",
|
||||
"24_h": "24hs",
|
||||
"use_setting": "Usar Ajuste",
|
||||
"am_pm": "am/pm",
|
||||
@@ -455,6 +461,7 @@
|
||||
"slots_load_fail": "No se pudo cargar el intervalo de tiempo disponible.",
|
||||
"additional_guests": "Añadir invitados",
|
||||
"your_name": "Tu Nombre",
|
||||
"your_full_name": "Su nombre completo",
|
||||
"email_address": "Email",
|
||||
"enter_valid_email": "Ingresa un correo electrónico válido",
|
||||
"location": "Ubicación",
|
||||
@@ -470,8 +477,8 @@
|
||||
"booking_confirmation": "Confirma tu {{eventTypeTitle}} con {{profileName}}",
|
||||
"booking_reschedule_confirmation": "Reprogramar tu {{eventTypeTitle}} con {{profileName}}",
|
||||
"in_person_meeting": "Reunión en Persona",
|
||||
"attendeeInPerson": "En persona (dirección del asistente)",
|
||||
"inPerson": "En persona (dirección del organizador)",
|
||||
"attendee_in_person": "En persona (dirección del asistente)",
|
||||
"in_person": "En persona (dirección del organizador)",
|
||||
"link_meeting": "Enlace de la reunión",
|
||||
"phone_call": "Número de teléfono del asistente",
|
||||
"your_number": "Tu número de teléfono",
|
||||
@@ -508,6 +515,8 @@
|
||||
"admin": "Administrador",
|
||||
"administrator_user": "Usuario administrador",
|
||||
"lets_create_first_administrator_user": "Vamos a crear el primer usuario administrador.",
|
||||
"admin_user_created": "Configuración del usuario administrador",
|
||||
"admin_user_created_description": "Ya ha creado un usuario administrador. Ahora puede iniciar sesión en su cuenta.",
|
||||
"new_member": "Nuevo Miembro",
|
||||
"invite": "Invitación",
|
||||
"add_team_members": "Añadir miembros del equipo",
|
||||
@@ -657,6 +666,7 @@
|
||||
"edit_availability": "Editar disponibilidad",
|
||||
"configure_availability": "Configure los horarios en los que está disponible para realizar reservas.",
|
||||
"copy_times_to": "Copiar tiempos en",
|
||||
"copy_times_to_tooltip": "Copiar tiempos a…",
|
||||
"change_weekly_schedule": "Cambia tu Horario Semanal",
|
||||
"logo": "Logotipo",
|
||||
"error": "Error",
|
||||
@@ -668,6 +678,7 @@
|
||||
"add_attendees": "Añadir Asistentes",
|
||||
"show_advanced_settings": "Mostrar Opciones Avanzadas",
|
||||
"event_name": "Nombre del Evento",
|
||||
"event_name_in_calendar": "Nombre del evento en el calendario",
|
||||
"event_name_tooltip": "Nombre que aparecerá en los calendarios",
|
||||
"meeting_with_user": "Reunión con {{attendeeName}}",
|
||||
"additional_inputs": "Campos Adicionales",
|
||||
@@ -786,6 +797,7 @@
|
||||
"number_apps_one": "{{count}} aplicación",
|
||||
"number_apps_other": "{{count}} aplicaciones",
|
||||
"trending_apps": "Aplicaciones populares",
|
||||
"most_popular": "Más popular",
|
||||
"explore_apps": "Aplicaciones {{category}}",
|
||||
"installed_apps": "Aplicaciones instaladas",
|
||||
"free_to_use_apps": "Gratis",
|
||||
@@ -796,12 +808,14 @@
|
||||
"no_category_apps_description_analytics": "Añada una aplicación de análisis para sus páginas de reserva",
|
||||
"no_category_apps_description_automation": "Añada una aplicación de automatización para utilizar",
|
||||
"no_category_apps_description_other": "Añade cualquier otro tipo de aplicación para hacer todo tipo de tareas",
|
||||
"no_category_apps_description_web3": "Agregue una aplicación web3 para sus páginas de reserva",
|
||||
"installed_app_calendar_description": "Configure el(los) calendario(s) para comprobar conflictos y evitar reservas duplicadas.",
|
||||
"installed_app_conferencing_description": "Añade tus aplicaciones de videoconferencia favoritas para las reuniones",
|
||||
"installed_app_payment_description": "Configura los servicios de procesamiento de pagos que vas a utilizar para cobrar a tus clientes.",
|
||||
"installed_app_analytics_description": "Configure qué aplicaciones de análisis va a utilizar para sus páginas de reserva",
|
||||
"installed_app_other_description": "Todas tus aplicaciones instaladas de otras categorías.",
|
||||
"installed_app_automation_description": "Configure qué aplicaciones de automatización va a utilizar",
|
||||
"installed_app_web3_description": "Configure qué aplicaciones web3 usar para sus páginas de reserva",
|
||||
"analytics": "Análisis",
|
||||
"empty_installed_apps_headline": "No hay aplicaciones instaladas",
|
||||
"empty_installed_apps_description": "Las aplicaciones te permiten mejorar significativamente tu flujo de trabajo y mejorar tu agendamiento.",
|
||||
@@ -929,6 +943,11 @@
|
||||
"current_location": "Ubicación actual",
|
||||
"user_phone": "Su número de teléfono",
|
||||
"new_location": "Nueva ubicación",
|
||||
"session": "Sesión",
|
||||
"session_description": "Controle la sesión de su cuenta",
|
||||
"session_timeout_after": "Tiempo de sesión agotado después de",
|
||||
"session_timeout": "Tiempo de sesión agotado",
|
||||
"session_timeout_description": "Invalide su sesión después de una cierta cantidad de tiempo.",
|
||||
"no_location": "No se ha definido ninguna ubicación",
|
||||
"set_location": "Establecer ubicación",
|
||||
"update_location": "Actualizar ubicación",
|
||||
@@ -1072,6 +1091,7 @@
|
||||
"broken_video_action": "No pudimos agregar el enlace de <1>{{location}}</1> a tu evento agendado. Contacta a tus invitados o actualiza tu calendario para agregar los detalles. Puedes <3>cambiar la ubicación de tu tipo de evento</3> o <5>remover la App y agregarla de nuevo.</5>",
|
||||
"broken_calendar_action": "No pudimos actualizar tu <1>{{calendar}}</1>. <2> Comprueba la configuración de tu calendario o elimina y añade tu calendario de nuevo </2>",
|
||||
"attendee_name": "Nombre del asistente",
|
||||
"scheduler_full_name": "El nombre completo de la persona que reserva",
|
||||
"broken_integration": "Integración rota",
|
||||
"problem_adding_video_link": "Hubo un problema al añadir un enlace de vídeo",
|
||||
"problem_updating_calendar": "Hubo un problema al actualizar tu calendario",
|
||||
@@ -1214,6 +1234,7 @@
|
||||
"connect_automation_apps": "Conecte aplicaciones de automatización",
|
||||
"connect_analytics_apps": "Conecte aplicaciones de análisis",
|
||||
"connect_other_apps": "Conectar otras aplicaciones",
|
||||
"connect_web3_apps": "Conectar aplicaciones web3",
|
||||
"current_step_of_total": "Paso {{currentStep}} de {{maxSteps}}",
|
||||
"add_variable": "Añadir variable",
|
||||
"custom_phone_number": "Número de teléfono personalizado",
|
||||
@@ -1230,6 +1251,7 @@
|
||||
"to": "Para",
|
||||
"workflow_turned_on_successfully": "El flujo de trabajo {{workflowName}} se ha activado {{offOn}} con éxito",
|
||||
"download_responses": "Descargar respuestas",
|
||||
"download_responses_description": "Descargue todas las respuestas de su formulario en formato CSV.",
|
||||
"download": "Descargar",
|
||||
"create_your_first_form": "Crea tu primer formulario",
|
||||
"create_your_first_form_description": "Con los formularios de orientación puedes hacer preguntas calificadoras y encaminarte hacia la persona o tipo de evento correctos.",
|
||||
@@ -1271,6 +1293,8 @@
|
||||
"routing_forms_send_email_owner": "Enviar correo electrónico al propietario",
|
||||
"routing_forms_send_email_owner_description": "Mande un correo electrónico al propietario cuando se envía el formulario",
|
||||
"add_new_form": "Añadir formulario nuevo",
|
||||
"create_your_first_route": "Cree su primera ruta",
|
||||
"route_to_the_right_person": "Ruta a la persona adecuada en función de las respuestas a su formulario",
|
||||
"form_description": "Crea tu formulario para dirigirlo a un agente de reservas",
|
||||
"copy_link_to_form": "Copiar enlace al formulario",
|
||||
"theme": "Tema",
|
||||
@@ -1301,6 +1325,7 @@
|
||||
"password_reset_leading": "Si no recibe un correo electrónico pronto, compruebe que la dirección de correo que ha introducido sea correcta, revise su carpeta de correo no deseado o comuníquese con el equipo de soporte si el problema persiste.",
|
||||
"password_updated": "¡Contraseña actualizada!",
|
||||
"pending_payment": "Pago pendiente",
|
||||
"pending_invites": "Invitaciones pendientes",
|
||||
"confirmation_page_rainbow": "Cierra el acceso a tu evento con tokens o NFTs en Ethereum, Polygon, etc.",
|
||||
"not_on_cal": "No estás en {{appName}}",
|
||||
"no_calendar_installed": "No hay ningún calendario instalado",
|
||||
@@ -1427,6 +1452,9 @@
|
||||
"disabled_calendar": "Si tiene otro calendario instalado, las nuevas reservas se añadirán a él. De lo contrario, conecte un nuevo calendario para que no se pierda ninguna reserva nueva.",
|
||||
"enable_apps": "Activar aplicaciones",
|
||||
"enable_apps_description": "Active aplicaciones que los usuarios puedan integrar con Cal.com",
|
||||
"purchase_license": "Compre una licencia",
|
||||
"already_have_key": "Ya tengo una clave:",
|
||||
"already_have_key_suggestion": "Copie aquí su variable de entorno CALCOM_LICENSE_KEY existente.",
|
||||
"app_is_enabled": "{{appName}} está activada",
|
||||
"app_is_disabled": "{{appName}} está desactivada",
|
||||
"keys_have_been_saved": "Se han guardado las claves",
|
||||
@@ -1447,6 +1475,7 @@
|
||||
"individual": "Individuo",
|
||||
"all_bookings_filter_label": "Todas las reservas",
|
||||
"all_users_filter_label": "Todos los usuarios",
|
||||
"your_bookings_filter_label": "Sus reservas",
|
||||
"meeting_url_variable": "URL de la reunión",
|
||||
"meeting_url_info": "URL de la reunión del evento",
|
||||
"date_overrides": "Anular fechas",
|
||||
@@ -1485,6 +1514,7 @@
|
||||
"round_robin_hosts": "Anfitriones por turnos",
|
||||
"minimum_round_robin_hosts_count": "Número de anfitriones requeridos para asistir",
|
||||
"hosts": "Anfitriones",
|
||||
"upgrade_to_enable_feature": "Debe crear un equipo para activar esta función. Haga clic para crear un equipo.",
|
||||
"new_attendee": "Nuevo asistente",
|
||||
"awaiting_approval": "En espera de aprobación",
|
||||
"requires_google_calendar": "Esta aplicación requiere una conexión con Google Calendar",
|
||||
@@ -1493,9 +1523,99 @@
|
||||
"continue_to_install_google_calendar": "Siga con la instalación de Google Calendar",
|
||||
"install_google_meet": "Instale Google Meet",
|
||||
"install_google_calendar": "Instale Google Calendar",
|
||||
"sender_name": "Nombre del remitente",
|
||||
"already_invited": "Asistente ya invitado",
|
||||
"no_recordings_found": "No se encontraron grabaciones",
|
||||
"reporting": "Reportando",
|
||||
"reporting_feature": "Vea todos los datos entrantes y descárguelos como un CSV",
|
||||
"teams_plan_required": "Se requiere un plan de equipos",
|
||||
"routing_forms_are_a_great_way": "Los formularios de enrutamiento son una excelente manera de enrutar sus clientes potenciales entrantes a la persona adecuada. Actualice a un plan de equipos para acceder a esta función.",
|
||||
"choose_a_license": "Elija una licencia",
|
||||
"choose_license_description": "Cal.com viene con una licencia AGPLv3 accesible y gratuita con algunas limitaciones que se puede actualizar a una licencia Empresarial en cualquier momento. Puede actualizar en cualquier momento más tarde.",
|
||||
"license": "Licencia",
|
||||
"agplv3_license": "Licencia AGPLv3",
|
||||
"ee_enterprise_license": "Licencia Empresarial \"/ee\"",
|
||||
"enterprise_booking_fee": "A partir de {{enterprise_booking_fee}}/mes",
|
||||
"enterprise_license_includes": "Todo para un caso de uso comercial",
|
||||
"no_need_to_keep_your_code_open_source": "No es necesario mantener su código abierto",
|
||||
"repackage_rebrand_resell": "Vuelva a empaquetar, cambie la marca y revenda fácilmente",
|
||||
"a_vast_suite_of_enterprise_features": "Un amplio conjunto de funciones empresariales",
|
||||
"free_license_fee": "$0,00/mes",
|
||||
"forever_open_and_free": "Siempre abierto y gratis",
|
||||
"required_to_keep_your_code_open_source": "Necesario para mantener su código abierto",
|
||||
"cannot_repackage_and_resell": "No se puede volver a empaquetar, cambiar la marca y revender fácilmente",
|
||||
"no_enterprise_features": "Sin características empresariales",
|
||||
"step_enterprise_license": "Licencia Empresarial",
|
||||
"step_enterprise_license_description": "Todo para un caso de uso comercial con alojamiento privado, reempaquetado, cambio de marca y reventa, además de acceso a componentes empresariales exclusivos.",
|
||||
"setup": "Configuración",
|
||||
"setup_description": "Configurar la instancia de Cal.com",
|
||||
"configure": "Configurar",
|
||||
"sso_configuration": "Configuración de SAML",
|
||||
"sso_configuration_description": "Configure SAML/OIDC SSO y permita que los miembros del equipo inicien sesión con un proveedor de identidad",
|
||||
"sso_oidc_heading": "SSO con OIDC",
|
||||
"sso_oidc_description": "Configure OIDC SSO con el proveedor de identidad de su elección.",
|
||||
"sso_oidc_configuration_title": "Configuración OIDC",
|
||||
"sso_oidc_configuration_description": "Configure la conexión OIDC a su proveedor de identidad. Puede encontrar la información requerida en su proveedor de identidad.",
|
||||
"sso_oidc_callback_copied": "URL de devolución de llamada copiada",
|
||||
"sso_saml_heading": "SSO con SAML",
|
||||
"sso_saml_description": "Configure SAML SSO con el proveedor de identidad de su elección.",
|
||||
"sso_saml_configuration_title": "Configuración de SAML",
|
||||
"sso_saml_configuration_description": "Configure la conexión SAML a su proveedor de identidad. Puede encontrar la información requerida en su proveedor de identidad.",
|
||||
"sso_saml_acsurl_copied": "URL de ACS copiada",
|
||||
"sso_saml_entityid_copied": "ID de entidad copiado",
|
||||
"sso_connection_created_successfully": "Configuración de {{connectionType}} creada con éxito",
|
||||
"sso_connection_deleted_successfully": "Configuración de {{connectionType}} eliminada con éxito",
|
||||
"delete_sso_configuration": "Eliminar la configuración de {{connectionType}}",
|
||||
"delete_sso_configuration_confirmation": "Sí, eliminar la configuración de {{connectionType}}",
|
||||
"delete_sso_configuration_confirmation_description": "¿Está seguro de que desea eliminar la configuración de {{connectionType}}? Los miembros de su equipo que utilicen el inicio de sesión {{connectionType}} ya no podrán acceder a Cal.com.",
|
||||
"organizer_timezone": "Zona horaria del organizador",
|
||||
"email_no_user_cta": "Crea tu Cuenta",
|
||||
"email_user_cta": "Ver la invitación",
|
||||
"email_no_user_invite_heading": "Lo han invitado a unirse a un equipo en {{appName}}",
|
||||
"email_no_user_invite_subheading": "{{invitedBy}} lo invitó a unirse a su equipo en {{appName}}. {{appName}} es el programador de eventos que les permite a usted y a su equipo programar reuniones sin correos electrónicos de ida y vuelta.",
|
||||
"email_no_user_invite_steps_intro": "Lo guiaremos a través de unos pocos pasos y disfrutará de una programación sin estrés con su equipo en muy poco tiempo.",
|
||||
"email_no_user_step_one": "Elija su nombre de usuario",
|
||||
"email_no_user_step_two": "Conecte su cuenta de calendario",
|
||||
"email_no_user_step_three": "Establezca su disponibilidad",
|
||||
"email_no_user_step_four": "Únase a {{teamName}}",
|
||||
"email_no_user_signoff": "Feliz programación le desea el equipo de {{appName}}",
|
||||
"impersonation_user_tip": "Está a punto de suplantar a un usuario, lo que significa que puede hacer cambios en su nombre. Tenga cuidado.",
|
||||
"available_variables": "Variables disponibles",
|
||||
"scheduler": "{Scheduler}",
|
||||
"recommended_next_steps": "Siguientes pasos recomendados",
|
||||
"create_a_managed_event": "Crear un tipo de evento administrado",
|
||||
"meetings_are_better_with_the_right": "Las reuniones son mejores con los miembros del equipo correctos. Invítelos ahora.",
|
||||
"collective_or_roundrobin": "Colectivo o turnos rotativos",
|
||||
"book_your_team_members": "Reserve a los miembros de su equipo en conjunto con eventos colectivos o realice un ciclo para encontrar a la persona adecuada con turnos rotativos.",
|
||||
"default_app_link_title": "Establecer un enlace de aplicación predeterminado",
|
||||
"default_app_link_description": "Establecer un enlace de aplicación predeterminado permite que todos los tipos de eventos recién creados utilicen el enlace de aplicación que establezca.",
|
||||
"change_default_conferencing_app": "Establecer como predeterminado",
|
||||
"booking_confirmation_failed": "Error al confirmar la reserva"
|
||||
"under_maintenance": "Fuera de servicio por mantenimiento",
|
||||
"under_maintenance_description": "El equipo de {{appName}} está realizando un mantenimiento programado. Si tiene alguna pregunta, comuníquese con soporte.",
|
||||
"event_type_seats": "{{numberOfSeats}} plazas",
|
||||
"booking_with_payment_cancelled": "Ya no es posible pagar por este evento",
|
||||
"booking_with_payment_cancelled_already_paid": "Un reembolso por el pago de esta reserva está en camino.",
|
||||
"booking_with_payment_cancelled_refunded": "El pago de esta reserva se ha reembolsado.",
|
||||
"booking_confirmation_failed": "Error al confirmar la reserva",
|
||||
"get_started_zapier_templates": "Comience con las plantillas de Zapier",
|
||||
"a_routing_form": "Un formulario de enrutamiento",
|
||||
"form_description_placeholder": "Descripción del formulario",
|
||||
"keep_me_connected_with_form": "Mantenerme conectado con el formulario",
|
||||
"fields_in_form_duplicated": "Cualquier cambio en el enrutador y los campos del formulario que se está duplicando se reflejará en el duplicado.",
|
||||
"form_deleted": "Formulario eliminado",
|
||||
"delete_form": "Eliminar formulario",
|
||||
"delete_form_action": "Sí, eliminar formulario",
|
||||
"delete_form_confirmation": "¿Está seguro de que desea eliminar este formulario? Cualquier persona con la que haya compartido el enlace ya no podrá reservar con él. Además, se eliminarían todas las respuestas asociadas.",
|
||||
"typeform_redirect_url_copied": "¡Se copió la URL de redireccionamiento de Typeform! Puede ir y establecer la URL en el formulario Typeform.",
|
||||
"modifications_in_fields_warning": "Las modificaciones en los campos y rutas de los siguientes formularios se reflejarán en este formulario.",
|
||||
"connected_forms": "Formularios conectados",
|
||||
"form_modifications_warning": "Los siguientes formularios se verían afectados cuando modifique campos o rutas aquí.",
|
||||
"responses_collection_waiting_description": "Espere un tiempo para que se recopilen las respuestas. También puede ir y enviar el formulario usted mismo.",
|
||||
"this_is_what_your_users_would_see": "Esto es lo que verían sus usuarios",
|
||||
"identifies_name_field": "Identifica el campo con este nombre.",
|
||||
"add_1_option_per_line": "Agregue 1 opción por línea",
|
||||
"select_a_router": "Seleccione un enrutador",
|
||||
"add_a_new_route": "Agregar una ruta nueva",
|
||||
"no_responses_yet": "Aún no hay respuestas",
|
||||
"this_will_be_the_placeholder": "Este será el marcador de posición"
|
||||
}
|
||||
|
||||
@@ -110,6 +110,7 @@
|
||||
"hidden_team_owner_message": "Vous avez besoin d'un compte Pro pour utiliser les équipes, vous êtes masqué(e) jusqu'à ce que vous mettiez à niveau.",
|
||||
"link_expires": "p.s. Il expire dans {{expiresIn}} heures.",
|
||||
"upgrade_to_per_seat": "Mise à niveau vers la place",
|
||||
"seat_options_doesnt_support_confirmation": "L'option de places ne prend pas en charge l'exigence de confirmation",
|
||||
"team_upgrade_seats_details": "Parmi les {{memberCount}} membres de votre équipe, {{unpaidCount}} place(s) sont impayées. À {{seatPrice}} $/mois par place, le coût total estimé de votre abonnement est de {{totalCost}} $/mois.",
|
||||
"team_upgrade_banner_description": "Merci d'avoir essayé notre nouveau plan Équipes. Nous avons remarqué que votre équipe « {{teamName}} » doit être mise à niveau.",
|
||||
"team_upgrade_banner_action": "Mettre à niveau",
|
||||
@@ -477,8 +478,8 @@
|
||||
"booking_confirmation": "Confirmez votre {{eventTypeTitle}} avec {{profileName}}",
|
||||
"booking_reschedule_confirmation": "Replanifiez votre {{eventTypeTitle}} avec {{profileName}}",
|
||||
"in_person_meeting": "Rendez-vous en personne",
|
||||
"attendeeInPerson": "En personne (adresse du participant)",
|
||||
"inPerson": "En personne (adresse de l'organisateur)",
|
||||
"attendee_in_person": "En personne (adresse du participant)",
|
||||
"in_person": "En personne (adresse de l'organisateur)",
|
||||
"link_meeting": "Rendez-vous avec lien",
|
||||
"phone_call": "Numéro de téléphone du participant",
|
||||
"your_number": "Votre numéro de téléphone",
|
||||
@@ -580,7 +581,7 @@
|
||||
"default_duration_no_options": "Veuillez d'abord choisir les durées disponibles",
|
||||
"multiple_duration_mins": "{{count}} $t(minute_timeUnit)",
|
||||
"minutes": "minutes",
|
||||
"round_robin": "Round-robin",
|
||||
"round_robin": "Round-Robin",
|
||||
"round_robin_description": "Alternez vos rendez-vous entre plusieurs membres d'équipe.",
|
||||
"url": "Lien",
|
||||
"hidden": "Masqué",
|
||||
@@ -1349,7 +1350,7 @@
|
||||
"manage_billing": "Gérer la facturation",
|
||||
"manage_billing_description": "Gérez tout ce qui est en lien avec la facturation.",
|
||||
"billing_freeplan_title": "Vous êtes actuellement sur le plan Gratuit",
|
||||
"billing_freeplan_description": "Nous travaillons mieux en équipe. Élargissez vos workflows avec le round-robin et les événements collectifs et produisez des formulaires de routage avancés.",
|
||||
"billing_freeplan_description": "Nous travaillons mieux en équipe. Élargissez vos workflows avec le Round-Robin et les événements collectifs et produisez des formulaires de routage avancés.",
|
||||
"billing_freeplan_cta": "Essayer maintenant",
|
||||
"billing_manage_details_title": "Affichez et gérez vos informations de facturation",
|
||||
"billing_manage_details_description": "Affichez et modifiez vos informations de facturation, et annulez votre abonnement.",
|
||||
@@ -1437,10 +1438,10 @@
|
||||
"collective_scheduling": "Planification collective",
|
||||
"make_it_easy_to_book": "Facilitez la réservation de votre équipe lorsque tout le monde est disponible.",
|
||||
"find_the_best_person": "Trouvez la meilleure personne disponible et alternez à travers votre équipe.",
|
||||
"fixed_round_robin": "Round-robin fixe",
|
||||
"add_one_fixed_attendee": "Ajoutez un participant fixe et le round-robin via un certain nombre de participants.",
|
||||
"fixed_round_robin": "Round-Robin fixe",
|
||||
"add_one_fixed_attendee": "Ajoutez un participant fixe et le Round-Robin via un certain nombre de participants.",
|
||||
"calcom_is_better_with_team": "Cal.com est meilleur en équipe",
|
||||
"add_your_team_members": "Ajoutez les membres de votre équipe à vos types d'événements. Utilisez la planification collective pour inclure tout le monde ou trouvez la personne la plus appropriée avec la planification round-robin.",
|
||||
"add_your_team_members": "Ajoutez les membres de votre équipe à vos types d'événements. Utilisez la planification collective pour inclure tout le monde ou trouvez la personne la plus appropriée avec la planification Round-Robin.",
|
||||
"booking_limit_reached": "La limite de réservation pour ce type d'événement a été atteinte",
|
||||
"admin_has_disabled": "Un administrateur a désactivé {{appName}}",
|
||||
"disabled_app_affects_event_type": "Un administrateur a désactivé {{appName}} qui affecte votre type d'événement {{eventType}}",
|
||||
@@ -1512,7 +1513,7 @@
|
||||
"assignment": "Affectation",
|
||||
"fixed_hosts": "Hôtes fixes",
|
||||
"add_fixed_hosts": "Ajouter des hôtes fixes",
|
||||
"round_robin_hosts": "Hôtes round-robin",
|
||||
"round_robin_hosts": "Hôtes Round-Robin",
|
||||
"minimum_round_robin_hosts_count": "Nombre d'hôtes requis pour participer",
|
||||
"hosts": "Hôtes",
|
||||
"upgrade_to_enable_feature": "Vous devez créer une équipe pour activer cette fonctionnalité. Cliquez pour créer une équipe.",
|
||||
@@ -1590,8 +1591,8 @@
|
||||
"create_a_managed_event": "Créer un type d'événement géré",
|
||||
"meetings_are_better_with_the_right": "Les rendez-vous sont meilleurs avec les bons membres d'équipe. Invitez-les maintenant.",
|
||||
"create_a_one_one_template": "Créez un modèle unique pour un type d'événement et distribuez-le à plusieurs membres.",
|
||||
"collective_or_roundrobin": "Collective ou round-robin",
|
||||
"book_your_team_members": "Réservez les membres de votre équipe entre eux avec des événements collectifs ou mettez en place un cycle pour obtenir la bonne personne avec le round-robin.",
|
||||
"collective_or_roundrobin": "Collective ou Round-Robin",
|
||||
"book_your_team_members": "Réservez les membres de votre équipe entre eux avec des événements collectifs ou mettez en place un cycle pour obtenir la bonne personne avec le Round-Robin.",
|
||||
"create_event_on": "Créer un événement dans",
|
||||
"default_app_link_title": "Définir un lien d'application par défaut",
|
||||
"default_app_link_description": "Définir un lien d'application par défaut permet à tous les nouveaux types d'événements d'utiliser le lien d'application que vous avez défini.",
|
||||
|
||||
@@ -110,6 +110,7 @@
|
||||
"hidden_team_owner_message": "נדרש חשבון Pro כדי להשתמש בתכונות הצוותים. תהיה מוסתר עד שתבצע שידרוג.",
|
||||
"link_expires": "נ.ב. תוקף הקישור יפוג תוך {{expiresIn}} שעות.",
|
||||
"upgrade_to_per_seat": "שדרג למינוי לפי מקום",
|
||||
"seat_options_doesnt_support_confirmation": "אפשרויות המושבים אינם תומכים בדרישת האישור",
|
||||
"team_upgrade_seats_details": "לא התבצע תשלום עבור {{unpaidCount}} מקומות מתוך {{memberCount}} חברי הצוות שלך. תמורת ${{seatPrice}} לחודש למקום, עלות המינוי הכוללת המשוערת שלך היא ${{totalCost}} לחודש.",
|
||||
"team_upgrade_banner_description": "אנחנו מודים לך על כך שניסית את החבילה החדשה שלנו לצוותים. שמנו לב שהצוות שלך, \"{{teamName}}\", זקוק לשדרוג.",
|
||||
"team_upgrade_banner_action": "כאן משדרגים",
|
||||
@@ -477,8 +478,8 @@
|
||||
"booking_confirmation": "אשר את ה{{eventTypeTitle}} עם {{profileName}}",
|
||||
"booking_reschedule_confirmation": "שנה את המועד של ה{{eventTypeTitle}} עם {{profileName}}",
|
||||
"in_person_meeting": "פגישה אישית",
|
||||
"attendeeInPerson": "פנים-אל-פנים (בכתובת של המשתתף)",
|
||||
"inPerson": "פנים-אל-פנים (בכתובת של המארגן)",
|
||||
"attendee_in_person": "פנים-אל-פנים (הכתובת של המשתתף/ת)",
|
||||
"in_person": "פנים-אל-פנים (הכתובת של המארגן/ת)",
|
||||
"link_meeting": "פגישה עם קישור",
|
||||
"phone_call": "מספר הטלפון של המשתתף/ת",
|
||||
"your_number": "מספר הטלפון שלך",
|
||||
|
||||
@@ -477,8 +477,8 @@
|
||||
"booking_confirmation": "Conferma il tuo {{eventTypeTitle}} con {{profileName}}",
|
||||
"booking_reschedule_confirmation": "Riprogramma il tuo {{eventTypeTitle}} con {{profileName}}",
|
||||
"in_person_meeting": "Link o riunione di persona",
|
||||
"attendeeInPerson": "Di persona (indirizzo del partecipante)",
|
||||
"inPerson": "Di persona (indirizzo dell'organizzatore)",
|
||||
"attendee_in_person": "Di persona (indirizzo del partecipante)",
|
||||
"in_person": "Di persona (indirizzo dell'organizzatore)",
|
||||
"link_meeting": "Collegamento riunione",
|
||||
"phone_call": "Numero di telefono del partecipante",
|
||||
"your_number": "Il tuo numero di telefono",
|
||||
|
||||
@@ -477,8 +477,8 @@
|
||||
"booking_confirmation": "{{profileName}} の{{eventTypeTitle}} を確認",
|
||||
"booking_reschedule_confirmation": "{{profileName}} の {{eventTypeTitle}} をスケジュール変更する",
|
||||
"in_person_meeting": "リンクまたは対面ミーティング",
|
||||
"attendeeInPerson": "対面(出席者のアドレス)",
|
||||
"inPerson": "対面(主催者のアドレス)",
|
||||
"attendee_in_person": "対面(出席者のアドレス)",
|
||||
"in_person": "対面(主催者のアドレス)",
|
||||
"link_meeting": "ミーティングをリンク",
|
||||
"phone_call": "出席者の電話番号",
|
||||
"your_number": "あなたの電話番号",
|
||||
|
||||
@@ -477,8 +477,8 @@
|
||||
"booking_confirmation": "{{profileName}}로 {{eventTypeTitle}} 확인",
|
||||
"booking_reschedule_confirmation": "{{profileName}}을 사용하여 {{eventTypeTitle}} 일정을 변경하세요.",
|
||||
"in_person_meeting": "온라인 또는 오프라인 회의",
|
||||
"attendeeInPerson": "직접 방문(참석자 주소)",
|
||||
"inPerson": "방문(주최자 주소)",
|
||||
"attendee_in_person": "직접 방문(참석자 주소)",
|
||||
"in_person": "방문(주최자 주소)",
|
||||
"link_meeting": "회의 링크",
|
||||
"phone_call": "참석자 전화 번호",
|
||||
"your_number": "본인 전화 번호",
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"upgrade_now": "Nu upgraden",
|
||||
"accept_invitation": "Uitnodiging accepteren",
|
||||
"calcom_explained": "{{appName}} is het open source Calendly-alternatief waarmee u uw eigen gegevens, werkstroom en uiterlijk in de hand houdt.",
|
||||
"calcom_explained_new_user": "Voltooi het instellen van uw {{appName}}-account! U bent slechts enkele stappen verwijderd van het oplossen van al uw planningsproblemen.",
|
||||
"have_any_questions": "Heeft u vragen? We zijn er om te helpen.",
|
||||
"reset_password_subject": "{{appName}}: Instructies voor het opnieuw instellen van uw wachtwoord",
|
||||
"event_declined_subject": "Afgewezen: {{title}}",
|
||||
@@ -23,6 +24,8 @@
|
||||
"rejection_reason_description": "Weet u zeker dat u de boeking wilt weigeren? We informeren de persoon die probeerde te boeken. U kunt hieronder een reden opgeven.",
|
||||
"rejection_confirmation": "Boeking weigeren",
|
||||
"manage_this_event": "Deze gebeurtenis beheren",
|
||||
"invite_team_member": "Teamlid uitnodigen",
|
||||
"invite_team_notifcation_badge": "Uitgenodigd",
|
||||
"your_event_has_been_scheduled": "Uw gebeurtenis is gepland",
|
||||
"your_event_has_been_scheduled_recurring": "Uw terugkerende gebeurtenis is gepland",
|
||||
"accept_our_license": "Accepteer onze licentie door de variable .env <1>NEXT_PUBLIC_LICENSE_CONSENT</1> te veranderen in '{{agree}}'.",
|
||||
@@ -410,6 +413,8 @@
|
||||
"password_updated_successfully": "Wachtwoord met succes bijgewerkt",
|
||||
"password_has_been_changed": "Uw wachtwoord is met succes gewijzigd.",
|
||||
"error_changing_password": "Er ging iets mis tijdens het wijzigen van uw wachtwoord",
|
||||
"session_timeout_changed": "Je sessieconfiguratie is bijgewerkt.",
|
||||
"session_timeout_change_error": "Fout bij het bijwerken van de sessieconfiguratie",
|
||||
"something_went_wrong": "Er ging iets fout.",
|
||||
"something_doesnt_look_right": "Iets ziet er niet correct uit?",
|
||||
"please_try_again": "Probeer het nogmaals.",
|
||||
@@ -428,6 +433,7 @@
|
||||
"password_hint_num": "Minimaal 1 cijfer bevatten",
|
||||
"invalid_password_hint": "Het wachtwoord moet minimaal {{passwordLength}} tekens lang zijn, minimaal 1 cijfer bevatten en bestaan uit een mix van hoofd- en kleine letters",
|
||||
"incorrect_password": "Uw wachtwoord is incorrect.",
|
||||
"incorrect_username_password": "Gebruikersnaam of wachtwoord is onjuist.",
|
||||
"24_h": "24u",
|
||||
"use_setting": "Instelling gebruiken",
|
||||
"am_pm": "am/pm",
|
||||
@@ -455,6 +461,7 @@
|
||||
"slots_load_fail": "De beschikbare tijdsperiodes konden niet worden geladen.",
|
||||
"additional_guests": "Gasten toevoegen",
|
||||
"your_name": "Uw naam",
|
||||
"your_full_name": "Uw volledige naam",
|
||||
"email_address": "E-mail adres",
|
||||
"enter_valid_email": "Voer een geldig e-mailadres in",
|
||||
"location": "Locatie",
|
||||
@@ -470,8 +477,8 @@
|
||||
"booking_confirmation": "Bevestig uw {{eventTypeTitle}} met {{profileName}}",
|
||||
"booking_reschedule_confirmation": "Opnieuw plannen van uw {{eventTypeTitle}} met {{profileName}}",
|
||||
"in_person_meeting": "Online of persoonlijk afspreken",
|
||||
"attendeeInPerson": "Persoonlijk (adres deelnemer)",
|
||||
"inPerson": "Persoonlijk (adres organisator)",
|
||||
"attendee_in_person": "Persoonlijk (adres deelnemer)",
|
||||
"in_person": "Persoonlijk (adres organisator)",
|
||||
"link_meeting": "Vergadering koppelen",
|
||||
"phone_call": "Telefoonnummer deelnemer",
|
||||
"your_number": "Uw telefoonnummer",
|
||||
@@ -508,6 +515,8 @@
|
||||
"admin": "Beheerder",
|
||||
"administrator_user": "Beheerdersgebruiker",
|
||||
"lets_create_first_administrator_user": "Laten we de eerste beheerdersgebruiker aanmaken.",
|
||||
"admin_user_created": "Beheerdersgebruikerconfiguratie",
|
||||
"admin_user_created_description": "U heeft al een beheerdersgebruiker gemaakt. U kunt nu inloggen op uw account.",
|
||||
"new_member": "Nieuw Lid",
|
||||
"invite": "Uitnodigen",
|
||||
"add_team_members": "Teamleden toevoegen",
|
||||
@@ -657,6 +666,7 @@
|
||||
"edit_availability": "Beschikbaarheid bewerken",
|
||||
"configure_availability": "Configureer tijden wanneer u beschikbaar bent voor afspraken.",
|
||||
"copy_times_to": "Tijden kopiëren naar",
|
||||
"copy_times_to_tooltip": "Tijden kopiëren naar …",
|
||||
"change_weekly_schedule": "Verander uw weekschema",
|
||||
"logo": "Logo",
|
||||
"error": "Foutmelding",
|
||||
@@ -668,6 +678,7 @@
|
||||
"add_attendees": "Deelnemers toevoegen",
|
||||
"show_advanced_settings": "Toon geavanceerde instellingen",
|
||||
"event_name": "Naam van evenement",
|
||||
"event_name_in_calendar": "Gebeurtenisnaam in agenda",
|
||||
"event_name_tooltip": "De naam die in kalenders wordt weergegeven",
|
||||
"meeting_with_user": "Afspraak met {{attendeeName}}",
|
||||
"additional_inputs": "Extra invoer",
|
||||
@@ -786,6 +797,7 @@
|
||||
"number_apps_one": "{{count}} app",
|
||||
"number_apps_other": "{{count}} apps",
|
||||
"trending_apps": "Trending apps",
|
||||
"most_popular": "Meest populair",
|
||||
"explore_apps": "{{category}}-apps",
|
||||
"installed_apps": "Geinstalleerde apps",
|
||||
"free_to_use_apps": "Gratis",
|
||||
@@ -796,12 +808,14 @@
|
||||
"no_category_apps_description_analytics": "Voeg een analyse-app toe aan uw boekingspagina's",
|
||||
"no_category_apps_description_automation": "Voeg een automatiseringsapp toe om te gebruiken",
|
||||
"no_category_apps_description_other": "Voeg een ander type app toe om allerlei soorten dingen te doen",
|
||||
"no_category_apps_description_web3": "Voeg een web3-app toe aan uw boekingspagina's",
|
||||
"installed_app_calendar_description": "Stel de agenda('s) in om te controleren op conflicten om dubbele boekingen te voorkomen.",
|
||||
"installed_app_conferencing_description": "Voeg uw favoriete apps voor videoconferenties toe voor uw vergaderingen",
|
||||
"installed_app_payment_description": "Configureer welke betalingsverwerkingsdiensten u wilt gebruiken bij het factureren aan uw klanten.",
|
||||
"installed_app_analytics_description": "Configureer welke analyse-apps moeten worden gebruikt voor uw boekingspagina's",
|
||||
"installed_app_other_description": "Alle geïnstalleerde apps uit andere categorieën.",
|
||||
"installed_app_automation_description": "Configureer welke automatiseringsapps moeten worden gebruikt",
|
||||
"installed_app_web3_description": "Configureer welke web3-apps moeten worden gebruikt voor uw boekingspagina's",
|
||||
"analytics": "Analyse",
|
||||
"empty_installed_apps_headline": "Geen apps geïnstalleerd",
|
||||
"empty_installed_apps_description": "Met apps kunt u uw workflow en uw planning aanzienlijk verbeteren.",
|
||||
@@ -929,6 +943,11 @@
|
||||
"current_location": "Huidige locatie",
|
||||
"user_phone": "Uw telefoonnummer",
|
||||
"new_location": "Nieuwe locatie",
|
||||
"session": "Sessie",
|
||||
"session_description": "Beheer uw accountsessie",
|
||||
"session_timeout_after": "Time-out sessie na",
|
||||
"session_timeout": "Sessietime-out",
|
||||
"session_timeout_description": "Maak uw sessie ongeldig na een bepaalde tijd.",
|
||||
"no_location": "Geen locatie bepaald",
|
||||
"set_location": "Locatie instellen",
|
||||
"update_location": "Locatie bijwerken",
|
||||
@@ -1072,6 +1091,7 @@
|
||||
"broken_video_action": "We konden de vergaderlink voor <1>{{location}}</1> niet aan uw geplande evenement toevoegen. Neem contact op met uw genodigden of werk uw agenda-evenement bij om de details toe te voegen. U kunt <3>uw locatie op het eventementtype wijzigen</3> of proberen <5>de app opnieuw toe te voegen.</5>",
|
||||
"broken_calendar_action": "We konden uw <1>{{calendar}}</1> niet bijwerken. <2>Controleer uw agenda-instellingen of verwijder uw agenda en voeg uw agenda opnieuw toe </2>",
|
||||
"attendee_name": "Naam deelnemer",
|
||||
"scheduler_full_name": "De volledige naam van de persoon die boekt",
|
||||
"broken_integration": "Beschadigde integratie",
|
||||
"problem_adding_video_link": "Er was een probleem met het toevoegen van een videolink",
|
||||
"problem_updating_calendar": "Er was een probleem met het bijwerken van uw agenda",
|
||||
@@ -1214,6 +1234,7 @@
|
||||
"connect_automation_apps": "Koppel automatiseringsapps",
|
||||
"connect_analytics_apps": "Koppel analyse-apps",
|
||||
"connect_other_apps": "Andere apps koppelen",
|
||||
"connect_web3_apps": "Web3-apps koppelen",
|
||||
"current_step_of_total": "Stap {{currentStep}} van {{maxSteps}}",
|
||||
"add_variable": "Variabele toevoegen",
|
||||
"custom_phone_number": "Aangepast telefoonnummer",
|
||||
@@ -1230,6 +1251,7 @@
|
||||
"to": "Aan",
|
||||
"workflow_turned_on_successfully": "De werkstroom {{workflowName}} is {{offOn}}",
|
||||
"download_responses": "Reacties downloaden",
|
||||
"download_responses_description": "Download alle reacties op uw formulier in CSV-indeling.",
|
||||
"download": "Downloaden",
|
||||
"create_your_first_form": "Maak uw eerste formulier",
|
||||
"create_your_first_form_description": "Met routeringsformulieren kunt u kwalificerende vragen stellen en doorverwijzen naar de juiste persoon of het juiste type gebeurtenis.",
|
||||
@@ -1271,6 +1293,8 @@
|
||||
"routing_forms_send_email_owner": "E-mail naar eigenaar versturen",
|
||||
"routing_forms_send_email_owner_description": "Verstuurt een e-mail naar de eigenaar wanneer het formulier is verzonden",
|
||||
"add_new_form": "Nieuw formulier toevoegen",
|
||||
"create_your_first_route": "Maak uw eerste route",
|
||||
"route_to_the_right_person": "Route naar de juiste persoon op basis van de antwoorden op uw formulier",
|
||||
"form_description": "Maak uw formulier om naar een boeker door te verwijzen",
|
||||
"copy_link_to_form": "Link kopiëren naar formulier",
|
||||
"theme": "Thema",
|
||||
@@ -1301,6 +1325,7 @@
|
||||
"password_reset_leading": "Als u niet spoedig een e-mail ontvangt, controleer dan of het ingevoerde e-mailadres correct is, controleer uw spamfolder of neem contact op met de ondersteuning als het probleem zich blijft voordoen.",
|
||||
"password_updated": "Wachtwoord bijgewerkt!",
|
||||
"pending_payment": "In afwachting van betaling",
|
||||
"pending_invites": "Openstaande uitnodigingen",
|
||||
"confirmation_page_rainbow": "Scherm uw gebeurtenis af met tokens of NFT's op Ethereum, Polygon en meer.",
|
||||
"not_on_cal": "Niet op {{appName}}",
|
||||
"no_calendar_installed": "Geen agenda geïnstalleerd",
|
||||
@@ -1427,6 +1452,9 @@
|
||||
"disabled_calendar": "Als u een andere agenda heeft geïnstalleerd, worden nieuwe boekingen daaraan toegevoegd. Zo niet, koppel dan een nieuwe agenda zodat u geen nieuwe boekingen mist.",
|
||||
"enable_apps": "Apps inschakelen",
|
||||
"enable_apps_description": "Schakel apps in die gebruikers kunnen integreren met Cal.com",
|
||||
"purchase_license": "Koop een licentie",
|
||||
"already_have_key": "Ik heb al een sleutel:",
|
||||
"already_have_key_suggestion": "Kopieer hier uw bestaande CALCOM_LICENSE_KEY-omgevingsvariabele.",
|
||||
"app_is_enabled": "{{appName}} is ingeschakeld",
|
||||
"app_is_disabled": "{{appName}} is uitgeschakeld",
|
||||
"keys_have_been_saved": "Sleutels zijn opgeslagen",
|
||||
@@ -1447,6 +1475,7 @@
|
||||
"individual": "Individueel",
|
||||
"all_bookings_filter_label": "Alle boekingen",
|
||||
"all_users_filter_label": "Alle gebruikers",
|
||||
"your_bookings_filter_label": "Uw boekingen",
|
||||
"meeting_url_variable": "Vergaderings-URL",
|
||||
"meeting_url_info": "De vergaderingsconferentie-url van de gebeurtenis",
|
||||
"date_overrides": "Datumoverschrijvingen",
|
||||
@@ -1485,6 +1514,7 @@
|
||||
"round_robin_hosts": "Round-robin-hosts",
|
||||
"minimum_round_robin_hosts_count": "Aantal vereiste hosts voor deelname",
|
||||
"hosts": "Hosts",
|
||||
"upgrade_to_enable_feature": "U moet een team maken om deze functie in te schakelen. Klik om een team te maken.",
|
||||
"new_attendee": "Nieuwe deelnemer",
|
||||
"awaiting_approval": "In afwachting van goedkeuring",
|
||||
"requires_google_calendar": "Deze app vereist een Google Agenda-koppeling",
|
||||
@@ -1493,9 +1523,99 @@
|
||||
"continue_to_install_google_calendar": "Ga door met het installeren van Google Agenda",
|
||||
"install_google_meet": "Google Meet installeren",
|
||||
"install_google_calendar": "Google Agenda installeren",
|
||||
"sender_name": "Naam afzender",
|
||||
"already_invited": "Deelnemer reeds uitgenodigd",
|
||||
"no_recordings_found": "Geen opnames gevonden",
|
||||
"reporting": "Rapportage",
|
||||
"reporting_feature": "Bekijk alle inkomende gegevens en download het als een CSV",
|
||||
"teams_plan_required": "Teamsabonnement vereist",
|
||||
"routing_forms_are_a_great_way": "Routingformulieren zijn een geweldige manier om uw inkomende leads naar de juiste persoon te leiden. Upgrade naar een teamsabonnement om toegang te krijgen tot deze functie.",
|
||||
"choose_a_license": "Kies een licentie",
|
||||
"choose_license_description": "Cal.com wordt geleverd met een toegankelijke en gratis AGPLv3-licentie met enkele beperkingen die op elk moment kan worden geüpgraded naar een bedrijfslicentie. U kunt later altijd upgraden.",
|
||||
"license": "Licentie",
|
||||
"agplv3_license": "AGPLv3-licentie",
|
||||
"ee_enterprise_license": "\"gratis\" bedrijfslicentie",
|
||||
"enterprise_booking_fee": "Vanaf {{enterprise_booking_fee}}/maand",
|
||||
"enterprise_license_includes": "Alles voor een commerciële toepassing",
|
||||
"no_need_to_keep_your_code_open_source": "Uw code hoeft niet open source te zijn",
|
||||
"repackage_rebrand_resell": "Gemakkelijk opnieuw verpakken, rebranden en doorverkopen",
|
||||
"a_vast_suite_of_enterprise_features": "Een uitgebreid pakket bedrijfsfuncties",
|
||||
"free_license_fee": "$ 0.00/maand",
|
||||
"forever_open_and_free": "Voor altijd open en gratis",
|
||||
"required_to_keep_your_code_open_source": "Vereist dagt uw code open source is",
|
||||
"cannot_repackage_and_resell": "Kan niet gemakkelijk opnieuw verpakken, rebranden en doorverkopen",
|
||||
"no_enterprise_features": "Geen bedrijfsfuncties",
|
||||
"step_enterprise_license": "Bedrijfslicentie",
|
||||
"step_enterprise_license_description": "Alles voor commerciële toepassing met privéhosting, opnieuw verpakken, rebranden en doorverkopen en toegang tot exclusieve bedrijfscomponenten.",
|
||||
"setup": "Configuratie",
|
||||
"setup_description": "Cal.com-exemplaar configureren",
|
||||
"configure": "Configureren",
|
||||
"sso_configuration": "Eenmalige aanmelding",
|
||||
"sso_configuration_description": "SAML/OIDC SSO configureren en teamleden laten inloggen met behulp van een identiteitsprovider",
|
||||
"sso_oidc_heading": "SSO met OIDC",
|
||||
"sso_oidc_description": "Configureer OIDC SSO met de identiteitsprovider van uw keuze.",
|
||||
"sso_oidc_configuration_title": "OIDC-configuratie",
|
||||
"sso_oidc_configuration_description": "Configureer de OIDC-verbinding met uw identiteitsprovider. U kunt de vereiste informatie vinden bij uw identiteitsprovider.",
|
||||
"sso_oidc_callback_copied": "URL voor terugbellen gekopieerd",
|
||||
"sso_saml_heading": "SSO met SAML",
|
||||
"sso_saml_description": "Configureer SAML SSO met de identiteitsprovider van uw keuze.",
|
||||
"sso_saml_configuration_title": "SAML-configuratie",
|
||||
"sso_saml_configuration_description": "Configureer de SAML-verbinding met uw identiteitsprovider. U kunt de vereiste informatie vinden bij uw identiteitsprovider.",
|
||||
"sso_saml_acsurl_copied": "ACS-URL gekopieerd",
|
||||
"sso_saml_entityid_copied": "Entiteits-ID gekopieerd",
|
||||
"sso_connection_created_successfully": "{{connectionType}}-configuratie gemaakt",
|
||||
"sso_connection_deleted_successfully": "{{connectionType}}-configuratie verwijderd",
|
||||
"delete_sso_configuration": "{{connectionType}}-configuratie verwijderen",
|
||||
"delete_sso_configuration_confirmation": "Ja, verwijder de {{connectionType}}-configuratie",
|
||||
"delete_sso_configuration_confirmation_description": "Weet u zeker dat u de {{connectionType}}-configuratie wilt verwijderen? Uw teamleden die {{connectionType}}-aanmelding gebruiken hebben niet langer toegang tot Cal.com.",
|
||||
"organizer_timezone": "Organisator tijdzone",
|
||||
"email_no_user_cta": "Uw account aanmaken",
|
||||
"email_user_cta": "Uitnodiging weergeven",
|
||||
"email_no_user_invite_heading": "U bent uitgenodigd om lid te worden van een team op {{appName}}",
|
||||
"email_no_user_invite_subheading": "{{invitedBy}} heeft u uitgenodigd om lid te worden van zijn team op {{appName}}. {{appName}} is de gebeurtenissenplanner die u en uw team in staat stelt vergaderingen te plannen zonder heen en weer te e-mailen.",
|
||||
"email_no_user_invite_steps_intro": "We doorlopen samen een paar korte stappen en in een mum van tijd kunt u genieten van een stressvrije planning met uw team.",
|
||||
"email_no_user_step_one": "Kies uw gebruikersnaam",
|
||||
"email_no_user_step_two": "Koppel uw agenda-account",
|
||||
"email_no_user_step_three": "Stel uw beschikbaarheid in",
|
||||
"email_no_user_step_four": "Neem deel aan {{teamName}}",
|
||||
"email_no_user_signoff": "Veel plezier met het plannen van het {{appName}}-team",
|
||||
"impersonation_user_tip": "U staat op het punt zich voor te doen als een gebruiker, wat betekent dat u namens hem wijzigingen kunt aanbrengen. Wees voorzichtig.",
|
||||
"available_variables": "Beschikbare variabelen",
|
||||
"scheduler": "{Scheduler}",
|
||||
"recommended_next_steps": "Aanbevolen volgende stappen",
|
||||
"create_a_managed_event": "Maak een beheerd gebeurtenistype",
|
||||
"meetings_are_better_with_the_right": "Vergaderingen zijn beter met de juiste teamleden erbij. Nodig ze nu uit.",
|
||||
"collective_or_roundrobin": "Collectief of round-robin",
|
||||
"book_your_team_members": "Boek uw teamleden samen met collectieve gebeurtenissen of blader voor de juiste persoon met round-robin.",
|
||||
"default_app_link_title": "Stel een standaard app-link in",
|
||||
"default_app_link_description": "Door een standaard app-link in te stellen kunnen alle nieuw gemaakte gebeurtenistypes de door u ingestelde app-link gebruiken.",
|
||||
"change_default_conferencing_app": "Als standaard instellen",
|
||||
"booking_confirmation_failed": "Boekingsbevestiging mislukt"
|
||||
"under_maintenance": "Onbereikbaar wegens onderhoud",
|
||||
"under_maintenance_description": "Het {{appName}}-team voert gepland onderhoud uit. Neem contact op met de ondersteuning als u vragen heeft.",
|
||||
"event_type_seats": "{{numberOfSeats}} plaatsen",
|
||||
"booking_with_payment_cancelled": "Betalen voor deze gebeurtenis is niet meer mogelijk",
|
||||
"booking_with_payment_cancelled_already_paid": "Een terugbetaling voor deze boeking is onderweg.",
|
||||
"booking_with_payment_cancelled_refunded": "Deze boekingsbetaling is terugbetaald.",
|
||||
"booking_confirmation_failed": "Boekingsbevestiging mislukt",
|
||||
"get_started_zapier_templates": "Aan de slag met Zapier-sjablonen",
|
||||
"a_routing_form": "Een routeringsformulier",
|
||||
"form_description_placeholder": "Formulierbeschrijving",
|
||||
"keep_me_connected_with_form": "Houd me verbonden met het formulier",
|
||||
"fields_in_form_duplicated": "Alle wijzigingen in router en velden van het formulier dat wordt gedupliceerd, worden in het duplicaat verwerkt.",
|
||||
"form_deleted": "Formulier verwijderd",
|
||||
"delete_form": "Formulier verwijderen",
|
||||
"delete_form_action": "Ja, verwijder het formulier",
|
||||
"delete_form_confirmation": "Weet u zeker dat u dit formulier wilt verwijderen? Iedereen met wie u de link heeft gedeeld kan dan niet meer boeken. Ook worden alle bijbehorende reacties verwijderd.",
|
||||
"typeform_redirect_url_copied": "Typeform-omleidings-URL gekopieerd! U kunt de URL instellen in het Typeform-formulier.",
|
||||
"modifications_in_fields_warning": "Wijzigingen in velden en routes van de volgende formulieren worden in dit formulier verwerkt.",
|
||||
"connected_forms": "Verbonden formulieren",
|
||||
"form_modifications_warning": "De volgende formulieren worden beïnvloed wanneer u hier velden of routes wijzigt.",
|
||||
"responses_collection_waiting_description": "Wacht enige tijd tot de reacties zijn verzameld. U kunt het formulier ook zelf indienen.",
|
||||
"this_is_what_your_users_would_see": "Dit is wat uw gebruikers te zien krijgen",
|
||||
"identifies_name_field": "Identificeert het veld met deze naam.",
|
||||
"add_1_option_per_line": "Voeg 1 optie per regel toe",
|
||||
"select_a_router": "Selecteer een router",
|
||||
"add_a_new_route": "Voeg een nieuwe route toe",
|
||||
"no_responses_yet": "Nog geen reacties",
|
||||
"this_will_be_the_placeholder": "Dit wordt de plaatshouder"
|
||||
}
|
||||
|
||||
@@ -470,8 +470,8 @@
|
||||
"booking_confirmation": "Bekreft {{eventTypeTitle}} med {{profileName}}",
|
||||
"booking_reschedule_confirmation": "Endre tidspunkt for {{eventTypeTitle}} med {{profileName}}",
|
||||
"in_person_meeting": "Personlig møte",
|
||||
"attendeeInPerson": "Personlig Oppmøte (Deltakers Adresse)",
|
||||
"inPerson": "Personlig Oppmøte (Arrangørens Adresse)",
|
||||
"attendee_in_person": "Personlig Oppmøte (Deltakers Adresse)",
|
||||
"in_person": "Personlig Oppmøte (Arrangørens Adresse)",
|
||||
"link_meeting": "Møte lenke",
|
||||
"phone_call": "Deltakers Telefonnummer",
|
||||
"your_number": "Ditt telefonnummer",
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"upgrade_now": "Ulepsz teraz",
|
||||
"accept_invitation": "Akceptuj zaproszenie",
|
||||
"calcom_explained": "{{appName}} zapewnia infrastrukturę planowania dla absolutnie wszystkich.",
|
||||
"calcom_explained_new_user": "Dokończ konfigurację konta w aplikacji {{appName}}! Od rozwiązania wszystkich Twoich problemów z układaniem grafików dzieli Cię tylko kilka kroków.",
|
||||
"have_any_questions": "Masz pytania? Jesteśmy tutaj, aby pomóc.",
|
||||
"reset_password_subject": "{{appName}}: Instrukcje resetowania hasła",
|
||||
"event_declined_subject": "Odrzucono: {{title}} w dniu {{date}}",
|
||||
@@ -23,6 +24,8 @@
|
||||
"rejection_reason_description": "Czy jesteś pewien, że chcesz odrzucić prośbę o rezerwację? Damy znać osobie, która próbowała jej dokonać. Poniżej możesz podać powód.",
|
||||
"rejection_confirmation": "Odrzuć prośbę o rezerwację",
|
||||
"manage_this_event": "Zarządzaj wydarzeniem",
|
||||
"invite_team_member": "Zaproś członka zespołu",
|
||||
"invite_team_notifcation_badge": "Zapr.",
|
||||
"your_event_has_been_scheduled": "Zaplanowano wydarzenie",
|
||||
"your_event_has_been_scheduled_recurring": "Twoje wydarzenie cykliczne zostało zaplanowane",
|
||||
"accept_our_license": "Zaakceptuj naszą licencję, zmieniając zmienną .env <1>NEXT_PUBLIC_LICENSE_CONSENT</1> na '{{agree}}'.",
|
||||
@@ -410,6 +413,8 @@
|
||||
"password_updated_successfully": "Hasło zaktualizowane pomyślnie",
|
||||
"password_has_been_changed": "Twoje hasło zostało pomyślnie zmienione.",
|
||||
"error_changing_password": "Błąd zmiany hasła",
|
||||
"session_timeout_changed": "Twoja konfiguracja sesji została pomyślnie zaktualizowana.",
|
||||
"session_timeout_change_error": "Podczas aktualizacji konfiguracji sesji wystąpił błąd.",
|
||||
"something_went_wrong": "Coś się zepsuło.",
|
||||
"something_doesnt_look_right": "Coś nie wygląda poprawnie?",
|
||||
"please_try_again": "Proszę spróbuj ponownie.",
|
||||
@@ -428,6 +433,7 @@
|
||||
"password_hint_num": "Zawrzyj co najmniej 1 cyfrę",
|
||||
"invalid_password_hint": "Hasło musi składać się z co najmniej {{passwordLength}} znaków, zawierać co najmniej jedną cyfrę oraz kombinację wielkich i małych liter",
|
||||
"incorrect_password": "Hasło jest nieprawidłowe.",
|
||||
"incorrect_username_password": "Nazwa użytkownika lub hasło są nieprawidłowe.",
|
||||
"24_h": "24 godz.",
|
||||
"use_setting": "Użyj ustawień",
|
||||
"am_pm": "rano/po południu",
|
||||
@@ -455,6 +461,7 @@
|
||||
"slots_load_fail": "Nie można załadować dostępnych przedziałów czasu.",
|
||||
"additional_guests": "Dodaj gości",
|
||||
"your_name": "Twoje imię",
|
||||
"your_full_name": "Twoje imię i nazwisko",
|
||||
"email_address": "Adres e-mail",
|
||||
"enter_valid_email": "Wprowadź prawidłowy adres e-mail",
|
||||
"location": "Lokalizacja",
|
||||
@@ -470,8 +477,8 @@
|
||||
"booking_confirmation": "Potwierdź {{eventTypeTitle}} z {{profileName}}",
|
||||
"booking_reschedule_confirmation": "Przełóż Twój {{eventTypeTitle}} z {{profileName}}",
|
||||
"in_person_meeting": "Link lub spotkanie osób",
|
||||
"attendeeInPerson": "Osobiście (adres uczestnika)",
|
||||
"inPerson": "Osobiście (adres organizatora)",
|
||||
"attendee_in_person": "Osobiście (adres uczestnika)",
|
||||
"in_person": "Osobiście (adres organizatora)",
|
||||
"link_meeting": "Link do spotkania",
|
||||
"phone_call": "Numer telefonu uczestnika",
|
||||
"your_number": "Twój numer telefonu",
|
||||
@@ -508,6 +515,8 @@
|
||||
"admin": "Administrator",
|
||||
"administrator_user": "Użytkownik-administrator",
|
||||
"lets_create_first_administrator_user": "Utwórzmy pierwszego użytkownika-administratora.",
|
||||
"admin_user_created": "Konfiguracja użytkownika administratora",
|
||||
"admin_user_created_description": "Utworzono już użytkownika administratora. Możesz teraz zalogować się na swoim koncie.",
|
||||
"new_member": "Nowy Członek",
|
||||
"invite": "Zaproś",
|
||||
"add_team_members": "Dodaj członków zespołu",
|
||||
@@ -657,6 +666,7 @@
|
||||
"edit_availability": "Edytuj dostępność",
|
||||
"configure_availability": "Skonfiguruj czasy, kiedy jesteś dostępny dla rezerwacji.",
|
||||
"copy_times_to": "Kopiuj czasy do",
|
||||
"copy_times_to_tooltip": "Kopiuj czasy do…",
|
||||
"change_weekly_schedule": "Zmień swój tygodniowy harmonogram",
|
||||
"logo": "Logo",
|
||||
"error": "Błąd",
|
||||
@@ -668,6 +678,7 @@
|
||||
"add_attendees": "Dodaj uczestników",
|
||||
"show_advanced_settings": "Pokaż ustawienia zaawansowane",
|
||||
"event_name": "Nazwa wydarzenia",
|
||||
"event_name_in_calendar": "Nazwa wydarzenia w kalendarzu",
|
||||
"event_name_tooltip": "Nazwa, która pojawi się w kalendarzach",
|
||||
"meeting_with_user": "Spotkanie z {{attendeeName}}",
|
||||
"additional_inputs": "Dodatkowe Wejścia",
|
||||
@@ -786,6 +797,7 @@
|
||||
"number_apps_one": "Liczba aplikacji: {{count}}",
|
||||
"number_apps_other": "Liczba aplikacji: {{count}}",
|
||||
"trending_apps": "Popularne aplikacje",
|
||||
"most_popular": "Najpopularniejsze",
|
||||
"explore_apps": "Aplikacje z kategorii {{category}}",
|
||||
"installed_apps": "Zainstalowane aplikacje",
|
||||
"free_to_use_apps": "Darmowe",
|
||||
@@ -796,12 +808,14 @@
|
||||
"no_category_apps_description_analytics": "Dodaj aplikację analityczną do stron rezerwacji",
|
||||
"no_category_apps_description_automation": "Dodaj aplikację automatyzującą, która ma być używana",
|
||||
"no_category_apps_description_other": "Dodaj dowolny typ aplikacji, aby uzyskać dostęp do różnych innych funkcji",
|
||||
"no_category_apps_description_web3": "Dodaj aplikację web3 do stron rezerwacji",
|
||||
"installed_app_calendar_description": "Ustaw kalendarze, aby wykrywać konflikty i unikać podwójnych rezerwacji.",
|
||||
"installed_app_conferencing_description": "Dodaj ulubione aplikacje do wideokonferencji, aby umożliwić korzystanie z nich podczas spotkań",
|
||||
"installed_app_payment_description": "Skonfiguruj usługi przetwarzania płatności, których chcesz używać do pobierania opłat od klientów.",
|
||||
"installed_app_analytics_description": "Skonfiguruj, które aplikacje analityczne mają być używane na stronach rezerwacji",
|
||||
"installed_app_other_description": "Wszystkie zainstalowane aplikacje z innych kategorii.",
|
||||
"installed_app_automation_description": "Skonfiguruj, które aplikacje automatyzujące mają być używane",
|
||||
"installed_app_web3_description": "Skonfiguruj, które aplikacje web3 mają być używane na stronach rezerwacji.",
|
||||
"analytics": "Analityka",
|
||||
"empty_installed_apps_headline": "Brak zainstalowanych aplikacji",
|
||||
"empty_installed_apps_description": "Aplikacje umożliwiają znaczne usprawnienie przebiegu pracy i uproszczenie planowania.",
|
||||
@@ -929,6 +943,11 @@
|
||||
"current_location": "Bieżąca lokalizacja",
|
||||
"user_phone": "Twój numer telefonu",
|
||||
"new_location": "Nowa lokalizacja",
|
||||
"session": "Sesja",
|
||||
"session_description": "Kontroluj sesję konta",
|
||||
"session_timeout_after": "Sesja wygasa po upływie",
|
||||
"session_timeout": "Limit czasu sesji",
|
||||
"session_timeout_description": "Unieważnij sesję po określonym czasie.",
|
||||
"no_location": "Nie określono lokalizacji",
|
||||
"set_location": "Określ lokalizację",
|
||||
"update_location": "Zaktualizuj lokalizację",
|
||||
@@ -1072,6 +1091,7 @@
|
||||
"broken_video_action": "Do zaplanowanego wydarzenia nie można dodać linku do spotkania <1>{{location}}</1>. Skontaktuj się z zaproszonymi osobami lub zaktualizuj wydarzenie w kalendarzu, aby dodać szczegóły. Możesz albo <3>zmienić lokalizację w typie wydarzenia</3>, albo spróbować <5>usunąć aplikację i ponownie ją dodać</5>.",
|
||||
"broken_calendar_action": "Nie udało nam się zaktualizować Twojego kalendarza <1>{{calendar}}</1>. <2> Sprawdź ustawienia kalendarza lub usuń swój kalendarz i dodaj go ponownie </2>",
|
||||
"attendee_name": "Nazwa uczestnika",
|
||||
"scheduler_full_name": "Imię i nazwisko osoby rezerwującej",
|
||||
"broken_integration": "Uszkodzona integracja",
|
||||
"problem_adding_video_link": "Podczas dodawania linku do wideo wystąpił problem",
|
||||
"problem_updating_calendar": "Podczas aktualizowania kalendarza wystąpił problem",
|
||||
@@ -1214,6 +1234,7 @@
|
||||
"connect_automation_apps": "Połącz aplikacje automatyzujące",
|
||||
"connect_analytics_apps": "Połącz aplikacje analityczne",
|
||||
"connect_other_apps": "Połącz inne aplikacje",
|
||||
"connect_web3_apps": "Połącz aplikacje web3",
|
||||
"current_step_of_total": "Krok {{currentStep}} z {{maxSteps}}",
|
||||
"add_variable": "Dodaj zmienną",
|
||||
"custom_phone_number": "Niestandardowy numer telefonu",
|
||||
@@ -1230,6 +1251,7 @@
|
||||
"to": "Do",
|
||||
"workflow_turned_on_successfully": "Przepływ pracy {{workflowName}} został {{offOn}}",
|
||||
"download_responses": "Pobierz odpowiedzi",
|
||||
"download_responses_description": "Pobierz wszystkie odpowiedzi na formularz w formacie CSV.",
|
||||
"download": "Pobierz",
|
||||
"create_your_first_form": "Utwórz pierwszy formularz",
|
||||
"create_your_first_form_description": "Za pomocą formularzy przekierowujących możesz zadawać pytania profilujące i przekierowywać użytkowników do odpowiednich osób lub typów wydarzeń.",
|
||||
@@ -1271,6 +1293,8 @@
|
||||
"routing_forms_send_email_owner": "Wyślij wiadomość e-mail do właściciela",
|
||||
"routing_forms_send_email_owner_description": "Wysyła wiadomość e-mail do właściciela, gdy formularz zostanie przesłany.",
|
||||
"add_new_form": "Dodaj nowy formularz",
|
||||
"create_your_first_route": "Utwórz pierwsze przekierowanie",
|
||||
"route_to_the_right_person": "Przekierowanie do właściwej osoby na podstawie odpowiedzi na Twój formularz",
|
||||
"form_description": "Utwórz formularz, aby przekierowywać osoby rezerwujące",
|
||||
"copy_link_to_form": "Skopiuj link do formularza",
|
||||
"theme": "Motyw",
|
||||
@@ -1301,6 +1325,7 @@
|
||||
"password_reset_leading": "Jeśli wkrótce nie otrzymasz wiadomości e-mail, sprawdź, czy wprowadzony adres e-mail jest poprawny, sprawdź folder ze spamem lub skontaktuj się z pomocą, jeśli problem będzie się powtarzał.",
|
||||
"password_updated": "Hasło zostało zaktualizowane!",
|
||||
"pending_payment": "Płatność w toku",
|
||||
"pending_invites": "Oczekujące zaproszenia",
|
||||
"confirmation_page_rainbow": "Udostępnij Twoje wydarzenie tylko posiadaczom tokenów lub NFT w blockchainach Ethereum, Polygon i innych.",
|
||||
"not_on_cal": "Niedostępne na {{appName}}",
|
||||
"no_calendar_installed": "Brak zainstalowanego kalendarza",
|
||||
@@ -1427,6 +1452,9 @@
|
||||
"disabled_calendar": "Jeśli masz zainstalowany inny kalendarz, nowe rezerwacje zostaną dodane do niego. Jeśli nie, podłącz nowy kalendarz, aby nie przegapić żadnych nowych rezerwacji.",
|
||||
"enable_apps": "Włącz aplikacje",
|
||||
"enable_apps_description": "Włącz aplikacje, które użytkownicy mogą zintegrować z usługą Cal.com",
|
||||
"purchase_license": "Kup licencję",
|
||||
"already_have_key": "Mam już klucz:",
|
||||
"already_have_key_suggestion": "Skopiuj istniejącą zmienną środowiskową CALCOM_LICENSE_KEY tutaj.",
|
||||
"app_is_enabled": "Aplikacja {{appName}} jest włączona",
|
||||
"app_is_disabled": "Aplikacja {{appName}} jest wyłączona",
|
||||
"keys_have_been_saved": "Klucze zostały zapisane",
|
||||
@@ -1447,6 +1475,7 @@
|
||||
"individual": "Pojedyncza osoba",
|
||||
"all_bookings_filter_label": "Wszystkie rezerwacje",
|
||||
"all_users_filter_label": "Wszyscy użytkownicy",
|
||||
"your_bookings_filter_label": "Twoje rezerwacje",
|
||||
"meeting_url_variable": "Adres URL spotkania",
|
||||
"meeting_url_info": "Adres URL konferencji na spotkaniu w ramach wydarzenia",
|
||||
"date_overrides": "Zastąpione daty",
|
||||
@@ -1485,6 +1514,7 @@
|
||||
"round_robin_hosts": "Gospodarze przypisywani algorytmem karuzelowym",
|
||||
"minimum_round_robin_hosts_count": "Liczba gospodarzy, których uczestnictwo jest wymagane",
|
||||
"hosts": "Gospodarze",
|
||||
"upgrade_to_enable_feature": "Musisz utworzyć zespół, aby włączyć tę funkcję. Kliknij, aby utworzyć zespół.",
|
||||
"new_attendee": "Nowy uczestnik",
|
||||
"awaiting_approval": "Oczekiwanie na zatwierdzenie",
|
||||
"requires_google_calendar": "Ta aplikacja wymaga połączenia z Kalendarzem Google",
|
||||
@@ -1493,9 +1523,58 @@
|
||||
"continue_to_install_google_calendar": "Kontynuuj instalację Kalendarza Google",
|
||||
"install_google_meet": "Zainstaluj Google Meet",
|
||||
"install_google_calendar": "Zainstaluj Kalendarz Google",
|
||||
"sender_name": "Nazwa nadawcy",
|
||||
"already_invited": "Uczestnik został już zaproszony.",
|
||||
"no_recordings_found": "Nie znaleziono nagrań",
|
||||
"reporting": "Raportowanie",
|
||||
"reporting_feature": "Zobacz wszystkie elementy przychodzące z danych i pobierz je w formacie CSV",
|
||||
"teams_plan_required": "Wymagany plan dla zespołów",
|
||||
"routing_forms_are_a_great_way": "Formularze przekierowania są świetnym sposobem na przekierowanie Twoich przychodzących leadów do właściwej osoby. Przejdź na plan dla zespołów, aby uzyskać dostęp do tej funkcji.",
|
||||
"choose_a_license": "Wybierz licencję",
|
||||
"choose_license_description": "Wraz z Cal.com zyskujesz przystępną i bezpłatną licencję AGPLv3 z pewnymi ograniczeniami, która może zostać ulepszona do licencji Enterprise w dowolnym momencie. Możesz wykupić licencję wyższego poziomu w każdej chwili.",
|
||||
"license": "Licencja",
|
||||
"agplv3_license": "Licencja AGPLv3",
|
||||
"enterprise_booking_fee": "Od {{enterprise_booking_fee}}/miesięcznie",
|
||||
"enterprise_license_includes": "Wszystko co niezbędne do zastosowań komercyjnych",
|
||||
"no_need_to_keep_your_code_open_source": "Twój kod nie musi pozostać na licencji typu open-source.",
|
||||
"repackage_rebrand_resell": "Łatwa modyfikacja wyglądu, marki i odsprzedaży",
|
||||
"a_vast_suite_of_enterprise_features": "Duży wybór funkcji dla przedsiębiorstw",
|
||||
"free_license_fee": "0,00 USD/miesiąc",
|
||||
"forever_open_and_free": "Zawsze za darmo i w otwartym dostępie",
|
||||
"required_to_keep_your_code_open_source": "Twój kod musi pozostać na licencji typu open-source.",
|
||||
"cannot_repackage_and_resell": "Nie da się łatwo zmodyfikować wyglądu, zmienić marki i odsprzedać.",
|
||||
"no_enterprise_features": "Brak funkcji dla przedsiębiorstw",
|
||||
"step_enterprise_license": "Licencja dla przedsiębiorstw",
|
||||
"setup": "Konfiguracja",
|
||||
"setup_description": "Skonfiguruj wystąpienie Cal.com",
|
||||
"configure": "Konfiguruj",
|
||||
"sso_configuration": "Pojedyncze logowanie",
|
||||
"email_no_user_cta": "Załóż swoje konto",
|
||||
"create_a_managed_event": "Utwórz typ zarządzanego wydarzenia",
|
||||
"meetings_are_better_with_the_right": "Spotkania idą lepiej, gdy uczestniczą w nich właściwi członkowie zespołu. Zaproś ich teraz.",
|
||||
"collective_or_roundrobin": "Kolektywnie czy według algorytmu karuzelowego",
|
||||
"book_your_team_members": "Zarezerwuj wszystkich członków zespołu za pomocą wydarzeń kolektywnych lub przeglądaj dostępne osoby, aby znaleźć tę właściwą za pomocą algorytmu karuzelowego.",
|
||||
"default_app_link_title": "Ustaw domyślny link do aplikacji",
|
||||
"default_app_link_description": "Ustawienie domyślnego linku do aplikacji pozwala wszystkim nowo utworzonym rodzajom wydarzeń na używanie ustawionego linku do aplikacji.",
|
||||
"change_default_conferencing_app": "Ustaw jako domyślne",
|
||||
"booking_confirmation_failed": "Potwierdzenie rezerwacji nie powiodło się"
|
||||
"under_maintenance": "Przerwa konserwacyjna",
|
||||
"under_maintenance_description": "Zespół {{appName}} przeprowadza zaplanowane prace konserwacyjne. Jeśli masz jakieś pytania, skontaktuj się z pomocą techniczną.",
|
||||
"event_type_seats": "Liczba miejsc: {{numberOfSeats}}",
|
||||
"booking_confirmation_failed": "Potwierdzenie rezerwacji nie powiodło się",
|
||||
"a_routing_form": "Formularz przekierowania",
|
||||
"form_description_placeholder": "Opis formularza",
|
||||
"keep_me_connected_with_form": "Zachowaj połączenie z formularzem",
|
||||
"fields_in_form_duplicated": "Duplikowanie zmian w przekierowaniu i polach formularza zostaną odzwierciedlone w duplikacie.",
|
||||
"form_deleted": "Formularz usunięty",
|
||||
"delete_form": "Usuń formularz",
|
||||
"delete_form_action": "Tak, usuń formularz",
|
||||
"delete_form_confirmation": "Czy na pewno chcesz usunąć ten formularz? Osoby, którym udostępniono link, nie będą już mogły użyć go do rezerwacji. Ponadto wszystkie powiązane odpowiedzi zostaną usunięte.",
|
||||
"typeform_redirect_url_copied": "Skopiowano adres URL przekierowania typu Typeform! Możesz teraz skonfigurować adres URL w formacie Typeform.",
|
||||
"modifications_in_fields_warning": "Zmiany w polach i przekierowaniach następujących formularzy zostaną odzwierciedlone w tym formularzu.",
|
||||
"connected_forms": "Połączone formularze",
|
||||
"form_modifications_warning": "Zmiany w polach i przekierowaniach tutaj będą miały wpływ na następujące formularze.",
|
||||
"responses_collection_waiting_description": "Poczekaj na zebranie odpowiedzi. Możesz też przesłać formularz osobiście.",
|
||||
"this_is_what_your_users_would_see": "To zobaczą Twoi użytkownicy.",
|
||||
"identifies_name_field": "Identyfikuje pole za pomocą tej nazwy.",
|
||||
"this_will_be_the_placeholder": "To będzie symbol zastępczy"
|
||||
}
|
||||
|
||||
@@ -470,8 +470,8 @@
|
||||
"booking_confirmation": "Confirme seu {{eventTypeTitle}} com {{profileName}}",
|
||||
"booking_reschedule_confirmation": "Reagende seu {{eventTypeTitle}} com {{profileName}}",
|
||||
"in_person_meeting": "Reunião presencial",
|
||||
"attendeeInPerson": "Pessoalmente (endereço do participante)",
|
||||
"inPerson": "Pessoalmente (endereço do organizador)",
|
||||
"attendee_in_person": "Pessoalmente (endereço do participante)",
|
||||
"in_person": "Pessoalmente (endereço do organizador)",
|
||||
"link_meeting": "Vincular reunião",
|
||||
"phone_call": "Número de telefone do participante",
|
||||
"your_number": "Seu número de telefone",
|
||||
|
||||
@@ -477,8 +477,8 @@
|
||||
"booking_confirmation": "Confirme o seu {{eventTypeTitle}} com {{profileName}}",
|
||||
"booking_reschedule_confirmation": "Reagende o seu {{eventTypeTitle}} com {{profileName}}",
|
||||
"in_person_meeting": "Ligação ou reunião presencial",
|
||||
"attendeeInPerson": "Pessoalmente (endereço do participante)",
|
||||
"inPerson": "Pessoalmente (endereço do organizador)",
|
||||
"attendee_in_person": "Pessoalmente (endereço do participante)",
|
||||
"in_person": "Pessoalmente (endereço do organizador)",
|
||||
"link_meeting": "Ligar reunião",
|
||||
"phone_call": "Número de telefone do participante",
|
||||
"your_number": "O seu número de telefone",
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"upgrade_now": "Faceți upgrade acum",
|
||||
"accept_invitation": "Acceptați invitația",
|
||||
"calcom_explained": "{{appName}} oferă infrastructura de programare pentru absolut toată lumea.",
|
||||
"calcom_explained_new_user": "Finalizați configurarea contului {{appName}}! Mai aveți doar câțiva pași până la soluționarea tuturor problemelor legate de programare.",
|
||||
"have_any_questions": "Aveți întrebări? Suntem aici pentru a vă ajuta.",
|
||||
"reset_password_subject": "{{appName}}: instrucțiuni de resetare a parolei",
|
||||
"event_declined_subject": "Refuzat: {{title}} în {{date}}",
|
||||
@@ -23,6 +24,8 @@
|
||||
"rejection_reason_description": "Sigur doriți să respingeți rezervarea? Vom anunța persoana care a încercat să rezerve. Puteți specifica un motiv mai jos.",
|
||||
"rejection_confirmation": "Respingeți rezervarea",
|
||||
"manage_this_event": "Gestionați acest eveniment",
|
||||
"invite_team_member": "Invitați un membru al echipei",
|
||||
"invite_team_notifcation_badge": "Inv.",
|
||||
"your_event_has_been_scheduled": "Evenimentul a fost programat",
|
||||
"your_event_has_been_scheduled_recurring": "Evenimentul dvs. recurent a fost programat",
|
||||
"accept_our_license": "Acceptați licența noastră schimbând variabila .env <1>URMĂTOAREA_LICENȚĂ_PUBLICĂ</1> în.",
|
||||
@@ -410,6 +413,8 @@
|
||||
"password_updated_successfully": "Parola actualizată cu succes",
|
||||
"password_has_been_changed": "Parola dvs. a fost modificată cu succes.",
|
||||
"error_changing_password": "Eroare la schimbarea parolei",
|
||||
"session_timeout_changed": "Configurația sesiunii dvs. a fost actualizată cu succes.",
|
||||
"session_timeout_change_error": "Eroare la actualizarea configurației sesiunii",
|
||||
"something_went_wrong": "A apărut o problemă.",
|
||||
"something_doesnt_look_right": "Ceva nu pare a fi corect?",
|
||||
"please_try_again": "Te rugăm să încerci din nou.",
|
||||
@@ -428,6 +433,7 @@
|
||||
"password_hint_num": "Conține cel puțin 1 cifră",
|
||||
"invalid_password_hint": "Parola trebuie să aibă cel puțin {{passwordLength}} caractere, să conțină cel puțin o cifră și o combinație de litere mari și litere mici",
|
||||
"incorrect_password": "Parola este incorectă.",
|
||||
"incorrect_username_password": "Numele de utilizator sau parola este incorectă.",
|
||||
"24_h": "24h",
|
||||
"use_setting": "Folosește setarea",
|
||||
"am_pm": "am/pm",
|
||||
@@ -455,6 +461,7 @@
|
||||
"slots_load_fail": "Nu s-au putut încărca intervalele de timp disponibile.",
|
||||
"additional_guests": "Adăugați vizitatori",
|
||||
"your_name": "Numele tău",
|
||||
"your_full_name": "Numele dvs. complet",
|
||||
"email_address": "Adresa de e-mail",
|
||||
"enter_valid_email": "Introduceți un e-mail valid",
|
||||
"location": "Locaţie",
|
||||
@@ -470,8 +477,8 @@
|
||||
"booking_confirmation": "Confirmă {{eventTypeTitle}} cu {{profileName}}",
|
||||
"booking_reschedule_confirmation": "Reprogramează {{eventTypeTitle}} cu {{profileName}}",
|
||||
"in_person_meeting": "Link sau întâlnire în persoană",
|
||||
"attendeeInPerson": "În persoană (adresă participant)",
|
||||
"inPerson": "În persoană (adresă organizator)",
|
||||
"attendee_in_person": "În persoană (adresă participant)",
|
||||
"in_person": "În persoană (adresă organizator)",
|
||||
"link_meeting": "Link întâlnire",
|
||||
"phone_call": "Număr de telefon participant",
|
||||
"your_number": "Numărul dvs. de telefon",
|
||||
@@ -508,6 +515,8 @@
|
||||
"admin": "Admin",
|
||||
"administrator_user": "Utilizator administrator",
|
||||
"lets_create_first_administrator_user": "Haideți să creăm primul utilizator administrator.",
|
||||
"admin_user_created": "Configurare utilizator-administrator",
|
||||
"admin_user_created_description": "Ați creat deja un utilizator-administrator. Vă puteți conecta acum la contul dvs.",
|
||||
"new_member": "Membru Nou",
|
||||
"invite": "Invită",
|
||||
"add_team_members": "Adăugați membri în echipă",
|
||||
@@ -657,6 +666,7 @@
|
||||
"edit_availability": "Modificați disponibilitatea",
|
||||
"configure_availability": "Configurați orele când sunteți disponibil pentru rezervări.",
|
||||
"copy_times_to": "Copiați orele în",
|
||||
"copy_times_to_tooltip": "Copiați orele în…",
|
||||
"change_weekly_schedule": "Modificaţi schema săptămânală",
|
||||
"logo": "Logo",
|
||||
"error": "Eroare",
|
||||
@@ -668,6 +678,7 @@
|
||||
"add_attendees": "Adăugați participanți",
|
||||
"show_advanced_settings": "Afișează setările avansate",
|
||||
"event_name": "Denumirea evenimentului",
|
||||
"event_name_in_calendar": "Denumirea evenimentului în calendar",
|
||||
"event_name_tooltip": "Numele care va apărea în calendare",
|
||||
"meeting_with_user": "Întâlnire cu {{attendeeName}}",
|
||||
"additional_inputs": "Date suplimentare",
|
||||
@@ -786,6 +797,7 @@
|
||||
"number_apps_one": "{{count}} aplicație",
|
||||
"number_apps_other": "{{count}} (de) aplicații",
|
||||
"trending_apps": "Aplicații populare",
|
||||
"most_popular": "Cele mai populare",
|
||||
"explore_apps": "Aplicații {{category}}",
|
||||
"installed_apps": "Aplicații instalate",
|
||||
"free_to_use_apps": "Gratuit",
|
||||
@@ -796,12 +808,14 @@
|
||||
"no_category_apps_description_analytics": "Adăugați o aplicație de analiză pentru paginile dvs. de rezervări",
|
||||
"no_category_apps_description_automation": "Adăugați o aplicație de automatizare de utilizat",
|
||||
"no_category_apps_description_other": "Adăugați orice alt tip de aplicație pentru a întreprinde diverse acțiuni",
|
||||
"no_category_apps_description_web3": "Adăugați o aplicație Web3 pentru paginile dvs. de rezervări",
|
||||
"installed_app_calendar_description": "Pentru a evita rezervările suprapuse, configurează calendarele astfel încât să poată verifica existența conflictelor.",
|
||||
"installed_app_conferencing_description": "Adăugați aplicațiile preferate de conferințe video pentru ședințele dvs.",
|
||||
"installed_app_payment_description": "Configurați serviciile de procesare a plăților care vor fi utilizate la taxarea clienților.",
|
||||
"installed_app_analytics_description": "Configurați care aplicații de analiză vor fi utilizate pentru paginile dvs. de rezervări",
|
||||
"installed_app_other_description": "Toate aplicațiile instalate din alte categorii.",
|
||||
"installed_app_automation_description": "Configurați care aplicații de automatizare vor fi utilizate",
|
||||
"installed_app_web3_description": "Configurați care aplicații Web3 vor fi utilizate pentru paginile dvs. de rezervări",
|
||||
"analytics": "Analiză",
|
||||
"empty_installed_apps_headline": "Nicio aplicație instalată",
|
||||
"empty_installed_apps_description": "Aplicațiile vă permit să vă îmbunătățiți în mod semnificativ fluxul de lucru și activitățile legate de programări.",
|
||||
@@ -929,6 +943,11 @@
|
||||
"current_location": "Locația curentă",
|
||||
"user_phone": "Numărul dvs. de telefon",
|
||||
"new_location": "Locație nouă",
|
||||
"session": "Sesiune",
|
||||
"session_description": "Controlați sesiunea contului",
|
||||
"session_timeout_after": "Expirare sesiune după",
|
||||
"session_timeout": "Expirare sesiune",
|
||||
"session_timeout_description": "Invalidați sesiunea după o anumită perioadă.",
|
||||
"no_location": "Nicio locație definită",
|
||||
"set_location": "Stabiliți locația",
|
||||
"update_location": "Actualizați locația",
|
||||
@@ -1072,6 +1091,7 @@
|
||||
"broken_video_action": "Nu am reușit să adăugăm linkul pentru întâlnirea <1>{{location}}</1> la evenimentul programat. Contactați-vă invitații sau actualizați-vă evenimentul din calendar pentru a adăuga detalii. Puteți fie <3> să modificați locul pentru tipul de eveniment, </3> fie să încercați să <5>ștergeți și să adăugați din nou aplicația.</5>",
|
||||
"broken_calendar_action": "Nu am reușit să vă actualizăm <1>{{calendar}}</1>. <2> Verificați setările calendarului sau ștergeți-l și adăugați-l din nou </2>",
|
||||
"attendee_name": "Numele participantului",
|
||||
"scheduler_full_name": "Numele complet al persoanei care efectuează rezervarea",
|
||||
"broken_integration": "Integrare întreruptă",
|
||||
"problem_adding_video_link": "A intervenit o problemă la adăugarea linkului pentru videoclip",
|
||||
"problem_updating_calendar": "A intervenit o problemă la actualizarea calendarului dvs.",
|
||||
@@ -1214,6 +1234,7 @@
|
||||
"connect_automation_apps": "Conectați aplicații de automatizare",
|
||||
"connect_analytics_apps": "Conectați aplicații de analiză",
|
||||
"connect_other_apps": "Conectați alte aplicații",
|
||||
"connect_web3_apps": "Conectați aplicații Web3",
|
||||
"current_step_of_total": "Pasul {{currentStep}} din {{maxSteps}}",
|
||||
"add_variable": "Adăugare variabilă",
|
||||
"custom_phone_number": "Număr de telefon personalizat",
|
||||
@@ -1230,6 +1251,7 @@
|
||||
"to": "Către",
|
||||
"workflow_turned_on_successfully": "Fluxul de lucru {{workflowName}} a fost {{offOn}} cu succes",
|
||||
"download_responses": "Descărcați răspunsurile",
|
||||
"download_responses_description": "Descărcați în format CSV toate răspunsurile la formularul dvs.",
|
||||
"download": "Descarcă",
|
||||
"create_your_first_form": "Creați primul dvs. formular",
|
||||
"create_your_first_form_description": "Cu ajutorul formularelor de direcționare, puteți adresa întrebări de calificare și le puteți redirecționa persoanei sau tipului de eveniment potrivit.",
|
||||
@@ -1271,6 +1293,8 @@
|
||||
"routing_forms_send_email_owner": "Trimiteți un e-mail către proprietar",
|
||||
"routing_forms_send_email_owner_description": "Trimite un e-mail către proprietar atunci când este trimis formularul",
|
||||
"add_new_form": "Adăugați un formular nou",
|
||||
"create_your_first_route": "Creați-vă primul parcurs",
|
||||
"route_to_the_right_person": "Direcționați către persoana potrivită, pe baza răspunsurilor la formularul dvs.",
|
||||
"form_description": "Creați formularul pentru direcționarea unei persoane care face rezervare",
|
||||
"copy_link_to_form": "Copiați linkul în formular",
|
||||
"theme": "Temă",
|
||||
@@ -1301,6 +1325,7 @@
|
||||
"password_reset_leading": "Dacă nu primiți un e-mail în curând, verificați dacă adresa de e-mail pe care ați introdus-o este corectă, verificați folderul de mesaje nedorite sau contactați serviciul de asistență dacă problema persistă.",
|
||||
"password_updated": "Parolă actualizată!",
|
||||
"pending_payment": "Plată în așteptare",
|
||||
"pending_invites": "Invitații în așteptare",
|
||||
"confirmation_page_rainbow": "Restricționați accesul la evenimentul dvs. cu tokenuri sau NFT-uri pe Ethereum, Polygon și altele.",
|
||||
"not_on_cal": "Nu este pe {{appName}}",
|
||||
"no_calendar_installed": "Niciun calendar instalat",
|
||||
@@ -1427,6 +1452,9 @@
|
||||
"disabled_calendar": "Dacă ai un alt calendar instalat, rezervările noi vor fi adăugate la acesta. Dacă nu ai, conectează un calendar nou, astfel încât să nu ratezi nicio rezervare nouă.",
|
||||
"enable_apps": "Activează aplicații",
|
||||
"enable_apps_description": "Activează aplicațiile pe care utilizatorii le pot integra cu Cal.com",
|
||||
"purchase_license": "Achiziționați o licență",
|
||||
"already_have_key": "Am deja o cheie:",
|
||||
"already_have_key_suggestion": "Copiați aici variabila de mediu CALCOM_LICENSE_KEY existentă.",
|
||||
"app_is_enabled": "{{appName}} este activat",
|
||||
"app_is_disabled": "{{appName}} este dezactivat",
|
||||
"keys_have_been_saved": "Cheile au fost salvate",
|
||||
@@ -1447,6 +1475,7 @@
|
||||
"individual": "Persoană",
|
||||
"all_bookings_filter_label": "Toate rezervările",
|
||||
"all_users_filter_label": "Toți utilizatorii",
|
||||
"your_bookings_filter_label": "Rezervările dvs.",
|
||||
"meeting_url_variable": "URL ședință",
|
||||
"meeting_url_info": "Adresa URL a evenimentului ședință tip conferință",
|
||||
"date_overrides": "Suprascrieri dată",
|
||||
@@ -1485,6 +1514,7 @@
|
||||
"round_robin_hosts": "Gazde Round-Robin",
|
||||
"minimum_round_robin_hosts_count": "Numărul de gazde necesar pentru participare",
|
||||
"hosts": "Gazde",
|
||||
"upgrade_to_enable_feature": "Trebuie să creați o echipă pentru a activa această caracteristică. Faceți clic pentru a crea o echipă.",
|
||||
"new_attendee": "Participant nou",
|
||||
"awaiting_approval": "În așteptarea aprobării",
|
||||
"requires_google_calendar": "Această aplicație necesită o conexiune cu Google Calendar",
|
||||
@@ -1493,9 +1523,99 @@
|
||||
"continue_to_install_google_calendar": "Continuă cu instalarea Google Calendar",
|
||||
"install_google_meet": "Instalează Google Meet",
|
||||
"install_google_calendar": "Instalează Google Calendar",
|
||||
"sender_name": "Nume expeditor",
|
||||
"already_invited": "Participant deja invitat",
|
||||
"no_recordings_found": "Nu s-au găsit înregistrări",
|
||||
"reporting": "Raportare",
|
||||
"reporting_feature": "Vizualizați toate datele primite și descărcați-le în format CSV",
|
||||
"teams_plan_required": "Este necesar un plan pentru echipe",
|
||||
"routing_forms_are_a_great_way": "Formularele de parcurs reprezintă un mod excelent de a vă direcționa potențialii clienți către persoana potrivită. Pentru a putea accesa această caracteristică, treceți la un plan pentru echipe.",
|
||||
"choose_a_license": "Alegeți o licență",
|
||||
"choose_license_description": "Cal.com include o licență AGPLv3 accesibilă și gratuită, cu unele limitări, însă care poate fi actualizată la o licență Enterprise în orice moment. Puteți face upgrade oricând mai târziu.",
|
||||
"license": "Licență",
|
||||
"agplv3_license": "Licență AGPLv3",
|
||||
"ee_enterprise_license": "Licență Enterprise „/ee”",
|
||||
"enterprise_booking_fee": "Începând de la {{enterprise_booking_fee}}/lună",
|
||||
"enterprise_license_includes": "Totul pentru uz comercial",
|
||||
"no_need_to_keep_your_code_open_source": "Nu este nevoie să vă păstrați codul open-source",
|
||||
"repackage_rebrand_resell": "Restructurați și revindeți cu ușurință, sub o nouă marcă",
|
||||
"a_vast_suite_of_enterprise_features": "O gamă largă de caracteristici specifice întreprinderilor",
|
||||
"free_license_fee": "0,00 USD/lună",
|
||||
"forever_open_and_free": "Deschis și gratuit fără limită de timp",
|
||||
"required_to_keep_your_code_open_source": "Este necesar să vă păstrați codul open-source",
|
||||
"cannot_repackage_and_resell": "Nu se poate restructura și revinde cu ușurință, sub o nouă marcă",
|
||||
"no_enterprise_features": "Fără caracteristici specifice întreprinderilor",
|
||||
"step_enterprise_license": "Licență Enterprise",
|
||||
"step_enterprise_license_description": "Totul pentru uz comercial, cu găzduire privată, restructurare și revânzare sub o nouă marcă, precum și cu acces la componente destinate exclusiv întreprinderilor.",
|
||||
"setup": "Configurare",
|
||||
"setup_description": "Configurare eveniment Cal.com",
|
||||
"configure": "Configurare",
|
||||
"sso_configuration": "Single Sign-On",
|
||||
"sso_configuration_description": "Configurați SSO cu SAML/OIDC și permiteți membrilor echipei să se conecteze folosind un furnizor de identitate",
|
||||
"sso_oidc_heading": "SSO cu OIDC",
|
||||
"sso_oidc_description": "Configurați SSO cu OIDC, apelând la furnizorul de identitate dorit.",
|
||||
"sso_oidc_configuration_title": "Configurare OIDC",
|
||||
"sso_oidc_configuration_description": "Configurați conexiunea OIDC la furnizorul dvs. de identitate. Puteți găsi informațiile necesare la furnizorul dvs. de identitate.",
|
||||
"sso_oidc_callback_copied": "URL-ul pentru apelare inversă a fost copiat",
|
||||
"sso_saml_heading": "SSO cu SAML",
|
||||
"sso_saml_description": "Configurați SSO cu SAML, apelând la furnizorul de identitate dorit.",
|
||||
"sso_saml_configuration_title": "Configurare SAML",
|
||||
"sso_saml_configuration_description": "Configurați conexiunea SAML la furnizorul dvs. de identitate. Puteți găsi informațiile necesare la furnizorul dvs. de identitate.",
|
||||
"sso_saml_acsurl_copied": "URL-ul ACS a fost copiat",
|
||||
"sso_saml_entityid_copied": "ID-ul entității a fost copiat",
|
||||
"sso_connection_created_successfully": "Configurația {{connectionType}} a fost creată cu succes",
|
||||
"sso_connection_deleted_successfully": "Configurația {{connectionType}} a fost ștearsă cu succes",
|
||||
"delete_sso_configuration": "Ștergeți configurația {{connectionType}}",
|
||||
"delete_sso_configuration_confirmation": "Da, șterg configurația {{connectionType}}",
|
||||
"delete_sso_configuration_confirmation_description": "Sigur doriți să ștergeți configurația {{connectionType}}? Membrii echipei dvs. care utilizează conectarea prin {{connectionType}} nu vor mai putea accesa Cal.com.",
|
||||
"organizer_timezone": "Fusul orar al organizatorului",
|
||||
"email_no_user_cta": "Creează-ți contul",
|
||||
"email_user_cta": "Vizualizare invitație",
|
||||
"email_no_user_invite_heading": "Ați fost invitat să faceți parte dintr-o echipă de pe {{appName}}",
|
||||
"email_no_user_invite_subheading": "{{invitedBy}} v-a invitat să faceți parte din echipa sa de pe {{appName}}. {{appName}} este un instrument de planificare a evenimentelor care vă permite dvs. și echipei dvs. să programați ședințe fără a face ping-pong prin e-mail.",
|
||||
"email_no_user_invite_steps_intro": "Vom parcurge împreună câțiva pași simpli și vă veți bucura împreună cu echipa dvs. de planificări fără probleme, în cel mai scurt timp.",
|
||||
"email_no_user_step_one": "Alegeți-vă numele de utilizator",
|
||||
"email_no_user_step_two": "Conectați-vă contul de calendar",
|
||||
"email_no_user_step_three": "Setați-vă disponibilitatea",
|
||||
"email_no_user_step_four": "Faceți parte din {{teamName}}",
|
||||
"email_no_user_signoff": "Echipa {{appName}} vă dorește programări cu spor",
|
||||
"impersonation_user_tip": "Urmează să simulați identitatea unui utilizator, ceea ce înseamnă că puteți face modificări în numele său. Acționați cu atenție.",
|
||||
"available_variables": "Variabile disponibile",
|
||||
"scheduler": "{Scheduler}",
|
||||
"recommended_next_steps": "Următorii pași recomandați",
|
||||
"create_a_managed_event": "Creați un tip de eveniment gestionat",
|
||||
"meetings_are_better_with_the_right": "Ședințele sunt mai agreabile dacă participă membrii potriviți ai echipei. Invitați-i acum.",
|
||||
"collective_or_roundrobin": "Alocare colectivă sau prin rotație",
|
||||
"book_your_team_members": "Efectuați rezervări comune pentru membrii echipei. Alegeți evenimente colective sau creați un ciclu pentru a găsi persoana potrivită prin alocarea prin rotație.",
|
||||
"default_app_link_title": "Setați un link implicit pentru aplicații",
|
||||
"default_app_link_description": "Setarea unui link implicit pentru aplicații permite tuturor tipurilor de evenimente nou-create să utilizeze linkul pentru aplicații pe care l-ați setat.",
|
||||
"change_default_conferencing_app": "Setează ca implicit",
|
||||
"booking_confirmation_failed": "Confirmare rezervare nereușită"
|
||||
"under_maintenance": "Serviciu întrerupt pentru întreținere",
|
||||
"under_maintenance_description": "Echipa {{appName}} efectuează lucrări de întreținere programate. Dacă aveți întrebări, contactați serviciul de asistență.",
|
||||
"event_type_seats": "{{numberOfSeats}} (de) locuri",
|
||||
"booking_with_payment_cancelled": "Nu se mai poate plăti pentru acest eveniment",
|
||||
"booking_with_payment_cancelled_already_paid": "Există o rambursare în curs pentru plata acestei rezervări.",
|
||||
"booking_with_payment_cancelled_refunded": "Plata pentru această rezervare a fost rambursată.",
|
||||
"booking_confirmation_failed": "Confirmare rezervare nereușită",
|
||||
"get_started_zapier_templates": "Fă primii pași cu șabloanele Zapier",
|
||||
"a_routing_form": "Un formular de redirecționare",
|
||||
"form_description_placeholder": "Descriere formular",
|
||||
"keep_me_connected_with_form": "Vreau să primesc actualizări privind formularul",
|
||||
"fields_in_form_duplicated": "Orice modificări aduse parcursului și câmpurilor din formularul duplicat se vor reflecta în duplicat.",
|
||||
"form_deleted": "Formular șters",
|
||||
"delete_form": "Ștergere formular",
|
||||
"delete_form_action": "Da, ștergeți formularul",
|
||||
"delete_form_confirmation": "Sigur doriți să ștergeți acest formular? Nicio persoană căreia i-ați transmis linkul nu va mai putea efectua rezervări pe baza lui. În plus, toate răspunsurile asociate vor fi șterse.",
|
||||
"typeform_redirect_url_copied": "URL-ul de redirecționare Typeform a fost copiat! Puteți accesa și seta URL-ul în formularul Typeform.",
|
||||
"modifications_in_fields_warning": "Modificările aduse câmpurilor și parcursurilor pentru următoarele formulare vor fi reproduse în acest formular.",
|
||||
"connected_forms": "Formulare conectate",
|
||||
"form_modifications_warning": "Următoarele formulare vor fi afectate dacă modificați aici câmpuri sau parcursuri.",
|
||||
"responses_collection_waiting_description": "Așteptați puțin pentru ca răspunsurile să fie colectate. Puteți trimite și dvs. formularul.",
|
||||
"this_is_what_your_users_would_see": "Iată ce vor vedea utilizatorii dvs.",
|
||||
"identifies_name_field": "Depistează câmpul după această denumire.",
|
||||
"add_1_option_per_line": "Adăugați o opțiune pe linie",
|
||||
"select_a_router": "Selectați o rută",
|
||||
"add_a_new_route": "Adăugați o rută nouă",
|
||||
"no_responses_yet": "Nu există încă răspunsuri",
|
||||
"this_will_be_the_placeholder": "Acesta va fi substituentul"
|
||||
}
|
||||
|
||||
@@ -470,8 +470,8 @@
|
||||
"booking_confirmation": "Подтвердите вашу встречу «{{eventTypeTitle}}» с {{profileName}}",
|
||||
"booking_reschedule_confirmation": "Перенесите вашу встречу «{{eventTypeTitle}}» с {{profileName}}",
|
||||
"in_person_meeting": "Ссылка или личная встреча",
|
||||
"attendeeInPerson": "Лично (адрес участника)",
|
||||
"inPerson": "Лично (адрес организатора)",
|
||||
"attendee_in_person": "Лично (адрес участника)",
|
||||
"in_person": "Лично (адрес организатора)",
|
||||
"link_meeting": "Встреча со ссылкой",
|
||||
"phone_call": "Номер телефона участника",
|
||||
"your_number": "Ваш номер телефона",
|
||||
|
||||
@@ -477,8 +477,8 @@
|
||||
"booking_confirmation": "Potvrdite vaš {{eventTypeTitle}} sa {{profileName}}",
|
||||
"booking_reschedule_confirmation": "Odložite vaš {{eventTypeTitle}} sa {{profileName}}",
|
||||
"in_person_meeting": "Sastanak uživo ili preko online linka",
|
||||
"attendeeInPerson": "Lično (adresa polaznika)",
|
||||
"inPerson": "Lično (adresa organizatora)",
|
||||
"attendee_in_person": "Lično (adresa polaznika)",
|
||||
"in_person": "Lično (adresa organizatora)",
|
||||
"link_meeting": "Link za sastanak",
|
||||
"phone_call": "Broj telefona učesnika",
|
||||
"your_number": "Vaš broj telefona",
|
||||
|
||||
@@ -477,8 +477,8 @@
|
||||
"booking_confirmation": "Bekräfta {{eventTypeTitle}} med {{profileName}}",
|
||||
"booking_reschedule_confirmation": "Omboka {{eventTypeTitle}} med {{profileName}}",
|
||||
"in_person_meeting": "Länk eller fysiskt möte",
|
||||
"attendeeInPerson": "Personligen (deltagandeadress)",
|
||||
"inPerson": "Personligen (orgnanisatörsadress)",
|
||||
"attendee_in_person": "Personligen (deltagandeadress)",
|
||||
"in_person": "Personligen (orgnanisatörsadress)",
|
||||
"link_meeting": "Länka möte",
|
||||
"phone_call": "Deltagarens telefonnummer",
|
||||
"your_number": "Ditt telefonnummer",
|
||||
|
||||
@@ -477,8 +477,8 @@
|
||||
"booking_confirmation": "{{profileName}} ile {{eventTypeTitle}} etkinliğinizi onaylayın",
|
||||
"booking_reschedule_confirmation": "{{profileName}} ile {{eventTypeTitle}} etkinliğinizi yeniden planlayın",
|
||||
"in_person_meeting": "Yüz yüze görüşme",
|
||||
"attendeeInPerson": "Şahsen (Katılımcı Adresi)",
|
||||
"inPerson": "Şahsen (Organizatör Adresi)",
|
||||
"attendee_in_person": "Şahsen (Katılımcı Adresi)",
|
||||
"in_person": "Şahsen (Organizatör Adresi)",
|
||||
"link_meeting": "Bağlantılı toplantı",
|
||||
"phone_call": "Katılımcı Telefon Numarası",
|
||||
"your_number": "Telefon numaranız",
|
||||
@@ -1539,7 +1539,9 @@
|
||||
"enterprise_license_includes": "Ticari bir kullanım durumu için her şey",
|
||||
"no_need_to_keep_your_code_open_source": "Kodunuzu açık kaynak olarak tutmanıza gerek yok",
|
||||
"repackage_rebrand_resell": "Kolayca yeniden paketleyin, yeniden markalalayın ve yeniden satış yapın",
|
||||
"a_vast_suite_of_enterprise_features": "Kapsamlı kurumsal özellikler paketi",
|
||||
"free_license_fee": "0,00 $/ay",
|
||||
"forever_open_and_free": "Sonsuza Kadar Açık ve Ücretsiz",
|
||||
"required_to_keep_your_code_open_source": "Kodunuzu açık kaynak olarak tutmanıza gerekiyor",
|
||||
"cannot_repackage_and_resell": "Yeniden paketleme, yeniden markalama ve yeniden satış kolayca yapılamaz",
|
||||
"no_enterprise_features": "Kurumsal özellik yok",
|
||||
|
||||
@@ -477,8 +477,8 @@
|
||||
"booking_confirmation": "Підтвердьте свій захід ({{eventTypeTitle}}) із користувачем {{profileName}}",
|
||||
"booking_reschedule_confirmation": "Перенесіть свій захід ({{eventTypeTitle}}) із користувачем {{profileName}}",
|
||||
"in_person_meeting": "Посилання або особиста зустріч",
|
||||
"attendeeInPerson": "Особисто (адреса відвідувача)",
|
||||
"inPerson": "Особисто (адреса організатора)",
|
||||
"attendee_in_person": "Особисто (адреса відвідувача)",
|
||||
"in_person": "Особисто (адреса організатора)",
|
||||
"link_meeting": "Нарада з посиланням",
|
||||
"phone_call": "Номер телефону учасника",
|
||||
"your_number": "Ваш номер телефону",
|
||||
|
||||
@@ -477,8 +477,8 @@
|
||||
"booking_confirmation": "Xác nhận {{eventTypeTitle}} của bạn với {{profileName}}",
|
||||
"booking_reschedule_confirmation": "Lên lịch lại {{eventTypeTitle}} của bạn với {{profileName}}",
|
||||
"in_person_meeting": "Gặp mặt trực tiếp",
|
||||
"attendeeInPerson": "Đích thân (địa chỉ người tham gia)",
|
||||
"inPerson": "Đích thân (địa chỉ người tổ chức)",
|
||||
"attendee_in_person": "Đích thân (địa chỉ người tham gia)",
|
||||
"in_person": "Đích thân (địa chỉ người tổ chức)",
|
||||
"link_meeting": "Liên kết cuộc họp",
|
||||
"phone_call": "Số điện thoại của người tham gia",
|
||||
"your_number": "Số điện thoại của bạn",
|
||||
|
||||
@@ -477,8 +477,8 @@
|
||||
"booking_confirmation": "确认您和 {{profileName}} 的 {{eventTypeTitle}}",
|
||||
"booking_reschedule_confirmation": "重新安排您和 {{profileName}} 的 {{eventTypeTitle}}",
|
||||
"in_person_meeting": "线上或线下会议",
|
||||
"attendeeInPerson": "本人(参与者地址)",
|
||||
"inPerson": "本人(组织者地址)",
|
||||
"attendee_in_person": "本人(参与者地址)",
|
||||
"in_person": "本人(组织者地址)",
|
||||
"link_meeting": "线上会议",
|
||||
"phone_call": "参与者电话号码",
|
||||
"your_number": "您的电话号码",
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"upgrade_now": "立刻升級",
|
||||
"accept_invitation": "接受邀請",
|
||||
"calcom_explained": "{{appName}} 可為所有人提供預定基礎架構。",
|
||||
"calcom_explained_new_user": "完成設定您的 {{appName}} 帳號!再完成幾個步驟,就能解決您所有的預定問題。",
|
||||
"have_any_questions": "有問題嗎?我們隨時在此幫助。",
|
||||
"reset_password_subject": "{{appName}}: 重新設置密碼說明",
|
||||
"event_declined_subject": "已拒絕:{{date}} 與 {{title}}",
|
||||
@@ -23,6 +24,8 @@
|
||||
"rejection_reason_description": "確定要拒絕預約嗎?我們會讓想要進行預約的對方知道。可以在下方提供原因。",
|
||||
"rejection_confirmation": "拒絕預約",
|
||||
"manage_this_event": "管理活動",
|
||||
"invite_team_member": "邀請團隊成員",
|
||||
"invite_team_notifcation_badge": "邀請",
|
||||
"your_event_has_been_scheduled": "活動已預定時間",
|
||||
"your_event_has_been_scheduled_recurring": "您的定期活動已預定",
|
||||
"accept_our_license": "接受授權的方式是修改 .env 變數 <1>NEXT_PUBLIC_LICENSE_CONSENT</1> 為 '{{agree}}'。",
|
||||
@@ -410,6 +413,8 @@
|
||||
"password_updated_successfully": "成功更新密碼",
|
||||
"password_has_been_changed": "密碼已成功更新。",
|
||||
"error_changing_password": "更換密碼時發生錯誤",
|
||||
"session_timeout_changed": "您的工作階段設定已經成功更新。",
|
||||
"session_timeout_change_error": "更新工作階段設定時發生錯誤",
|
||||
"something_went_wrong": "有些不對勁。",
|
||||
"something_doesnt_look_right": "有看起來怪怪的東西嗎?",
|
||||
"please_try_again": "請再試一次。",
|
||||
@@ -428,6 +433,7 @@
|
||||
"password_hint_num": "至少包含 1 個數字",
|
||||
"invalid_password_hint": "密碼長度至少要有 {{passwordLength}} 個字元,其中包含至少一個數字和大小寫字母組合",
|
||||
"incorrect_password": "密碼不正確。",
|
||||
"incorrect_username_password": "使用者名稱或密碼不正確。",
|
||||
"24_h": "24 小時",
|
||||
"use_setting": "使用設定",
|
||||
"am_pm": "上午/下午",
|
||||
@@ -455,6 +461,7 @@
|
||||
"slots_load_fail": "無法讀取剩下的時間區間。",
|
||||
"additional_guests": "新增賓客",
|
||||
"your_name": "名字",
|
||||
"your_full_name": "您的全名",
|
||||
"email_address": "電子郵件位址",
|
||||
"enter_valid_email": "請輸入有效的電子郵件",
|
||||
"location": "地點",
|
||||
@@ -470,8 +477,8 @@
|
||||
"booking_confirmation": "向 {{profileName}} 確認{{eventTypeTitle}}。",
|
||||
"booking_reschedule_confirmation": "向 {{profileName}} 重新預定{{eventTypeTitle}}",
|
||||
"in_person_meeting": "實體會議",
|
||||
"attendeeInPerson": "親自赴會 (與會者地址)",
|
||||
"inPerson": "親自赴會 (主辦者地址)",
|
||||
"attendee_in_person": "親自赴會 (與會者地址)",
|
||||
"in_person": "親自赴會 (主辦者地址)",
|
||||
"link_meeting": "線上會議",
|
||||
"phone_call": "與會者電話",
|
||||
"your_number": "您的電話號碼",
|
||||
@@ -508,6 +515,8 @@
|
||||
"admin": "管理者",
|
||||
"administrator_user": "管理員使用者",
|
||||
"lets_create_first_administrator_user": "我們來建立第一個管理員使用者吧。",
|
||||
"admin_user_created": "管理員使用者設定",
|
||||
"admin_user_created_description": "您已建立管理員使用者。您現在可以登入您的帳號。",
|
||||
"new_member": "新成員",
|
||||
"invite": "邀請",
|
||||
"add_team_members": "新增團隊成員",
|
||||
@@ -657,6 +666,7 @@
|
||||
"edit_availability": "編輯可預定會議的時間",
|
||||
"configure_availability": "設定開放接受預約的時段。",
|
||||
"copy_times_to": "將時間複製到",
|
||||
"copy_times_to_tooltip": "將時間複製到…",
|
||||
"change_weekly_schedule": "更改每週行程",
|
||||
"logo": "標誌",
|
||||
"error": "錯誤",
|
||||
@@ -668,6 +678,7 @@
|
||||
"add_attendees": "加入與會者",
|
||||
"show_advanced_settings": "顯示進階設定",
|
||||
"event_name": "活動名稱",
|
||||
"event_name_in_calendar": "行事曆中的活動名稱",
|
||||
"event_name_tooltip": "會顯示在行事曆上的名字",
|
||||
"meeting_with_user": "與 {{attendeeName}} 的會議",
|
||||
"additional_inputs": "額外輸入欄",
|
||||
@@ -786,6 +797,7 @@
|
||||
"number_apps_one": "{{count}} 個應用程式",
|
||||
"number_apps_other": "{{count}} 個應用程式",
|
||||
"trending_apps": "熱門應用程式",
|
||||
"most_popular": "最熱門",
|
||||
"explore_apps": "{{category}}應用程式",
|
||||
"installed_apps": "已安裝的應用程式",
|
||||
"free_to_use_apps": "免費",
|
||||
@@ -796,12 +808,14 @@
|
||||
"no_category_apps_description_analytics": "為您的預約頁面加入分析應用程式",
|
||||
"no_category_apps_description_automation": "加入自動化應用程式來使用",
|
||||
"no_category_apps_description_other": "新增任何其他類型的應用程式以完成各種操作",
|
||||
"no_category_apps_description_web3": "為您的預約頁面加入 web3 應用程式",
|
||||
"installed_app_calendar_description": "設定行事曆來檢查衝突,以避免重複預約。",
|
||||
"installed_app_conferencing_description": "新增您愛用的視訊會議應用程式",
|
||||
"installed_app_payment_description": "設定向客戶收費時要使用的付款處理服務。",
|
||||
"installed_app_analytics_description": "設定要為您的預約頁面使用哪些分析應用程式",
|
||||
"installed_app_other_description": "其他類別的所有已安裝應用程式。",
|
||||
"installed_app_automation_description": "設定要使用哪些自動化應用程式",
|
||||
"installed_app_web3_description": "設定要為您的預約頁面使用哪些 web3 應用程式",
|
||||
"analytics": "分析",
|
||||
"empty_installed_apps_headline": "沒有已安裝的應用程式",
|
||||
"empty_installed_apps_description": "應用程式使您能夠增強您的工作流程並顯著改善您的日程安排。",
|
||||
@@ -929,6 +943,11 @@
|
||||
"current_location": "目前地點",
|
||||
"user_phone": "您的電話號碼",
|
||||
"new_location": "新地點",
|
||||
"session": "工作階段",
|
||||
"session_description": "控制您的帳號工作階段",
|
||||
"session_timeout_after": "逾時工作階段前置時間",
|
||||
"session_timeout": "工作階段逾時",
|
||||
"session_timeout_description": "在特定時間過後使工作階段無效。",
|
||||
"no_location": "定已義新的地點",
|
||||
"set_location": "設定地點",
|
||||
"update_location": "更新地點",
|
||||
@@ -1072,6 +1091,7 @@
|
||||
"broken_video_action": "我們無法將 <1>{{location}}</1> 會議連結新增至您已預定的活動。請聯絡您的受邀者或更新行事曆活動來新增詳細資料。您可以<3>變更活動類型的地點</3>,或試著<5>移除應用程式,然後再次重新安裝。</5>",
|
||||
"broken_calendar_action": "我們無法更新您的 <1>{{calendar}}</1>。<2>請檢查您的行事曆設定,或移除您的行事曆然後再次新增</2>",
|
||||
"attendee_name": "與會者姓名",
|
||||
"scheduler_full_name": "預約人全名",
|
||||
"broken_integration": "整合中斷",
|
||||
"problem_adding_video_link": "新增影片連結時發生問題",
|
||||
"problem_updating_calendar": "更新行事曆時發生問題",
|
||||
@@ -1214,6 +1234,7 @@
|
||||
"connect_automation_apps": "連至自動化應用程式",
|
||||
"connect_analytics_apps": "連至分析應用程式",
|
||||
"connect_other_apps": "連接其他應用程式",
|
||||
"connect_web3_apps": "連接 web3 應用程式",
|
||||
"current_step_of_total": "第 {{currentStep}} 步,共 {{maxSteps}} 步",
|
||||
"add_variable": "新增變數",
|
||||
"custom_phone_number": "自訂電話號碼",
|
||||
@@ -1230,6 +1251,7 @@
|
||||
"to": "至",
|
||||
"workflow_turned_on_successfully": "「{{workflowName}}」工作流程已成功{{offOn}}",
|
||||
"download_responses": "下載回應",
|
||||
"download_responses_description": "以 CSV 格式下載您表單的所有回應。",
|
||||
"download": "下載",
|
||||
"create_your_first_form": "建立您的第一份表單",
|
||||
"create_your_first_form_description": "您可使用引導表單提出符合條件的問題,並引導至適當的人員或活動類型。",
|
||||
@@ -1271,6 +1293,8 @@
|
||||
"routing_forms_send_email_owner": "傳送電子郵件給擁有者",
|
||||
"routing_forms_send_email_owner_description": "表單提交後傳送電子郵件給擁有者",
|
||||
"add_new_form": "新增新表單",
|
||||
"create_your_first_route": "建立第一份引導表單",
|
||||
"route_to_the_right_person": "根據表單回覆引導至合適的人員",
|
||||
"form_description": "建立您的表單來引導預約者",
|
||||
"copy_link_to_form": "複製連結至表單",
|
||||
"theme": "主題",
|
||||
@@ -1301,6 +1325,7 @@
|
||||
"password_reset_leading": "如果您稍後還是沒有收到電子郵件,請檢查您輸入的電子郵件地址是否正確,並查看您的垃圾郵件資料夾;若問題持續發生,請聯絡支援團隊。",
|
||||
"password_updated": "密碼已更新!",
|
||||
"pending_payment": "待付款",
|
||||
"pending_invites": "待回應的邀請",
|
||||
"confirmation_page_rainbow": "使用 Ethereum、Polygon 等的 Token 或 NFT 來以代幣管制您的活動。",
|
||||
"not_on_cal": "不在 {{appName}} 上",
|
||||
"no_calendar_installed": "未安裝行事曆",
|
||||
@@ -1427,6 +1452,9 @@
|
||||
"disabled_calendar": "如果您安裝了其他行事曆,新的預約就會新增到該行事曆中。如果沒有,請連至新行事曆,這樣才不會錯過任何新的預約。",
|
||||
"enable_apps": "啟用應用程式",
|
||||
"enable_apps_description": "啟用使用者可以與 Cal.com 整合的應用程式",
|
||||
"purchase_license": "購買授權",
|
||||
"already_have_key": "我已經有金鑰:",
|
||||
"already_have_key_suggestion": "請在這裡複製您目前的 CALCOM_LICENSE_KEY 環境變數。",
|
||||
"app_is_enabled": "已啟用 {{appName}}",
|
||||
"app_is_disabled": "已停用 {{appName}}",
|
||||
"keys_have_been_saved": "已儲存金鑰",
|
||||
@@ -1447,6 +1475,7 @@
|
||||
"individual": "個人",
|
||||
"all_bookings_filter_label": "所有預約",
|
||||
"all_users_filter_label": "所有使用者",
|
||||
"your_bookings_filter_label": "您的預約",
|
||||
"meeting_url_variable": "會議網址",
|
||||
"meeting_url_info": "活動會議網址",
|
||||
"date_overrides": "日期覆寫",
|
||||
@@ -1485,6 +1514,7 @@
|
||||
"round_robin_hosts": "輪流主辦人",
|
||||
"minimum_round_robin_hosts_count": "須參加的主辦人數",
|
||||
"hosts": "主辦人",
|
||||
"upgrade_to_enable_feature": "您需要建立團隊才能啟用此功能。按一下即可建立團隊。",
|
||||
"new_attendee": "新參與者",
|
||||
"awaiting_approval": "正在等待核准",
|
||||
"requires_google_calendar": "此應用程式需要 Google 日曆連結",
|
||||
@@ -1493,9 +1523,99 @@
|
||||
"continue_to_install_google_calendar": "繼續安裝 Google 日曆",
|
||||
"install_google_meet": "安裝 Google Meet",
|
||||
"install_google_calendar": "安裝 Google 日曆",
|
||||
"sender_name": "傳送者名稱",
|
||||
"already_invited": "與會者已獲邀",
|
||||
"no_recordings_found": "找不到錄製內容",
|
||||
"reporting": "報表",
|
||||
"reporting_feature": "查看所有傳入的資料,並以 CSV 檔案格式下載",
|
||||
"teams_plan_required": "需要團隊方案",
|
||||
"routing_forms_are_a_great_way": "引導表單可將到來的潛在客戶引導至合適的人員,是絕佳的處理方式。升級至團隊方案即可使用此功能。",
|
||||
"choose_a_license": "選擇授權",
|
||||
"choose_license_description": "Cal.com 隨附可供使用的免費 AGPLv3 授權,您可隨時將其中的部分限制升級至 Enterprise 授權。您之後隨時可以升級。",
|
||||
"license": "授權",
|
||||
"agplv3_license": "AGPLv3 授權",
|
||||
"ee_enterprise_license": "“/ee” Enterprise 授權",
|
||||
"enterprise_booking_fee": "每月 {{enterprise_booking_fee}} 起",
|
||||
"enterprise_license_includes": "商業使用案例的所有功能",
|
||||
"no_need_to_keep_your_code_open_source": "程式碼無須保持開源狀態",
|
||||
"repackage_rebrand_resell": "輕鬆重新包裝、換新品牌和轉售",
|
||||
"a_vast_suite_of_enterprise_features": "應有盡有的企業版功能套組",
|
||||
"free_license_fee": "$0.00/月",
|
||||
"forever_open_and_free": "永遠開放且免費",
|
||||
"required_to_keep_your_code_open_source": "程式碼須保持開源狀態",
|
||||
"cannot_repackage_and_resell": "無法輕鬆重新包裝、換新品牌和轉售",
|
||||
"no_enterprise_features": "沒有企業版功能",
|
||||
"step_enterprise_license": "Enterprise 授權",
|
||||
"step_enterprise_license_description": "商業使用案例的所有功能,隨附私人託管、重新包裝、換新品牌和轉售與專屬企業版元件存取權。",
|
||||
"setup": "設定",
|
||||
"setup_description": "設定 Cal.com 實例",
|
||||
"configure": "設定",
|
||||
"sso_configuration": "SAML 設定",
|
||||
"sso_configuration_description": "設定 SAML/OIDC SSO,並允許團隊成員使用 Identity Provider 登入",
|
||||
"sso_oidc_heading": "OIDC 型 SSO",
|
||||
"sso_oidc_description": "使用自選的 Identity Provider 設定 OIDC SSO。",
|
||||
"sso_oidc_configuration_title": "OIDC 設定",
|
||||
"sso_oidc_configuration_description": "設定 OIDC 連線至您的身分提供者。您可以在身分提供者中找到必要的資訊。",
|
||||
"sso_oidc_callback_copied": "已複製回呼網址",
|
||||
"sso_saml_heading": "SAML 型 SSO",
|
||||
"sso_saml_description": "使用自選的 Identity Provider 設定 SAML SSO。",
|
||||
"sso_saml_configuration_title": "SAML 設定",
|
||||
"sso_saml_configuration_description": "設定與您身分提供者的 SAML 連結。您可以在身分提供者中找到必要的資訊。",
|
||||
"sso_saml_acsurl_copied": "已複製 ACS 網址",
|
||||
"sso_saml_entityid_copied": "已複製實體 ID",
|
||||
"sso_connection_created_successfully": "已成功建立 {{connectionType}} 設定",
|
||||
"sso_connection_deleted_successfully": "已成功刪除 {{connectionType}} 設定",
|
||||
"delete_sso_configuration": "刪除 {{connectionType}} 設定",
|
||||
"delete_sso_configuration_confirmation": "是,刪除 {{connectionType}} 設定",
|
||||
"delete_sso_configuration_confirmation_description": "確定要刪除 {{connectionType}} 設定?使用 {{connectionType}} 登入的團隊成員將再也無法存取 Cal.com。",
|
||||
"organizer_timezone": "主辦者時區",
|
||||
"email_no_user_cta": "新增帳號",
|
||||
"email_user_cta": "檢視邀請",
|
||||
"email_no_user_invite_heading": "您已獲邀加入 {{appName}} 上的團隊",
|
||||
"email_no_user_invite_subheading": "{{invitedBy}} 已邀請您加入對方在 {{appName}} 上的團隊。{{appName}} 是活動多工排程工具,可讓您和您的團隊無須透過繁複的電子郵件往來就能輕鬆預定會議。",
|
||||
"email_no_user_invite_steps_intro": "我們會逐步引導您完成幾個簡短的步驟,接著您就能馬上與團隊享受沒有壓力的排程預定功能。",
|
||||
"email_no_user_step_one": "選擇使用者名稱",
|
||||
"email_no_user_step_two": "連結行事曆帳號",
|
||||
"email_no_user_step_three": "設定開放時間",
|
||||
"email_no_user_step_four": "加入 {{teamName}}",
|
||||
"email_no_user_signoff": "{{appName}} 團隊祝您排程愉快",
|
||||
"impersonation_user_tip": "您即將模擬某位使用者,這表示您可以代表對方進行變更。請謹慎操作。",
|
||||
"available_variables": "可用的變數",
|
||||
"scheduler": "{Scheduler}",
|
||||
"recommended_next_steps": "建議的後續步驟",
|
||||
"create_a_managed_event": "建立受管活動類型",
|
||||
"meetings_are_better_with_the_right": "找對團隊成員開會,開會更有效率。立即邀請他們。",
|
||||
"collective_or_roundrobin": "集體或輪流制",
|
||||
"book_your_team_members": "使用集體活動一併預約所有團隊成員,或是使用輪流制循環找出合適的人員。",
|
||||
"default_app_link_title": "設定預設應用程式連結",
|
||||
"default_app_link_description": "設定預設應用程式連結,即可讓所有全新建立的活動類型使用您設定的應用程式連結。",
|
||||
"change_default_conferencing_app": "設為預設",
|
||||
"booking_confirmation_failed": "預約確認失敗"
|
||||
"under_maintenance": "維修停機中",
|
||||
"under_maintenance_description": "{{appName}} 團隊正在執行預定維修。如有任何疑問,請聯絡支援團隊。",
|
||||
"event_type_seats": "{{numberOfSeats}} 個座位",
|
||||
"booking_with_payment_cancelled": "無法再為此活動付費",
|
||||
"booking_with_payment_cancelled_already_paid": "此預約付款的退款已在辦理中。",
|
||||
"booking_with_payment_cancelled_refunded": "此預約付款已退款。",
|
||||
"booking_confirmation_failed": "預約確認失敗",
|
||||
"get_started_zapier_templates": "開始使用 Zapier 範本",
|
||||
"a_routing_form": "引導表單",
|
||||
"form_description_placeholder": "表單說明",
|
||||
"keep_me_connected_with_form": "將我與此表單保持連結",
|
||||
"fields_in_form_duplicated": "目前複製的引導工具和表單欄位如有任何變更,也會反映在複本中。",
|
||||
"form_deleted": "已刪除表單",
|
||||
"delete_form": "刪除表單",
|
||||
"delete_form_action": "是,刪除表單",
|
||||
"delete_form_confirmation": "確定要刪除此表單嗎?您分享此連結的任何使用者,將無法再使用此表單預約。此外,所有相關的回應也會遭到刪除。",
|
||||
"typeform_redirect_url_copied": "已複製 Typeform 重新導向網址!您可以在 Typeform 表單中設定網址。",
|
||||
"modifications_in_fields_warning": "欄位與以下表單的引導路由如有任何修改之處,也會反映在此表單中。",
|
||||
"connected_forms": "連結的表單",
|
||||
"form_modifications_warning": "您在這裡修改欄位或引導路由時,以下表單也會受到影響。",
|
||||
"responses_collection_waiting_description": "請稍微等待系統回收答覆。您也可以自行提交表單。",
|
||||
"this_is_what_your_users_would_see": "以下是您的使用者會看到的內容",
|
||||
"identifies_name_field": "按照此名稱辨識欄位。",
|
||||
"add_1_option_per_line": "每行新增 1 個選項",
|
||||
"select_a_router": "選取引導器",
|
||||
"add_a_new_route": "新增新引導",
|
||||
"no_responses_yet": "還沒有回應",
|
||||
"this_will_be_the_placeholder": "這裡會是預留位置"
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ function Dialogs({
|
||||
isLoading={deleteMutation.isLoading}
|
||||
variety="danger"
|
||||
title={t("delete_form")}
|
||||
confirmBtn={t("delete_form_action")}
|
||||
confirmBtnText={t("delete_form_action")}
|
||||
loadingText={t("delete_form_action")}
|
||||
onConfirm={(e) => {
|
||||
if (!deleteDialogFormId) {
|
||||
@@ -230,7 +230,10 @@ function Dialogs({
|
||||
id: deleteDialogFormId,
|
||||
});
|
||||
}}>
|
||||
{t("delete_form_confirmation")}
|
||||
<ul className="list-disc pl-3">
|
||||
<li> {t("delete_form_confirmation")}</li>
|
||||
<li> {t("delete_form_confirmation_2")}</li>
|
||||
</ul>
|
||||
</ConfirmationDialogContent>
|
||||
</Dialog>
|
||||
<NewFormDialog appUrl={appUrl} />
|
||||
|
||||
@@ -12,7 +12,7 @@ export type DefaultEventLocationType = {
|
||||
type: DefaultEventLocationTypeEnum;
|
||||
label: string;
|
||||
messageForOrganizer: string;
|
||||
category: string;
|
||||
category: "in person" | "other" | "phone";
|
||||
|
||||
iconUrl: string;
|
||||
urlRegExp?: string;
|
||||
@@ -66,7 +66,7 @@ export const defaultLocations: DefaultEventLocationType[] = [
|
||||
{
|
||||
default: true,
|
||||
type: DefaultEventLocationTypeEnum.AttendeeInPerson,
|
||||
label: "attendeeInPerson",
|
||||
label: "attendee_in_person",
|
||||
variable: "address",
|
||||
organizerInputType: null,
|
||||
messageForOrganizer: "Cal will ask your invitee to enter an address before scheduling.",
|
||||
@@ -79,7 +79,7 @@ export const defaultLocations: DefaultEventLocationType[] = [
|
||||
{
|
||||
default: true,
|
||||
type: DefaultEventLocationTypeEnum.InPerson,
|
||||
label: "inPerson",
|
||||
label: "in_person",
|
||||
organizerInputType: "text",
|
||||
messageForOrganizer: "Provide an Address or Place",
|
||||
// HACK:
|
||||
@@ -91,7 +91,7 @@ export const defaultLocations: DefaultEventLocationType[] = [
|
||||
{
|
||||
default: true,
|
||||
type: DefaultEventLocationTypeEnum.Link,
|
||||
label: "Link",
|
||||
label: "link_meeting",
|
||||
organizerInputType: "text",
|
||||
variable: "locationLink",
|
||||
messageForOrganizer: "Provide a Meeting Link",
|
||||
@@ -102,7 +102,7 @@ export const defaultLocations: DefaultEventLocationType[] = [
|
||||
{
|
||||
default: true,
|
||||
type: DefaultEventLocationTypeEnum.Phone,
|
||||
label: "Attendee Phone Number",
|
||||
label: "attendee_phone_number",
|
||||
variable: "phone",
|
||||
organizerInputType: null,
|
||||
attendeeInputType: "phone",
|
||||
@@ -117,7 +117,7 @@ export const defaultLocations: DefaultEventLocationType[] = [
|
||||
{
|
||||
default: true,
|
||||
type: DefaultEventLocationTypeEnum.UserPhone,
|
||||
label: "Organizer Phone Number",
|
||||
label: "organizer_phone_number",
|
||||
messageForOrganizer: "Provide your phone number",
|
||||
organizerInputType: "phone",
|
||||
variable: "locationPhoneNumber",
|
||||
|
||||
@@ -94,23 +94,17 @@ export function getLocationGroupedOptions(integrations: ReturnType<typeof getApp
|
||||
|
||||
// Translating labels and pushing into array
|
||||
for (const category in apps) {
|
||||
const tmp = { label: category, options: apps[category] };
|
||||
if (tmp.label === "in person") {
|
||||
tmp.options = tmp.options.map((l) => ({
|
||||
const tmp = {
|
||||
label: t(category),
|
||||
options: apps[category].map((l) => ({
|
||||
...l,
|
||||
label: t(l.label),
|
||||
}));
|
||||
} else {
|
||||
tmp.options.map((l) => ({
|
||||
...l,
|
||||
label: t(l.label.toLowerCase().split(" ").join("_")),
|
||||
}));
|
||||
}
|
||||
|
||||
tmp.label = t(tmp.label);
|
||||
})),
|
||||
};
|
||||
|
||||
locations.push(tmp);
|
||||
}
|
||||
|
||||
return locations;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,6 @@ export const getConnectedCalendars = async (
|
||||
calendarCredentials.map(async (item) => {
|
||||
try {
|
||||
const { calendar, integration, credential } = item;
|
||||
let primary!: IntegrationCalendar;
|
||||
|
||||
// Don't leak credentials to the client
|
||||
const credentialId = credential.id;
|
||||
@@ -57,12 +56,7 @@ export const getConnectedCalendars = async (
|
||||
const cals = await calendar.listCalendars();
|
||||
const calendars = _(cals)
|
||||
.map((cal) => {
|
||||
if (cal.primary) {
|
||||
primary = { ...cal, credentialId };
|
||||
}
|
||||
if (cal.externalId === destinationCalendarExternalId) {
|
||||
destinationCalendar = cal;
|
||||
}
|
||||
if (cal.externalId === destinationCalendarExternalId) destinationCalendar = cal;
|
||||
return {
|
||||
...cal,
|
||||
readOnly: cal.readOnly || false,
|
||||
@@ -73,11 +67,7 @@ export const getConnectedCalendars = async (
|
||||
})
|
||||
.sortBy(["primary"])
|
||||
.value();
|
||||
|
||||
if (primary && destinationCalendar) {
|
||||
destinationCalendar.primaryEmail = primary.email;
|
||||
destinationCalendar.integrationTitle = integration.title;
|
||||
}
|
||||
const primary = calendars.find((item) => item.primary) ?? calendars.find((cal) => cal !== undefined);
|
||||
if (!primary) {
|
||||
return {
|
||||
integration,
|
||||
@@ -87,6 +77,10 @@ export const getConnectedCalendars = async (
|
||||
},
|
||||
};
|
||||
}
|
||||
if (destinationCalendar) {
|
||||
destinationCalendar.primaryEmail = primary.email;
|
||||
destinationCalendar.integrationTitle = integration.title;
|
||||
}
|
||||
|
||||
return {
|
||||
integration: cleanIntegrationKeys(integration),
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import getLabelValueMapFromResponses from "@calcom/lib/getLabelValueMapFromResponses";
|
||||
import type { CalendarEvent } from "@calcom/types/Calendar";
|
||||
|
||||
import { Info } from "./Info";
|
||||
|
||||
export function UserFieldsResponses(props: { calEvent: CalendarEvent }) {
|
||||
const { customInputs, userFieldsResponses } = props.calEvent;
|
||||
const responses = userFieldsResponses || customInputs;
|
||||
if (!responses) return null;
|
||||
const labelValueMap = getLabelValueMapFromResponses(props.calEvent);
|
||||
|
||||
if (!labelValueMap) return null;
|
||||
return (
|
||||
<>
|
||||
{Object.keys(responses).map((key) =>
|
||||
responses[key] !== "" ? (
|
||||
<Info key={key} label={key} description={`${responses[key]}`} withSpacer />
|
||||
{Object.keys(labelValueMap).map((key) =>
|
||||
labelValueMap[key] !== "" ? (
|
||||
<Info key={key} label={key} description={`${labelValueMap[key]}`} withSpacer />
|
||||
) : null
|
||||
)}
|
||||
</>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { DateArray } from "ics";
|
||||
import type { DateArray, ParticipationStatus, ParticipationRole } from "ics";
|
||||
import { createEvent } from "ics";
|
||||
import type { TFunction } from "next-i18next";
|
||||
import { RRule } from "rrule";
|
||||
@@ -36,6 +36,8 @@ export default class AttendeeScheduledEmail extends BaseEmail {
|
||||
// ics appends "RRULE:" already, so removing it from RRule generated string
|
||||
recurrenceRule = new RRule(this.calEvent.recurringEvent).toString().replace("RRULE:", "");
|
||||
}
|
||||
const partstat: ParticipationStatus = "NEEDS-ACTION";
|
||||
const role: ParticipationRole = "REQ-PARTICIPANT";
|
||||
const icsEvent = createEvent({
|
||||
start: dayjs(this.calEvent.startTime)
|
||||
.utc()
|
||||
@@ -52,14 +54,21 @@ export default class AttendeeScheduledEmail extends BaseEmail {
|
||||
...this.calEvent.attendees.map((attendee: Person) => ({
|
||||
name: attendee.name,
|
||||
email: attendee.email,
|
||||
partstat,
|
||||
role,
|
||||
rsvp: true,
|
||||
})),
|
||||
...(this.calEvent.team?.members
|
||||
? this.calEvent.team?.members.map((member: Person) => ({
|
||||
name: member.name,
|
||||
email: member.email,
|
||||
partstat,
|
||||
role,
|
||||
rsvp: true,
|
||||
}))
|
||||
: []),
|
||||
],
|
||||
method: "REQUEST",
|
||||
...{ recurrenceRule },
|
||||
status: "CONFIRMED",
|
||||
});
|
||||
@@ -74,6 +83,7 @@ export default class AttendeeScheduledEmail extends BaseEmail {
|
||||
icalEvent: {
|
||||
filename: "event.ics",
|
||||
content: this.getiCalEventAsString(),
|
||||
method: "REQUEST",
|
||||
},
|
||||
to: `${this.attendee.name} <${this.attendee.email}>`,
|
||||
from: `${this.calEvent.organizer.name} <${this.getMailerOptions().from}>`,
|
||||
|
||||
@@ -363,11 +363,23 @@ function getBookingData({
|
||||
const reqBody = bookingDataSchema.parse(req.body);
|
||||
if ("responses" in reqBody) {
|
||||
const responses = reqBody.responses;
|
||||
const userFieldsResponses = {} as typeof responses;
|
||||
const calEventResponses = {} as NonNullable<CalendarEvent["responses"]>;
|
||||
const calEventUserFieldsResponses = {} as NonNullable<CalendarEvent["userFieldsResponses"]>;
|
||||
eventType.bookingFields.forEach((field) => {
|
||||
if (field.editable === "user" || field.editable === "user-readonly") {
|
||||
userFieldsResponses[field.name] = responses[field.name];
|
||||
const label = field.label || field.defaultLabel;
|
||||
if (!label) {
|
||||
throw new Error('Missing label for booking field "' + field.name + '"');
|
||||
}
|
||||
if (field.editable === "user" || field.editable === "user-readonly") {
|
||||
calEventUserFieldsResponses[field.name] = {
|
||||
label,
|
||||
value: responses[field.name],
|
||||
};
|
||||
}
|
||||
calEventResponses[field.name] = {
|
||||
label,
|
||||
value: responses[field.name],
|
||||
};
|
||||
});
|
||||
return {
|
||||
...reqBody,
|
||||
@@ -377,8 +389,9 @@ function getBookingData({
|
||||
location: responses.location?.optionValue || responses.location?.value || "",
|
||||
smsReminderNumber: responses.smsReminderNumber,
|
||||
notes: responses.notes || "",
|
||||
userFieldsResponses,
|
||||
calEventUserFieldsResponses,
|
||||
rescheduleReason: responses.rescheduleReason,
|
||||
calEventResponses,
|
||||
};
|
||||
} else {
|
||||
// Check if required custom inputs exist
|
||||
@@ -721,7 +734,8 @@ async function handler(
|
||||
}
|
||||
|
||||
const responses = "responses" in reqBody ? reqBody.responses : null;
|
||||
const userFieldsResponses = "userFieldsResponses" in reqBody ? reqBody.userFieldsResponses : null;
|
||||
const calEventUserFieldsResponses =
|
||||
"calEventUserFieldsResponses" in reqBody ? reqBody.calEventUserFieldsResponses : null;
|
||||
let evt: CalendarEvent = {
|
||||
type: eventType.title,
|
||||
title: getEventName(eventNameObject), //this needs to be either forced in english, or fetched for each attendee and organizer separately
|
||||
@@ -737,8 +751,8 @@ async function handler(
|
||||
timeZone: organizerUser.timeZone,
|
||||
language: { translate: tOrganizer, locale: organizerUser.locale ?? "en" },
|
||||
},
|
||||
responses,
|
||||
userFieldsResponses,
|
||||
responses: "calEventResponses" in reqBody ? reqBody.calEventResponses : null,
|
||||
userFieldsResponses: calEventUserFieldsResponses,
|
||||
attendees: attendeesList,
|
||||
location: bookingLocation, // Will be processed by the EventManager later.
|
||||
/** For team events & dynamic collective events, we will need to handle each member destinationCalendar eventually */
|
||||
|
||||
@@ -8,7 +8,7 @@ import type {
|
||||
|
||||
import {WEBAPP_URL} from "@calcom/lib/constants";
|
||||
|
||||
import {samlDatabaseUrl, samlAudience, samlPath, oidcPath} from "./saml";
|
||||
import { samlDatabaseUrl, samlAudience, samlPath, oidcPath, clientSecretVerifier } from "./saml";
|
||||
|
||||
// Set the required options. Refer to https://github.com/boxyhq/jackson#configuration for the full list
|
||||
const opts: JacksonOption = {
|
||||
@@ -22,6 +22,8 @@ const opts: JacksonOption = {
|
||||
url: samlDatabaseUrl,
|
||||
encryptionKey: process.env.CALENDSO_ENCRYPTION_KEY,
|
||||
},
|
||||
idpEnabled: true,
|
||||
clientSecretVerifier,
|
||||
};
|
||||
|
||||
let connectionController: IConnectionAPIController;
|
||||
|
||||
@@ -13,6 +13,7 @@ export const samlProductID = "Cal.com";
|
||||
export const samlAudience = "https://saml.cal.com";
|
||||
export const samlPath = "/api/auth/saml/callback";
|
||||
export const oidcPath = "/api/auth/oidc";
|
||||
export const clientSecretVerifier = process.env.SAML_CLIENT_SECRET_VERIFIER || "dummy";
|
||||
|
||||
export const hostedCal = Boolean(HOSTED_CAL_FEATURES);
|
||||
export const tenantPrefix = "team-";
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
import FreshChatMenuItem from "../lib/freshchat/FreshChatMenuItem";
|
||||
import HelpscoutMenuItem from "../lib/helpscout/HelpscoutMenuItem";
|
||||
import IntercomMenuItem from "../lib/intercom/IntercomMenuItem";
|
||||
import ZendeskMenuItem from "../lib/zendesk/ZendeskMenuItem";
|
||||
|
||||
export default function HelpMenuItem() {
|
||||
interface ContactMenuItem {
|
||||
onHelpItemSelect: () => void;
|
||||
}
|
||||
|
||||
export default function ContactMenuItem(props: ContactMenuItem) {
|
||||
const { onHelpItemSelect } = props;
|
||||
return (
|
||||
<>
|
||||
<IntercomMenuItem />
|
||||
<ZendeskMenuItem />
|
||||
<HelpscoutMenuItem />
|
||||
<IntercomMenuItem onHelpItemSelect={onHelpItemSelect} />
|
||||
<ZendeskMenuItem onHelpItemSelect={onHelpItemSelect} />
|
||||
<HelpscoutMenuItem onHelpItemSelect={onHelpItemSelect} />
|
||||
<FreshChatMenuItem onHelpItemSelect={onHelpItemSelect} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ import { trpc } from "@calcom/trpc/react";
|
||||
import { Button, showToast } from "@calcom/ui";
|
||||
import { FiExternalLink, FiAlertTriangle } from "@calcom/ui/components/icon";
|
||||
|
||||
import { useFreshChat } from "../lib/freshchat/FreshChatProvider";
|
||||
import { isFreshChatEnabled } from "../lib/freshchat/FreshChatScript";
|
||||
import ContactMenuItem from "./ContactMenuItem";
|
||||
|
||||
interface HelpMenuItemProps {
|
||||
@@ -21,6 +23,8 @@ export default function HelpMenuItem({ onHelpItemSelect }: HelpMenuItemProps) {
|
||||
const [, loadChat] = useChat();
|
||||
const { t } = useLocale();
|
||||
|
||||
const { setActive: setFreshChat } = useFreshChat();
|
||||
|
||||
const mutation = trpc.viewer.submitFeedback.useMutation({
|
||||
onSuccess: () => {
|
||||
setDisableSubmit(true);
|
||||
@@ -43,7 +47,6 @@ export default function HelpMenuItem({ onHelpItemSelect }: HelpMenuItemProps) {
|
||||
<div className="w-full py-5">
|
||||
<p className="mb-1 px-5 text-gray-500">{t("resources").toUpperCase()}</p>
|
||||
<a
|
||||
onClick={() => onHelpItemSelect()}
|
||||
href="https://docs.cal.com/"
|
||||
target="_blank"
|
||||
className="flex w-full px-5 py-2 pr-4 text-sm font-medium text-gray-700 hover:bg-gray-100 hover:text-gray-900"
|
||||
@@ -57,7 +60,6 @@ export default function HelpMenuItem({ onHelpItemSelect }: HelpMenuItemProps) {
|
||||
/>
|
||||
</a>
|
||||
<a
|
||||
onClick={() => onHelpItemSelect()}
|
||||
href="https://developer.cal.com/"
|
||||
target="_blank"
|
||||
className="flex w-full px-5 py-2 pr-4 text-sm font-medium text-gray-700 hover:bg-gray-100 hover:text-gray-900"
|
||||
@@ -70,8 +72,8 @@ export default function HelpMenuItem({ onHelpItemSelect }: HelpMenuItemProps) {
|
||||
)}
|
||||
/>
|
||||
</a>
|
||||
<div onClick={() => onHelpItemSelect()}>
|
||||
<ContactMenuItem />
|
||||
<div>
|
||||
<ContactMenuItem onHelpItemSelect={onHelpItemSelect} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -202,7 +204,11 @@ export default function HelpMenuItem({ onHelpItemSelect }: HelpMenuItemProps) {
|
||||
className="font-medium underline hover:text-gray-700"
|
||||
onClick={() => {
|
||||
setActive(true);
|
||||
loadChat({ open: true });
|
||||
if (isFreshChatEnabled) {
|
||||
setFreshChat(true);
|
||||
} else {
|
||||
loadChat({ open: true });
|
||||
}
|
||||
onHelpItemSelect();
|
||||
}}>
|
||||
{t("contact_support")}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
|
||||
import { useFreshChat } from "./FreshChatProvider";
|
||||
import { isFreshChatEnabled } from "./FreshChatScript";
|
||||
|
||||
interface FreshChatMenuItemProps {
|
||||
onHelpItemSelect: () => void;
|
||||
}
|
||||
|
||||
export default function FreshChatMenuItem(props: FreshChatMenuItemProps) {
|
||||
const { onHelpItemSelect } = props;
|
||||
const { t } = useLocale();
|
||||
|
||||
const { setActive } = useFreshChat();
|
||||
|
||||
if (!isFreshChatEnabled) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
onClick={() => {
|
||||
setActive(true);
|
||||
onHelpItemSelect();
|
||||
}}
|
||||
className="flex w-full px-5 py-2 pr-4 text-sm font-medium text-gray-700 hover:bg-gray-100 hover:text-gray-900">
|
||||
{t("contact_support")}
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import type { ReactNode, Dispatch, SetStateAction } from "react";
|
||||
import { createContext, useState, useContext } from "react";
|
||||
|
||||
import FreshChatScript from "./FreshChatScript";
|
||||
|
||||
type FreshChatContextType = { active: boolean; setActive: Dispatch<SetStateAction<boolean>> };
|
||||
|
||||
const FreshChatContext = createContext<FreshChatContextType>({ active: false, setActive: () => undefined });
|
||||
|
||||
interface FreshChatProviderProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
export const useFreshChat = () => useContext(FreshChatContext);
|
||||
|
||||
export default function FreshChatProvider(props: FreshChatProviderProps) {
|
||||
const [active, setActive] = useState(false);
|
||||
|
||||
return (
|
||||
<FreshChatContext.Provider value={{ active, setActive }}>
|
||||
{props.children}
|
||||
{active && <FreshChatScript />}
|
||||
</FreshChatContext.Provider>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import Script from "next/script";
|
||||
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
fcWidget: any;
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
||||
const host = process.env.NEXT_PUBLIC_FRESHCHAT_HOST;
|
||||
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
||||
const token = process.env.NEXT_PUBLIC_FRESHCHAT_TOKEN;
|
||||
|
||||
export const isFreshChatEnabled = host !== "undefined" && token !== "undefined";
|
||||
|
||||
export default function FreshChatScript() {
|
||||
const { data } = trpc.viewer.me.useQuery();
|
||||
return (
|
||||
<Script
|
||||
id="fresh-chat-sdk"
|
||||
src="https://wchat.freshchat.com/js/widget.js"
|
||||
onLoad={() => {
|
||||
window.fcWidget.init({
|
||||
token,
|
||||
host,
|
||||
externalId: data?.id,
|
||||
lastName: data?.name,
|
||||
email: data?.email,
|
||||
meta: {
|
||||
username: data?.username,
|
||||
},
|
||||
open: true,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -3,7 +3,12 @@ import { HelpScout, useChat } from "react-live-chat-loader";
|
||||
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
|
||||
export default function HelpscoutMenuItem() {
|
||||
interface HelpscoutMenuItemProps {
|
||||
onHelpItemSelect: () => void;
|
||||
}
|
||||
|
||||
export default function HelpscoutMenuItem(props: HelpscoutMenuItemProps) {
|
||||
const { onHelpItemSelect } = props;
|
||||
const { t } = useLocale();
|
||||
const [active, setActive] = useState(false);
|
||||
|
||||
@@ -12,19 +17,21 @@ export default function HelpscoutMenuItem() {
|
||||
function handleClick() {
|
||||
setActive(true);
|
||||
loadChat({ open: true });
|
||||
onHelpItemSelect();
|
||||
}
|
||||
|
||||
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
||||
if (!process.env.NEXT_PUBLIC_HELPSCOUT_KEY) return null;
|
||||
else
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
onClick={handleClick}
|
||||
className="flex w-full px-5 py-2 pr-4 text-sm font-medium text-gray-700 hover:bg-gray-100 hover:text-gray-900">
|
||||
{t("contact_support")}
|
||||
</button>
|
||||
|
||||
{active && <HelpScout color="#292929" icon="message" horizontalPosition="right" zIndex="1" />}
|
||||
</>
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
onClick={handleClick}
|
||||
className="flex w-full px-5 py-2 pr-4 text-sm font-medium text-gray-700 hover:bg-gray-100 hover:text-gray-900">
|
||||
{t("contact_support")}
|
||||
</button>
|
||||
|
||||
{active && <HelpScout color="#292929" icon="message" horizontalPosition="right" zIndex="1" />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,19 +2,26 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
|
||||
import { useIntercom } from "./useIntercom";
|
||||
|
||||
export default function IntercomMenuItem() {
|
||||
interface IntercomMenuItemProps {
|
||||
onHelpItemSelect: () => void;
|
||||
}
|
||||
|
||||
export default function IntercomMenuItem(props: IntercomMenuItemProps) {
|
||||
const { onHelpItemSelect } = props;
|
||||
const { t } = useLocale();
|
||||
const { boot, show } = useIntercom();
|
||||
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
||||
if (!process.env.NEXT_PUBLIC_INTERCOM_APP_ID) return null;
|
||||
else
|
||||
return (
|
||||
<button
|
||||
onClick={() => {
|
||||
boot();
|
||||
show();
|
||||
}}
|
||||
className="flex w-full px-5 py-2 pr-4 text-sm font-medium text-gray-700 hover:bg-gray-100 hover:text-gray-900">
|
||||
{t("contact_support")}
|
||||
</button>
|
||||
);
|
||||
|
||||
return (
|
||||
<button
|
||||
onClick={() => {
|
||||
boot();
|
||||
show();
|
||||
onHelpItemSelect();
|
||||
}}
|
||||
className="flex w-full px-5 py-2 pr-4 text-sm font-medium text-gray-700 hover:bg-gray-100 hover:text-gray-900">
|
||||
{t("contact_support")}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,24 +3,33 @@ import { useState } from "react";
|
||||
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
|
||||
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
||||
const ZENDESK_KEY = process.env.NEXT_PUBLIC_ZENDESK_KEY;
|
||||
|
||||
export default function ZendeskMenuItem() {
|
||||
interface ZendeskMenuItemProps {
|
||||
onHelpItemSelect: () => void;
|
||||
}
|
||||
|
||||
export default function ZendeskMenuItem(props: ZendeskMenuItemProps) {
|
||||
const { onHelpItemSelect } = props;
|
||||
const [active, setActive] = useState(false);
|
||||
const { t } = useLocale();
|
||||
|
||||
if (!process.env.NEXT_PUBLIC_ZENDESK_KEY) return null;
|
||||
else
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
onClick={() => setActive(true)}
|
||||
className="flex w-full px-5 py-2 pr-4 text-sm font-medium text-gray-700 hover:bg-gray-100 hover:text-gray-900">
|
||||
{t("contact_support")}
|
||||
</button>
|
||||
{active && (
|
||||
<Script id="ze-snippet" src={"https://static.zdassets.com/ekr/snippet.js?key=" + ZENDESK_KEY} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
if (!ZENDESK_KEY) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
onClick={() => {
|
||||
setActive(true);
|
||||
onHelpItemSelect();
|
||||
}}
|
||||
className="flex w-full px-5 py-2 pr-4 text-sm font-medium text-gray-700 hover:bg-gray-100 hover:text-gray-900">
|
||||
{t("contact_support")}
|
||||
</button>
|
||||
{active && (
|
||||
<Script id="ze-snippet" src={"https://static.zdassets.com/ekr/snippet.js?key=" + ZENDESK_KEY} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { trpc } from "@calcom/trpc/react";
|
||||
import { Avatar, Button, Form, ImageUploader, TextField } from "@calcom/ui";
|
||||
import { FiArrowRight } from "@calcom/ui/components/icon";
|
||||
|
||||
import { NewTeamFormValues } from "../lib/types";
|
||||
import type { NewTeamFormValues } from "../lib/types";
|
||||
|
||||
const querySchema = z.object({
|
||||
returnTo: z.string(),
|
||||
@@ -140,10 +140,14 @@ export const CreateANewTeamForm = () => {
|
||||
{t("cancel")}
|
||||
</Button>
|
||||
<Button
|
||||
disabled={createTeamMutation.isLoading}
|
||||
disabled={
|
||||
newTeamFormMethods.formState.isSubmitting ||
|
||||
createTeamMutation.isError ||
|
||||
createTeamMutation.isLoading
|
||||
}
|
||||
color="primary"
|
||||
type="submit"
|
||||
EndIcon={FiArrowRight}
|
||||
type="submit"
|
||||
className="w-full justify-center">
|
||||
{t("continue")}
|
||||
</Button>
|
||||
|
||||
@@ -48,7 +48,7 @@ const locationFormSchema = z.array(
|
||||
);
|
||||
|
||||
const querySchema = z.object({
|
||||
eventPage: z.string(),
|
||||
eventPage: z.string().optional(),
|
||||
teamId: z.union([z.string().transform((val) => +val), z.number()]).optional(),
|
||||
title: z.string().optional(),
|
||||
slug: z.string().optional(),
|
||||
|
||||
@@ -286,6 +286,7 @@ export const FormBuilder = function FormBuilder({
|
||||
return (
|
||||
<li
|
||||
key={index}
|
||||
data-testid={`field-${field.name}`}
|
||||
className="group relative flex items-center justify-between border-b p-4 last:border-b-0">
|
||||
<button
|
||||
type="button"
|
||||
@@ -322,6 +323,7 @@ export const FormBuilder = function FormBuilder({
|
||||
{field.editable !== "user-readonly" && (
|
||||
<div className="flex items-center space-x-2">
|
||||
<Switch
|
||||
data-testid="toggle-field"
|
||||
disabled={field.editable === "system"}
|
||||
tooltip={field.editable === "system" ? t("form_builder_system_field_cant_toggle") : ""}
|
||||
checked={!field.hidden}
|
||||
@@ -356,7 +358,12 @@ export const FormBuilder = function FormBuilder({
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
<Button color="minimal" onClick={addField} className="mt-4" StartIcon={FiPlus}>
|
||||
<Button
|
||||
color="minimal"
|
||||
data-testid="add-field"
|
||||
onClick={addField}
|
||||
className="mt-4"
|
||||
StartIcon={FiPlus}>
|
||||
{addFieldLabel}
|
||||
</Button>
|
||||
</div>
|
||||
@@ -368,7 +375,7 @@ export const FormBuilder = function FormBuilder({
|
||||
fieldIndex: -1,
|
||||
})
|
||||
}>
|
||||
<DialogContent>
|
||||
<DialogContent enableOverflow>
|
||||
<DialogHeader title={t("add_a_booking_question")} subtitle={t("form_builder_field_add_subtitle")} />
|
||||
<div>
|
||||
<Form
|
||||
@@ -405,6 +412,7 @@ export const FormBuilder = function FormBuilder({
|
||||
}}>
|
||||
<SelectField
|
||||
defaultValue={FieldTypes[3]} // "text" as defaultValue
|
||||
id="test-field-type"
|
||||
isDisabled={
|
||||
fieldForm.getValues("editable") === "system" ||
|
||||
fieldForm.getValues("editable") === "system-but-optional"
|
||||
@@ -473,7 +481,9 @@ export const FormBuilder = function FormBuilder({
|
||||
/>
|
||||
<DialogFooter>
|
||||
<DialogClose color="secondary">Cancel</DialogClose>
|
||||
<Button type="submit">{isFieldEditMode ? t("save") : t("add")}</Button>
|
||||
<Button data-testid="field-add-save" type="submit">
|
||||
{isFieldEditMode ? t("save") : t("add")}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</Form>
|
||||
</div>
|
||||
@@ -684,9 +694,7 @@ export const FormBuilderField = ({
|
||||
const { t } = useLocale();
|
||||
const { control, formState } = useFormContext();
|
||||
return (
|
||||
<div
|
||||
data-form-builder-field-name={field.name}
|
||||
className={classNames(className, field.hidden ? "hidden" : "")}>
|
||||
<div data-fob-field-name={field.name} className={classNames(className, field.hidden ? "hidden" : "")}>
|
||||
<Controller
|
||||
control={control}
|
||||
// Make it a variable
|
||||
@@ -718,7 +726,7 @@ export const FormBuilderField = ({
|
||||
}
|
||||
return (
|
||||
<div
|
||||
data-field-name={field.name}
|
||||
data-testid={`error-message-${field.name}`}
|
||||
className="mt-2 flex items-center text-sm text-red-700 ">
|
||||
<FiInfo className="h-3 w-3 ltr:mr-2 rtl:ml-2" />
|
||||
<p>{t(message)}</p>
|
||||
|
||||
@@ -174,7 +174,7 @@ const SettingsSidebarContainer = ({
|
||||
return (
|
||||
<nav
|
||||
className={classNames(
|
||||
"no-scrollbar fixed bottom-0 left-0 top-0 z-50 flex max-h-screen w-56 flex-col space-y-1 overflow-x-hidden overflow-y-scroll bg-gray-50 px-2 pb-3 transition-transform max-lg:z-10 lg:sticky lg:flex",
|
||||
"no-scrollbar fixed bottom-0 left-0 top-0 z-20 flex max-h-screen w-56 flex-col space-y-1 overflow-x-hidden overflow-y-scroll bg-gray-50 px-2 pb-3 transition-transform max-lg:z-10 lg:sticky lg:flex",
|
||||
className,
|
||||
navigationIsOpenedOnMobile
|
||||
? "translate-x-0 opacity-100"
|
||||
|
||||
@@ -63,6 +63,7 @@ import {
|
||||
FiArrowLeft,
|
||||
} from "@calcom/ui/components/icon";
|
||||
|
||||
import FreshChatProvider from "../ee/support/lib/freshchat/FreshChatProvider";
|
||||
import { TeamInviteBadge } from "./TeamInviteBadge";
|
||||
|
||||
/* TODO: Migate this */
|
||||
@@ -316,106 +317,112 @@ function UserDropdown({ small }: { small?: boolean }) {
|
||||
</div>
|
||||
|
||||
<DropdownMenuPortal>
|
||||
<DropdownMenuContent
|
||||
onInteractOutside={() => {
|
||||
setMenuOpen(false);
|
||||
setHelpOpen(false);
|
||||
}}
|
||||
className="overflow-hidden rounded-md">
|
||||
{helpOpen ? (
|
||||
<HelpMenuItem onHelpItemSelect={() => onHelpItemSelect()} />
|
||||
) : (
|
||||
<>
|
||||
<DropdownMenuItem>
|
||||
<DropdownItem
|
||||
type="button"
|
||||
StartIcon={(props) => (
|
||||
<FiMoon
|
||||
className={classNames(
|
||||
user.away
|
||||
? "text-purple-500 group-hover:text-purple-700"
|
||||
: "text-gray-500 group-hover:text-gray-700",
|
||||
props.className
|
||||
)}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
)}
|
||||
onClick={() => {
|
||||
mutation.mutate({ away: !user?.away });
|
||||
utils.viewer.me.invalidate();
|
||||
}}>
|
||||
{user.away ? t("set_as_free") : t("set_as_away")}
|
||||
</DropdownItem>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
{user.username && (
|
||||
<>
|
||||
<DropdownMenuItem>
|
||||
<DropdownItem
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href={`${process.env.NEXT_PUBLIC_WEBSITE_URL}/${user.username}`}
|
||||
StartIcon={FiExternalLink}>
|
||||
{t("view_public_page")}
|
||||
</DropdownItem>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<DropdownItem
|
||||
type="button"
|
||||
StartIcon={FiLink}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
navigator.clipboard.writeText(
|
||||
`${process.env.NEXT_PUBLIC_WEBSITE_URL}/${user.username}`
|
||||
);
|
||||
showToast(t("link_copied"), "success");
|
||||
}}>
|
||||
{t("copy_public_page_link")}
|
||||
</DropdownItem>
|
||||
</DropdownMenuItem>
|
||||
</>
|
||||
)}
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>
|
||||
<DropdownItem
|
||||
StartIcon={(props) => <FiSlack strokeWidth={1.5} {...props} />}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href={JOIN_SLACK}>
|
||||
{t("join_our_slack")}
|
||||
</DropdownItem>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<DropdownItem StartIcon={FiMap} target="_blank" href={ROADMAP}>
|
||||
{t("visit_roadmap")}
|
||||
</DropdownItem>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<DropdownItem
|
||||
type="button"
|
||||
StartIcon={(props) => <FiHelpCircle aria-hidden="true" {...props} />}
|
||||
onClick={() => setHelpOpen(true)}>
|
||||
{t("help")}
|
||||
</DropdownItem>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem className="desktop-hidden hidden lg:flex">
|
||||
<DropdownItem StartIcon={FiDownload} target="_blank" rel="noreferrer" href={DESKTOP_APP_LINK}>
|
||||
{t("download_desktop_app")}
|
||||
</DropdownItem>
|
||||
</DropdownMenuItem>
|
||||
<FreshChatProvider>
|
||||
<DropdownMenuContent
|
||||
onInteractOutside={() => {
|
||||
setMenuOpen(false);
|
||||
setHelpOpen(false);
|
||||
}}
|
||||
className="overflow-hidden rounded-md">
|
||||
{helpOpen ? (
|
||||
<HelpMenuItem onHelpItemSelect={() => onHelpItemSelect()} />
|
||||
) : (
|
||||
<>
|
||||
<DropdownMenuItem>
|
||||
<DropdownItem
|
||||
type="button"
|
||||
StartIcon={(props) => (
|
||||
<FiMoon
|
||||
className={classNames(
|
||||
user.away
|
||||
? "text-purple-500 group-hover:text-purple-700"
|
||||
: "text-gray-500 group-hover:text-gray-700",
|
||||
props.className
|
||||
)}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
)}
|
||||
onClick={() => {
|
||||
mutation.mutate({ away: !user?.away });
|
||||
utils.viewer.me.invalidate();
|
||||
}}>
|
||||
{user.away ? t("set_as_free") : t("set_as_away")}
|
||||
</DropdownItem>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
{user.username && (
|
||||
<>
|
||||
<DropdownMenuItem>
|
||||
<DropdownItem
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href={`${process.env.NEXT_PUBLIC_WEBSITE_URL}/${user.username}`}
|
||||
StartIcon={FiExternalLink}>
|
||||
{t("view_public_page")}
|
||||
</DropdownItem>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<DropdownItem
|
||||
type="button"
|
||||
StartIcon={FiLink}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
navigator.clipboard.writeText(
|
||||
`${process.env.NEXT_PUBLIC_WEBSITE_URL}/${user.username}`
|
||||
);
|
||||
showToast(t("link_copied"), "success");
|
||||
}}>
|
||||
{t("copy_public_page_link")}
|
||||
</DropdownItem>
|
||||
</DropdownMenuItem>
|
||||
</>
|
||||
)}
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>
|
||||
<DropdownItem
|
||||
StartIcon={(props) => <FiSlack strokeWidth={1.5} {...props} />}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href={JOIN_SLACK}>
|
||||
{t("join_our_slack")}
|
||||
</DropdownItem>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<DropdownItem StartIcon={FiMap} target="_blank" href={ROADMAP}>
|
||||
{t("visit_roadmap")}
|
||||
</DropdownItem>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<DropdownItem
|
||||
type="button"
|
||||
StartIcon={(props) => <FiHelpCircle aria-hidden="true" {...props} />}
|
||||
onClick={() => setHelpOpen(true)}>
|
||||
{t("help")}
|
||||
</DropdownItem>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem className="desktop-hidden hidden lg:flex">
|
||||
<DropdownItem
|
||||
StartIcon={FiDownload}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href={DESKTOP_APP_LINK}>
|
||||
{t("download_desktop_app")}
|
||||
</DropdownItem>
|
||||
</DropdownMenuItem>
|
||||
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>
|
||||
<DropdownItem
|
||||
type="button"
|
||||
StartIcon={(props) => <FiLogOut aria-hidden="true" {...props} />}
|
||||
onClick={() => signOut({ callbackUrl: "/auth/logout" })}>
|
||||
{t("sign_out")}
|
||||
</DropdownItem>
|
||||
</DropdownMenuItem>
|
||||
</>
|
||||
)}
|
||||
</DropdownMenuContent>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>
|
||||
<DropdownItem
|
||||
type="button"
|
||||
StartIcon={(props) => <FiLogOut aria-hidden="true" {...props} />}
|
||||
onClick={() => signOut({ callbackUrl: "/auth/logout" })}>
|
||||
{t("sign_out")}
|
||||
</DropdownItem>
|
||||
</DropdownMenuItem>
|
||||
</>
|
||||
)}
|
||||
</DropdownMenuContent>
|
||||
</FreshChatProvider>
|
||||
</DropdownMenuPortal>
|
||||
</Dropdown>
|
||||
);
|
||||
|
||||
@@ -4,6 +4,7 @@ import { v5 as uuidv5 } from "uuid";
|
||||
import type { CalendarEvent } from "@calcom/types/Calendar";
|
||||
|
||||
import { WEBAPP_URL } from "./constants";
|
||||
import getLabelValueMapFromResponses from "./getLabelValueMapFromResponses";
|
||||
|
||||
const translator = short();
|
||||
|
||||
@@ -72,17 +73,18 @@ ${calEvent.additionalNotes}
|
||||
};
|
||||
|
||||
export const getUserFieldsResponses = (calEvent: CalendarEvent) => {
|
||||
const responses = calEvent.userFieldsResponses || calEvent.customInputs;
|
||||
if (!responses) {
|
||||
const labelValueMap = getLabelValueMapFromResponses(calEvent);
|
||||
|
||||
if (!labelValueMap) {
|
||||
return "";
|
||||
}
|
||||
const responsesString = Object.keys(responses)
|
||||
const responsesString = Object.keys(labelValueMap)
|
||||
.map((key) => {
|
||||
if (!responses) return "";
|
||||
if (responses[key] !== "") {
|
||||
if (!labelValueMap) return "";
|
||||
if (labelValueMap[key] !== "") {
|
||||
return `
|
||||
${key}:
|
||||
${responses[key]}
|
||||
${labelValueMap[key]}
|
||||
`;
|
||||
}
|
||||
})
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import type { CalendarEvent } from "@calcom/types/Calendar";
|
||||
|
||||
export default function getLabelValueMapFromResponses(calEvent: CalendarEvent) {
|
||||
const { customInputs, userFieldsResponses } = calEvent;
|
||||
|
||||
let labelValueMap: Record<string, string | string[]> = {};
|
||||
if (userFieldsResponses) {
|
||||
for (const [, value] of Object.entries(userFieldsResponses)) {
|
||||
labelValueMap[value.label] = value.value;
|
||||
}
|
||||
} else {
|
||||
labelValueMap = customInputs as Record<string, string | string[]>;
|
||||
}
|
||||
return labelValueMap;
|
||||
}
|
||||
@@ -68,6 +68,12 @@ const publicViewerRouter = router({
|
||||
locale,
|
||||
};
|
||||
}),
|
||||
countryCode: publicProcedure.query(({ ctx }) => {
|
||||
const { req } = ctx;
|
||||
|
||||
const countryCode: string | string[] = req?.headers?.["x-vercel-ip-country"] ?? "";
|
||||
return { countryCode: Array.isArray(countryCode) ? countryCode[0] : countryCode };
|
||||
}),
|
||||
samlTenantProduct: publicProcedure
|
||||
.input(
|
||||
z.object({
|
||||
|
||||
@@ -367,8 +367,10 @@ export async function getSchedule(input: z.infer<typeof getScheduleSchema>, ctx:
|
||||
const computedAvailableSlots = availableTimeSlots.reduce(
|
||||
(
|
||||
r: Record<string, { time: string; users: string[]; attendees?: number; bookingUid?: string }[]>,
|
||||
{ time: time, ...passThroughProps }
|
||||
{ time: _time, ...passThroughProps }
|
||||
) => {
|
||||
// TODO: Adds unit tests to prevent regressions in getSchedule (try multiple timezones)
|
||||
const time = _time.tz(input.timeZone);
|
||||
r[time.format("YYYY-MM-DD")] = r[time.format("YYYY-MM-DD")] || [];
|
||||
r[time.format("YYYY-MM-DD")].push({
|
||||
...passThroughProps,
|
||||
|
||||
@@ -87,7 +87,7 @@ export const ssoRouter = router({
|
||||
try {
|
||||
return await connectionController.createSAMLConnection({
|
||||
encodedRawMetadata,
|
||||
defaultRedirectUrl: `${process.env.NEXT_PUBLIC_WEBAPP_URL}/api/auth/saml/idp`,
|
||||
defaultRedirectUrl: `${process.env.NEXT_PUBLIC_WEBAPP_URL}/auth/saml-idp`,
|
||||
redirectUrl: JSON.stringify([`${process.env.NEXT_PUBLIC_WEBAPP_URL}/*`]),
|
||||
tenant: teamId ? tenantPrefix + teamId : samlTenantID,
|
||||
product: samlProductID,
|
||||
|
||||
@@ -92,6 +92,25 @@ export const viewerTeamsRouter = router({
|
||||
|
||||
if (nameCollisions) throw new TRPCError({ code: "BAD_REQUEST", message: "Team name already taken." });
|
||||
|
||||
// Ensure that the user is not duplicating a requested team
|
||||
const duplicatedRequest = await ctx.prisma.team.findFirst({
|
||||
where: {
|
||||
members: {
|
||||
some: {
|
||||
userId: ctx.user.id,
|
||||
},
|
||||
},
|
||||
metadata: {
|
||||
path: ["requestedSlug"],
|
||||
equals: slug,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (duplicatedRequest) {
|
||||
return duplicatedRequest;
|
||||
}
|
||||
|
||||
const createTeam = await ctx.prisma.team.create({
|
||||
data: {
|
||||
name,
|
||||
|
||||
Vendored
+14
-2
@@ -165,10 +165,22 @@ export interface CalendarEvent {
|
||||
seatsPerTimeSlot?: number | null;
|
||||
|
||||
// It has responses to all the fields(system + user)
|
||||
responses?: Prisma.JsonObject | null;
|
||||
responses?: Record<
|
||||
string,
|
||||
{
|
||||
value: string | string[];
|
||||
label: string;
|
||||
}
|
||||
> | null;
|
||||
|
||||
// It just has responses to only the user fields. It allows to easily iterate over to show only user fields
|
||||
userFieldsResponses?: Prisma.JsonObject | null;
|
||||
userFieldsResponses?: Record<
|
||||
string,
|
||||
{
|
||||
value: string | string[];
|
||||
label: string;
|
||||
}
|
||||
> | null;
|
||||
}
|
||||
|
||||
export interface EntryPoint {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
||||
import type { PropsWithChildren, ReactNode } from "react";
|
||||
import type { PropsWithChildren, ReactElement } from "react";
|
||||
import React from "react";
|
||||
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
@@ -7,16 +7,18 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { FiAlertCircle, FiCheck } from "../icon";
|
||||
import { DialogClose, DialogContent } from "./Dialog";
|
||||
|
||||
type ConfirmBtnType =
|
||||
| { confirmBtn?: never; confirmBtnText?: string }
|
||||
| { confirmBtnText?: never; confirmBtn?: ReactElement };
|
||||
|
||||
export type ConfirmationDialogContentProps = {
|
||||
confirmBtn?: ReactNode;
|
||||
confirmBtnText?: string;
|
||||
cancelBtnText?: string;
|
||||
isLoading?: boolean;
|
||||
loadingText?: string;
|
||||
onConfirm?: (event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
|
||||
title: string;
|
||||
variety?: "danger" | "warning" | "success";
|
||||
};
|
||||
} & ConfirmBtnType;
|
||||
|
||||
export function ConfirmationDialogContent(props: PropsWithChildren<ConfirmationDialogContentProps>) {
|
||||
const { t } = useLocale();
|
||||
|
||||
@@ -73,11 +73,11 @@ export const DialogContent = React.forwardRef<HTMLDivElement, DialogContentProps
|
||||
({ children, title, Icon, enableOverflow, type = "creation", ...props }, forwardedRef) => {
|
||||
return (
|
||||
<DialogPrimitive.Portal>
|
||||
<DialogPrimitive.Overlay className="fadeIn fixed inset-0 bg-gray-500 bg-opacity-80 transition-opacity" />
|
||||
<DialogPrimitive.Overlay className="fadeIn fixed inset-0 z-50 bg-gray-500 bg-opacity-80 transition-opacity" />
|
||||
<DialogPrimitive.Content
|
||||
{...props}
|
||||
className={classNames(
|
||||
"fadeIn fixed left-1/2 top-1/2 min-w-[360px] -translate-x-1/2 -translate-y-1/2 rounded bg-white text-left shadow-xl focus-visible:outline-none sm:w-full sm:align-middle",
|
||||
"fadeIn fixed left-1/2 top-1/2 z-50 min-w-[360px] -translate-x-1/2 -translate-y-1/2 rounded bg-white text-left shadow-xl focus-visible:outline-none sm:w-full sm:align-middle",
|
||||
props.size == "xl"
|
||||
? "p-8 sm:max-w-[90rem]"
|
||||
: props.size == "lg"
|
||||
|
||||
@@ -12,6 +12,7 @@ type Props = {
|
||||
disabled?: boolean;
|
||||
onCheckedChange?: (checked: boolean) => void;
|
||||
"data-testid"?: string;
|
||||
tooltip?: string;
|
||||
};
|
||||
|
||||
function SettingsToggle({
|
||||
@@ -21,6 +22,7 @@ function SettingsToggle({
|
||||
title,
|
||||
children,
|
||||
disabled,
|
||||
tooltip,
|
||||
...rest
|
||||
}: Props) {
|
||||
const [animateRef] = useAutoAnimate<HTMLDivElement>();
|
||||
@@ -36,9 +38,10 @@ function SettingsToggle({
|
||||
checked={checked}
|
||||
onCheckedChange={onCheckedChange}
|
||||
disabled={disabled}
|
||||
tooltip={tooltip}
|
||||
/>
|
||||
|
||||
<div className="">
|
||||
<div>
|
||||
<Label className="text-sm font-semibold leading-none text-black">{title}</Label>
|
||||
{description && <p className="-mt-1.5 text-sm leading-normal text-gray-600">{description}</p>}
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { isSupportedCountry } from "libphonenumber-js";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useState } from "react";
|
||||
import BasePhoneInput from "react-phone-number-input";
|
||||
import type { Props, Country } from "react-phone-number-input";
|
||||
import "react-phone-number-input/style.css";
|
||||
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
|
||||
export type PhoneInputProps = Props<{
|
||||
value: string;
|
||||
id?: string;
|
||||
@@ -34,16 +36,13 @@ function PhoneInput({ name, className = "", onChange, ...rest }: PhoneInputProps
|
||||
|
||||
const useDefaultCountry = () => {
|
||||
const [defaultCountry, setDefaultCountry] = useState<Country>("US");
|
||||
useEffect(() => {
|
||||
fetch("/api/countrycode")
|
||||
.then((res) => res.json())
|
||||
.then((res) => {
|
||||
if (isSupportedCountry(res.countryCode)) setDefaultCountry(res.countryCode);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
}, []);
|
||||
const query = trpc.viewer.public.countryCode.useQuery(undefined, {
|
||||
onSuccess: (data) => {
|
||||
if (isSupportedCountry(data?.countryCode)) {
|
||||
setDefaultCountry(data.countryCode as Country);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return defaultCountry;
|
||||
};
|
||||
|
||||
+16
-2
@@ -8,7 +8,15 @@ dotEnv.config({ path: ".env" });
|
||||
|
||||
const outputDir = path.join(__dirname, "test-results");
|
||||
|
||||
const DEFAULT_NAVIGATION_TIMEOUT = 15000;
|
||||
// Dev Server on local can be slow to start up and process requests. So, keep timeouts really high on local, so that tests run reliably locally
|
||||
|
||||
// So, if not in CI, keep the timers high, if the test is stuck somewhere and there is unnecessary wait developer can see in browser that it's stuck
|
||||
const DEFAULT_NAVIGATION_TIMEOUT = process.env.CI ? 15000 : 50000;
|
||||
const DEFAULT_EXPECT_TIMEOUT = process.env.CI ? 10000 : 50000;
|
||||
|
||||
// Test Timeout can hit due to slow expect, slow navigation.
|
||||
// So, it should me much higher than sum of expect and navigation timeouts as there can be many async expects and navigations in a single test
|
||||
const DEFAULT_TEST_TIMEOUT = process.env.CI ? 60000 : 120000;
|
||||
|
||||
const headless = !!process.env.CI || !!process.env.PLAYWRIGHT_HEADLESS;
|
||||
|
||||
@@ -36,7 +44,7 @@ const config: PlaywrightTestConfig = {
|
||||
forbidOnly: !!process.env.CI,
|
||||
retries: 2,
|
||||
workers: os.cpus().length,
|
||||
timeout: 60_000,
|
||||
timeout: DEFAULT_TEST_TIMEOUT,
|
||||
maxFailures: headless ? 10 : undefined,
|
||||
fullyParallel: true,
|
||||
reporter: [
|
||||
@@ -58,6 +66,9 @@ const config: PlaywrightTestConfig = {
|
||||
name: "@calcom/web",
|
||||
testDir: "./apps/web/playwright",
|
||||
testMatch: /.*\.e2e\.tsx?/,
|
||||
expect: {
|
||||
timeout: DEFAULT_EXPECT_TIMEOUT,
|
||||
},
|
||||
use: {
|
||||
...devices["Desktop Chrome"],
|
||||
/** If navigation takes more than this, then something's wrong, let's fail fast. */
|
||||
@@ -68,6 +79,9 @@ const config: PlaywrightTestConfig = {
|
||||
name: "@calcom/app-store",
|
||||
testDir: "./packages/app-store/",
|
||||
testMatch: /.*\.e2e\.tsx?/,
|
||||
expect: {
|
||||
timeout: DEFAULT_EXPECT_TIMEOUT,
|
||||
},
|
||||
use: {
|
||||
...devices["Desktop Chrome"],
|
||||
/** If navigation takes more than this, then something's wrong, let's fail fast. */
|
||||
|
||||
@@ -248,6 +248,7 @@
|
||||
"$SALESFORCE_CONSUMER_SECRET",
|
||||
"$SAML_ADMINS",
|
||||
"$SAML_DATABASE_URL",
|
||||
"$SAML_CLIENT_SECRET_VERIFIER",
|
||||
"$SEND_FEEDBACK_EMAIL",
|
||||
"$SENTRY_DSN",
|
||||
"$NEXT_PUBLIC_SENTRY_DSN",
|
||||
|
||||
@@ -53,6 +53,14 @@
|
||||
dependencies:
|
||||
"@jridgewell/trace-mapping" "^0.3.0"
|
||||
|
||||
"@ampproject/remapping@^2.2.0":
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d"
|
||||
integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==
|
||||
dependencies:
|
||||
"@jridgewell/gen-mapping" "^0.1.0"
|
||||
"@jridgewell/trace-mapping" "^0.3.9"
|
||||
|
||||
"@apidevtools/json-schema-ref-parser@9.0.9", "@apidevtools/json-schema-ref-parser@^9.0.6":
|
||||
version "9.0.9"
|
||||
resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz#d720f9256e3609621280584f2b47ae165359268b"
|
||||
@@ -85,6 +93,18 @@
|
||||
call-me-maybe "^1.0.1"
|
||||
z-schema "^4.2.3"
|
||||
|
||||
"@auth/core@^0.1.4":
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@auth/core/-/core-0.1.4.tgz#72a15907be721ddb142c57a717b2b1695017363d"
|
||||
integrity sha512-RsGtCWzbimuTUfV0ODE8NDxiJ5iDJAR3Wedj5OgdyZxTlCxSirXKf7+6g+krE6gHG3PoOkkd6xN6QENk+D60xw==
|
||||
dependencies:
|
||||
"@panva/hkdf" "1.0.2"
|
||||
cookie "0.5.0"
|
||||
jose "4.11.1"
|
||||
oauth4webapi "2.0.5"
|
||||
preact "10.11.3"
|
||||
preact-render-to-string "5.2.3"
|
||||
|
||||
"@aws-crypto/ie11-detection@^2.0.0":
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@aws-crypto/ie11-detection/-/ie11-detection-2.0.2.tgz#9c39f4a5558196636031a933ec1b4792de959d6a"
|
||||
@@ -1001,9 +1021,9 @@
|
||||
integrity sha512-CHIGpJcUQ5lU9KrPHTjBMhVwQG6CQjxfg36fGXl3qk/Gik1WwWachaXFuo0uCWJT/mStOKtcbFJCaVLihC1CMw==
|
||||
|
||||
"@babel/compat-data@^7.20.5":
|
||||
version "7.20.14"
|
||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.14.tgz#4106fc8b755f3e3ee0a0a7c27dde5de1d2b2baf8"
|
||||
integrity sha512-0YpKHD6ImkWMEINCyDAD0HLLUH/lPCefG8ld9it8DJB2wnApraKuhgYTvTY1z7UFIfBTGy5LwncZ+5HWWGbhFw==
|
||||
version "7.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.21.0.tgz#c241dc454e5b5917e40d37e525e2f4530c399298"
|
||||
integrity sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==
|
||||
|
||||
"@babel/core@7.12.9":
|
||||
version "7.12.9"
|
||||
@@ -1092,20 +1112,20 @@
|
||||
semver "^6.3.0"
|
||||
|
||||
"@babel/core@^7.17.10":
|
||||
version "7.20.12"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.12.tgz#7930db57443c6714ad216953d1356dac0eb8496d"
|
||||
integrity sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==
|
||||
version "7.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.21.0.tgz#1341aefdcc14ccc7553fcc688dd8986a2daffc13"
|
||||
integrity sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA==
|
||||
dependencies:
|
||||
"@ampproject/remapping" "^2.1.0"
|
||||
"@ampproject/remapping" "^2.2.0"
|
||||
"@babel/code-frame" "^7.18.6"
|
||||
"@babel/generator" "^7.20.7"
|
||||
"@babel/generator" "^7.21.0"
|
||||
"@babel/helper-compilation-targets" "^7.20.7"
|
||||
"@babel/helper-module-transforms" "^7.20.11"
|
||||
"@babel/helpers" "^7.20.7"
|
||||
"@babel/parser" "^7.20.7"
|
||||
"@babel/helper-module-transforms" "^7.21.0"
|
||||
"@babel/helpers" "^7.21.0"
|
||||
"@babel/parser" "^7.21.0"
|
||||
"@babel/template" "^7.20.7"
|
||||
"@babel/traverse" "^7.20.12"
|
||||
"@babel/types" "^7.20.7"
|
||||
"@babel/traverse" "^7.21.0"
|
||||
"@babel/types" "^7.21.0"
|
||||
convert-source-map "^1.7.0"
|
||||
debug "^4.1.0"
|
||||
gensync "^1.0.0-beta.2"
|
||||
@@ -1226,6 +1246,16 @@
|
||||
"@jridgewell/gen-mapping" "^0.3.2"
|
||||
jsesc "^2.5.1"
|
||||
|
||||
"@babel/generator@^7.21.0", "@babel/generator@^7.21.1":
|
||||
version "7.21.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.21.1.tgz#951cc626057bc0af2c35cd23e9c64d384dea83dd"
|
||||
integrity sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA==
|
||||
dependencies:
|
||||
"@babel/types" "^7.21.0"
|
||||
"@jridgewell/gen-mapping" "^0.3.2"
|
||||
"@jridgewell/trace-mapping" "^0.3.17"
|
||||
jsesc "^2.5.1"
|
||||
|
||||
"@babel/helper-annotate-as-pure@^7.18.6":
|
||||
version "7.18.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb"
|
||||
@@ -1405,6 +1435,14 @@
|
||||
"@babel/template" "^7.18.10"
|
||||
"@babel/types" "^7.19.0"
|
||||
|
||||
"@babel/helper-function-name@^7.21.0":
|
||||
version "7.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz#d552829b10ea9f120969304023cd0645fa00b1b4"
|
||||
integrity sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==
|
||||
dependencies:
|
||||
"@babel/template" "^7.20.7"
|
||||
"@babel/types" "^7.21.0"
|
||||
|
||||
"@babel/helper-get-function-arity@^7.16.7":
|
||||
version "7.16.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz#ea08ac753117a669f1508ba06ebcc49156387419"
|
||||
@@ -1447,7 +1485,7 @@
|
||||
dependencies:
|
||||
"@babel/types" "^7.18.6"
|
||||
|
||||
"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.20.11":
|
||||
"@babel/helper-module-transforms@^7.12.1":
|
||||
version "7.20.11"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz#df4c7af713c557938c50ea3ad0117a7944b2f1b0"
|
||||
integrity sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==
|
||||
@@ -1517,6 +1555,20 @@
|
||||
"@babel/traverse" "^7.19.6"
|
||||
"@babel/types" "^7.19.4"
|
||||
|
||||
"@babel/helper-module-transforms@^7.21.0":
|
||||
version "7.21.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz#160caafa4978ac8c00ac66636cb0fa37b024e2d2"
|
||||
integrity sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==
|
||||
dependencies:
|
||||
"@babel/helper-environment-visitor" "^7.18.9"
|
||||
"@babel/helper-module-imports" "^7.18.6"
|
||||
"@babel/helper-simple-access" "^7.20.2"
|
||||
"@babel/helper-split-export-declaration" "^7.18.6"
|
||||
"@babel/helper-validator-identifier" "^7.19.1"
|
||||
"@babel/template" "^7.20.7"
|
||||
"@babel/traverse" "^7.21.2"
|
||||
"@babel/types" "^7.21.2"
|
||||
|
||||
"@babel/helper-optimise-call-expression@^7.18.6":
|
||||
version "7.18.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe"
|
||||
@@ -1709,14 +1761,14 @@
|
||||
"@babel/traverse" "^7.19.4"
|
||||
"@babel/types" "^7.19.4"
|
||||
|
||||
"@babel/helpers@^7.20.7":
|
||||
version "7.20.13"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.20.13.tgz#e3cb731fb70dc5337134cadc24cbbad31cc87ad2"
|
||||
integrity sha512-nzJ0DWCL3gB5RCXbUO3KIMMsBY2Eqbx8mBpKGE/02PgyRQFcPQLbkQ1vyy596mZLaP+dAfD+R4ckASzNVmW3jg==
|
||||
"@babel/helpers@^7.21.0":
|
||||
version "7.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.21.0.tgz#9dd184fb5599862037917cdc9eecb84577dc4e7e"
|
||||
integrity sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==
|
||||
dependencies:
|
||||
"@babel/template" "^7.20.7"
|
||||
"@babel/traverse" "^7.20.13"
|
||||
"@babel/types" "^7.20.7"
|
||||
"@babel/traverse" "^7.21.0"
|
||||
"@babel/types" "^7.21.0"
|
||||
|
||||
"@babel/highlight@^7.16.7":
|
||||
version "7.16.10"
|
||||
@@ -1776,10 +1828,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.6.tgz#b923430cb94f58a7eae8facbffa9efd19130e7f8"
|
||||
integrity sha512-h1IUp81s2JYJ3mRkdxJgs4UvmSsRvDrx5ICSJbPvtWYv5i1nTBGcBpnog+89rAFMwvvru6E5NUHdBe01UeSzYA==
|
||||
|
||||
"@babel/parser@^7.20.13":
|
||||
version "7.20.15"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.15.tgz#eec9f36d8eaf0948bb88c87a46784b5ee9fd0c89"
|
||||
integrity sha512-DI4a1oZuf8wC+oAJA9RW6ga3Zbe8RZFt7kD9i4qAspz3I/yHet1VvC3DiSy/fsUvv5pvJuNPh0LPOdCcqinDPg==
|
||||
"@babel/parser@^7.21.0", "@babel/parser@^7.21.2":
|
||||
version "7.21.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.2.tgz#dacafadfc6d7654c3051a66d6fe55b6cb2f2a0b3"
|
||||
integrity sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==
|
||||
|
||||
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6":
|
||||
version "7.18.6"
|
||||
@@ -2330,7 +2382,14 @@
|
||||
dependencies:
|
||||
"@babel/plugin-transform-react-jsx" "^7.18.6"
|
||||
|
||||
"@babel/plugin-transform-react-jsx-self@^7.16.7", "@babel/plugin-transform-react-jsx-self@^7.18.6":
|
||||
"@babel/plugin-transform-react-jsx-self@^7.16.7":
|
||||
version "7.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.21.0.tgz#ec98d4a9baafc5a1eb398da4cf94afbb40254a54"
|
||||
integrity sha512-f/Eq+79JEu+KUANFks9UZCcvydOOGMgF7jBrcwjHa5jTZD8JivnhCJYvmlhR/WTXBWonDExPoW0eO/CR4QJirA==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.20.2"
|
||||
|
||||
"@babel/plugin-transform-react-jsx-self@^7.18.6":
|
||||
version "7.18.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.18.6.tgz#3849401bab7ae8ffa1e3e5687c94a753fc75bda7"
|
||||
integrity sha512-A0LQGx4+4Jv7u/tWzoJF7alZwnBDQd6cGLh9P+Ttk4dpiL+J5p7NSNv/9tlEFFJDq3kjxOavWmbm6t0Gk+A3Ig==
|
||||
@@ -2363,15 +2422,15 @@
|
||||
"@babel/types" "^7.18.6"
|
||||
|
||||
"@babel/plugin-transform-react-jsx@^7.17.3":
|
||||
version "7.20.13"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.20.13.tgz#f950f0b0c36377503d29a712f16287cedf886cbb"
|
||||
integrity sha512-MmTZx/bkUrfJhhYAYt3Urjm+h8DQGrPrnKQ94jLo7NLuOU+T89a7IByhKmrb8SKhrIYIQ0FN0CHMbnFRen4qNw==
|
||||
version "7.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.21.0.tgz#656b42c2fdea0a6d8762075d58ef9d4e3c4ab8a2"
|
||||
integrity sha512-6OAWljMvQrZjR2DaNhVfRz6dkCAVV+ymcLUmaf8bccGOHn2v5rHJK3tTpij0BuhdYWP4LLaqj5lwcdlpAAPuvg==
|
||||
dependencies:
|
||||
"@babel/helper-annotate-as-pure" "^7.18.6"
|
||||
"@babel/helper-module-imports" "^7.18.6"
|
||||
"@babel/helper-plugin-utils" "^7.20.2"
|
||||
"@babel/plugin-syntax-jsx" "^7.18.6"
|
||||
"@babel/types" "^7.20.7"
|
||||
"@babel/types" "^7.21.0"
|
||||
|
||||
"@babel/plugin-transform-react-jsx@^7.18.10":
|
||||
version "7.18.10"
|
||||
@@ -2840,19 +2899,19 @@
|
||||
debug "^4.1.0"
|
||||
globals "^11.1.0"
|
||||
|
||||
"@babel/traverse@^7.20.12", "@babel/traverse@^7.20.13":
|
||||
version "7.20.13"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.13.tgz#817c1ba13d11accca89478bd5481b2d168d07473"
|
||||
integrity sha512-kMJXfF0T6DIS9E8cgdLCSAL+cuCK+YEZHWiLK0SXpTo8YRj5lpJu3CDNKiIBCne4m9hhTIqUg6SYTAI39tAiVQ==
|
||||
"@babel/traverse@^7.21.0", "@babel/traverse@^7.21.2":
|
||||
version "7.21.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.21.2.tgz#ac7e1f27658750892e815e60ae90f382a46d8e75"
|
||||
integrity sha512-ts5FFU/dSUPS13tv8XiEObDu9K+iagEKME9kAbaP7r0Y9KtZJZ+NGndDvWoRAYNpeWafbpFeki3q9QoMD6gxyw==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.18.6"
|
||||
"@babel/generator" "^7.20.7"
|
||||
"@babel/generator" "^7.21.1"
|
||||
"@babel/helper-environment-visitor" "^7.18.9"
|
||||
"@babel/helper-function-name" "^7.19.0"
|
||||
"@babel/helper-function-name" "^7.21.0"
|
||||
"@babel/helper-hoist-variables" "^7.18.6"
|
||||
"@babel/helper-split-export-declaration" "^7.18.6"
|
||||
"@babel/parser" "^7.20.13"
|
||||
"@babel/types" "^7.20.7"
|
||||
"@babel/parser" "^7.21.2"
|
||||
"@babel/types" "^7.21.2"
|
||||
debug "^4.1.0"
|
||||
globals "^11.1.0"
|
||||
|
||||
@@ -2925,6 +2984,15 @@
|
||||
"@babel/helper-validator-identifier" "^7.19.1"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@babel/types@^7.21.0", "@babel/types@^7.21.2":
|
||||
version "7.21.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.2.tgz#92246f6e00f91755893c2876ad653db70c8310d1"
|
||||
integrity sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw==
|
||||
dependencies:
|
||||
"@babel/helper-string-parser" "^7.19.4"
|
||||
"@babel/helper-validator-identifier" "^7.19.1"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@base2/pretty-print-object@1.0.1":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@base2/pretty-print-object/-/pretty-print-object-1.0.1.tgz#371ba8be66d556812dc7fb169ebc3c08378f69d4"
|
||||
@@ -3378,26 +3446,6 @@
|
||||
minimatch "^3.1.2"
|
||||
strip-json-comments "^3.1.1"
|
||||
|
||||
"@eslint/eslintrc@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.0.0.tgz#943309d8697c52fc82c076e90c1c74fbbe69dbff"
|
||||
integrity sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==
|
||||
dependencies:
|
||||
ajv "^6.12.4"
|
||||
debug "^4.3.2"
|
||||
espree "^9.4.0"
|
||||
globals "^13.19.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"
|
||||
|
||||
"@eslint/js@8.35.0":
|
||||
version "8.35.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.35.0.tgz#b7569632b0b788a0ca0e438235154e45d42813a7"
|
||||
integrity sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==
|
||||
|
||||
"@ethereumjs/common@^2.5.0", "@ethereumjs/common@^2.6.3":
|
||||
version "2.6.3"
|
||||
resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.3.tgz#39ddece7300b336276bad6c02f6a9f1a082caa05"
|
||||
@@ -4728,6 +4776,14 @@
|
||||
magic-string "^0.26.1"
|
||||
react-docgen-typescript "^2.1.1"
|
||||
|
||||
"@jridgewell/gen-mapping@^0.1.0":
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996"
|
||||
integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==
|
||||
dependencies:
|
||||
"@jridgewell/set-array" "^1.0.0"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||
|
||||
"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2":
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9"
|
||||
@@ -4747,7 +4803,7 @@
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz#68eb521368db76d040a6315cdb24bf2483037b9c"
|
||||
integrity sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==
|
||||
|
||||
"@jridgewell/set-array@^1.0.1":
|
||||
"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
|
||||
integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
|
||||
@@ -4802,7 +4858,7 @@
|
||||
"@jridgewell/resolve-uri" "^3.0.3"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||
|
||||
"@jridgewell/trace-mapping@^0.3.14":
|
||||
"@jridgewell/trace-mapping@^0.3.14", "@jridgewell/trace-mapping@^0.3.17":
|
||||
version "0.3.17"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985"
|
||||
integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==
|
||||
@@ -5302,6 +5358,11 @@
|
||||
"@otplib/plugin-crypto" "^12.0.1"
|
||||
"@otplib/plugin-thirty-two" "^12.0.1"
|
||||
|
||||
"@panva/hkdf@1.0.2":
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@panva/hkdf/-/hkdf-1.0.2.tgz#bab0f09d09de9fd83628220d496627681bc440d6"
|
||||
integrity sha512-MSAs9t3Go7GUkMhpKC44T58DJ5KGk2vBo+h1cqQeqlMfdGkxaVB78ZWpv9gYi/g2fa4sopag9gJsNvS8XGgWJA==
|
||||
|
||||
"@panva/hkdf@^1.0.2":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@panva/hkdf/-/hkdf-1.0.4.tgz#4e02bb248402ff6c5c024e23a68438e2b0e69d67"
|
||||
@@ -5352,7 +5413,7 @@
|
||||
resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1"
|
||||
integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==
|
||||
|
||||
"@prisma/client@^4.11.0", "@prisma/client@^4.8.1":
|
||||
"@prisma/client@^4.11.0":
|
||||
version "4.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@prisma/client/-/client-4.11.0.tgz#41d5664dea4172c954190a432f70b86d3e2e629b"
|
||||
integrity sha512-0INHYkQIqgAjrt7NzhYpeDQi8x3Nvylc2uDngKyFDDj1tTRQ4uV1HnVmd1sQEraeVAN63SOK0dgCKQHlvjL0KA==
|
||||
@@ -8650,7 +8711,7 @@
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react@*", "@types/react@16 || 17 || 18", "@types/react@18.0.26", "@types/react@^18.0.17":
|
||||
"@types/react@*", "@types/react@16 || 17 || 18", "@types/react@18.0.26":
|
||||
version "18.0.26"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.26.tgz#8ad59fc01fef8eaf5c74f4ea392621749f0b7917"
|
||||
integrity sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==
|
||||
@@ -14121,52 +14182,6 @@ eslint@8.4.1:
|
||||
text-table "^0.2.0"
|
||||
v8-compile-cache "^2.0.3"
|
||||
|
||||
eslint@^8.22.0:
|
||||
version "8.35.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.35.0.tgz#fffad7c7e326bae606f0e8f436a6158566d42323"
|
||||
integrity sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==
|
||||
dependencies:
|
||||
"@eslint/eslintrc" "^2.0.0"
|
||||
"@eslint/js" "8.35.0"
|
||||
"@humanwhocodes/config-array" "^0.11.8"
|
||||
"@humanwhocodes/module-importer" "^1.0.1"
|
||||
"@nodelib/fs.walk" "^1.2.8"
|
||||
ajv "^6.10.0"
|
||||
chalk "^4.0.0"
|
||||
cross-spawn "^7.0.2"
|
||||
debug "^4.3.2"
|
||||
doctrine "^3.0.0"
|
||||
escape-string-regexp "^4.0.0"
|
||||
eslint-scope "^7.1.1"
|
||||
eslint-utils "^3.0.0"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
espree "^9.4.0"
|
||||
esquery "^1.4.2"
|
||||
esutils "^2.0.2"
|
||||
fast-deep-equal "^3.1.3"
|
||||
file-entry-cache "^6.0.1"
|
||||
find-up "^5.0.0"
|
||||
glob-parent "^6.0.2"
|
||||
globals "^13.19.0"
|
||||
grapheme-splitter "^1.0.4"
|
||||
ignore "^5.2.0"
|
||||
import-fresh "^3.0.0"
|
||||
imurmurhash "^0.1.4"
|
||||
is-glob "^4.0.0"
|
||||
is-path-inside "^3.0.3"
|
||||
js-sdsl "^4.1.4"
|
||||
js-yaml "^4.1.0"
|
||||
json-stable-stringify-without-jsonify "^1.0.1"
|
||||
levn "^0.4.1"
|
||||
lodash.merge "^4.6.2"
|
||||
minimatch "^3.1.2"
|
||||
natural-compare "^1.4.0"
|
||||
optionator "^0.9.1"
|
||||
regexpp "^3.2.0"
|
||||
strip-ansi "^6.0.1"
|
||||
strip-json-comments "^3.1.0"
|
||||
text-table "^0.2.0"
|
||||
|
||||
eslint@^8.34.0:
|
||||
version "8.34.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.34.0.tgz#fe0ab0ef478104c1f9ebc5537e303d25a8fb22d6"
|
||||
@@ -14260,13 +14275,6 @@ esquery@^1.4.0:
|
||||
dependencies:
|
||||
estraverse "^5.1.0"
|
||||
|
||||
esquery@^1.4.2:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b"
|
||||
integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==
|
||||
dependencies:
|
||||
estraverse "^5.1.0"
|
||||
|
||||
esrecurse@^4.1.0, esrecurse@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
|
||||
@@ -18287,6 +18295,11 @@ joi@^17.7.0:
|
||||
"@sideway/formula" "^3.0.1"
|
||||
"@sideway/pinpoint" "^2.0.0"
|
||||
|
||||
jose@4.11.1:
|
||||
version "4.11.1"
|
||||
resolved "https://registry.yarnpkg.com/jose/-/jose-4.11.1.tgz#8f7443549befe5bddcf4bae664a9cbc1a62da4fa"
|
||||
integrity sha512-YRv4Tk/Wlug8qicwqFNFVEZSdbROCHRAC6qu/i0dyNKr5JQdoa2pIGoS04lLO/jXQX7Z9omoNewYIVIxqZBd9Q==
|
||||
|
||||
jose@4.11.2:
|
||||
version "4.11.2"
|
||||
resolved "https://registry.yarnpkg.com/jose/-/jose-4.11.2.tgz#d9699307c02e18ff56825843ba90e2fae9f09e23"
|
||||
@@ -18297,7 +18310,7 @@ jose@^4.10.0:
|
||||
resolved "https://registry.yarnpkg.com/jose/-/jose-4.11.0.tgz#1c7f5c7806383d3e836434e8f49da531cb046a9d"
|
||||
integrity sha512-wLe+lJHeG8Xt6uEubS4x0LVjS/3kXXu9dGoj9BNnlhYq7Kts0Pbb2pvv5KiI0yaKH/eaiR0LUOBhOVo9ktd05A==
|
||||
|
||||
jose@^4.11.4:
|
||||
jose@^4.11.4, jose@^4.13.1:
|
||||
version "4.13.1"
|
||||
resolved "https://registry.yarnpkg.com/jose/-/jose-4.13.1.tgz#449111bb5ab171db85c03f1bd2cb1647ca06db1c"
|
||||
integrity sha512-MSJQC5vXco5Br38mzaQKiq9mwt7lwj2eXpgpRyQYNHYt2lq1PjkWa7DLXX0WVcQLE9HhMh3jPiufS7fhJf+CLQ==
|
||||
@@ -20687,7 +20700,7 @@ next-api-middleware@^1.0.1:
|
||||
dependencies:
|
||||
debug "^4.3.2"
|
||||
|
||||
next-auth@^4.10.3, next-auth@^4.18.8:
|
||||
next-auth@^4.18.8:
|
||||
version "4.20.1"
|
||||
resolved "https://registry.yarnpkg.com/next-auth/-/next-auth-4.20.1.tgz#6e65c4fde14171f6ce64f05f672f80f39fc418c7"
|
||||
integrity sha512-ZcTUN4qzzZ/zJYgOW0hMXccpheWtAol8QOMdMts+LYRcsPGsqf2hEityyaKyECQVw1cWInb9dF3wYwI5GZdEmQ==
|
||||
@@ -20758,13 +20771,6 @@ next-tick@^1.1.0:
|
||||
resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb"
|
||||
integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==
|
||||
|
||||
next-transpile-modules@^10.0.0:
|
||||
version "10.0.0"
|
||||
resolved "https://registry.yarnpkg.com/next-transpile-modules/-/next-transpile-modules-10.0.0.tgz#7152880048835acb64d05fc7aa34910cbe7994da"
|
||||
integrity sha512-FyeJ++Lm2Fq31gbThiRCrJlYpIY9QaI7A3TjuhQLzOix8ChQrvn5ny4MhfIthS5cy6+uK1AhDRvxVdW17y3Xdw==
|
||||
dependencies:
|
||||
enhanced-resolve "^5.10.0"
|
||||
|
||||
next-transpile-modules@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/next-transpile-modules/-/next-transpile-modules-8.0.0.tgz#56375cdc25ae5d23a834195f277fc2737b26cb97"
|
||||
@@ -20778,7 +20784,7 @@ next-validations@^0.2.0:
|
||||
resolved "https://registry.yarnpkg.com/next-validations/-/next-validations-0.2.1.tgz#68010c9b017ba48eec4f404fd42eb9b0c7324737"
|
||||
integrity sha512-92pR14MPTTx0ynlvYH2TwMf7WiGiznNL/l0dtZyKPw3x48rcMhwEZrP1ZmsMJwzp5D+U+sY2deexeLWC8rlNtQ==
|
||||
|
||||
next@^13.1.1, next@^13.2.1:
|
||||
next@^13.2.1:
|
||||
version "13.2.3"
|
||||
resolved "https://registry.yarnpkg.com/next/-/next-13.2.3.tgz#92d170e7aca421321f230ff80c35c4751035f42e"
|
||||
integrity sha512-nKFJC6upCPN7DWRx4+0S/1PIOT7vNlCT157w9AzbXEgKy6zkiPKEt5YyRUsRZkmpEqBVrGgOqNfwecTociyg+w==
|
||||
@@ -21103,6 +21109,11 @@ oauth-sign@~0.9.0:
|
||||
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
|
||||
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
|
||||
|
||||
oauth4webapi@2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/oauth4webapi/-/oauth4webapi-2.0.5.tgz#03e4ac9c29ec45423f07e47cd238cf179e0af6f8"
|
||||
integrity sha512-KmoR3KxCwmr9KvL/c/6UVzQnc4CUjo+j8NSgD3bWYlZXpUmyOVw97nDVb0BKZhCcUtGsbll16v8vsnR5JbTZ9A==
|
||||
|
||||
oauth@^0.9.15:
|
||||
version "0.9.15"
|
||||
resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1"
|
||||
@@ -22294,7 +22305,7 @@ postcss@^7.0.14, postcss@^7.0.26, postcss@^7.0.32, postcss@^7.0.36, postcss@^7.0
|
||||
picocolors "^0.2.1"
|
||||
source-map "^0.6.1"
|
||||
|
||||
postcss@^8.2.15, postcss@^8.4.13, postcss@^8.4.17, postcss@^8.4.18:
|
||||
postcss@^8.2.15, postcss@^8.4.17, postcss@^8.4.18:
|
||||
version "8.4.18"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.18.tgz#6d50046ea7d3d66a85e0e782074e7203bc7fbca2"
|
||||
integrity sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==
|
||||
@@ -22303,7 +22314,7 @@ postcss@^8.2.15, postcss@^8.4.13, postcss@^8.4.17, postcss@^8.4.18:
|
||||
picocolors "^1.0.0"
|
||||
source-map-js "^1.0.2"
|
||||
|
||||
postcss@^8.4.21:
|
||||
postcss@^8.4.13, postcss@^8.4.21:
|
||||
version "8.4.21"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.21.tgz#c639b719a57efc3187b13a1d765675485f4134f4"
|
||||
integrity sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==
|
||||
@@ -22334,6 +22345,13 @@ postgres-interval@^1.1.0:
|
||||
dependencies:
|
||||
xtend "^4.0.0"
|
||||
|
||||
preact-render-to-string@5.2.3:
|
||||
version "5.2.3"
|
||||
resolved "https://registry.yarnpkg.com/preact-render-to-string/-/preact-render-to-string-5.2.3.tgz#23d17376182af720b1060d5a4099843c7fe92fe4"
|
||||
integrity sha512-aPDxUn5o3GhWdtJtW0svRC2SS/l8D9MAgo2+AWml+BhDImb27ALf04Q2d+AHqUUOc6RdSXFIBVa2gxzgMKgtZA==
|
||||
dependencies:
|
||||
pretty-format "^3.8.0"
|
||||
|
||||
preact-render-to-string@^5.1.19:
|
||||
version "5.2.6"
|
||||
resolved "https://registry.yarnpkg.com/preact-render-to-string/-/preact-render-to-string-5.2.6.tgz#0ff0c86cd118d30affb825193f18e92bd59d0604"
|
||||
@@ -22341,6 +22359,11 @@ preact-render-to-string@^5.1.19:
|
||||
dependencies:
|
||||
pretty-format "^3.8.0"
|
||||
|
||||
preact@10.11.3, preact@^10.6.3:
|
||||
version "10.11.3"
|
||||
resolved "https://registry.yarnpkg.com/preact/-/preact-10.11.3.tgz#8a7e4ba19d3992c488b0785afcc0f8aa13c78d19"
|
||||
integrity sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==
|
||||
|
||||
preact@10.4.1:
|
||||
version "10.4.1"
|
||||
resolved "https://registry.yarnpkg.com/preact/-/preact-10.4.1.tgz#9b3ba020547673a231c6cf16f0fbaef0e8863431"
|
||||
@@ -22351,11 +22374,6 @@ preact@^10.5.9:
|
||||
resolved "https://registry.yarnpkg.com/preact/-/preact-10.10.6.tgz#1fe62aecf93974b64e6a42e09ba1f00f93207d14"
|
||||
integrity sha512-w0mCL5vICUAZrh1DuHEdOWBjxdO62lvcO++jbzr8UhhYcTbFkpegLH9XX+7MadjTl/y0feoqwQ/zAnzkc/EGog==
|
||||
|
||||
preact@^10.6.3:
|
||||
version "10.11.3"
|
||||
resolved "https://registry.yarnpkg.com/preact/-/preact-10.11.3.tgz#8a7e4ba19d3992c488b0785afcc0f8aa13c78d19"
|
||||
integrity sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==
|
||||
|
||||
prelude-ls@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
|
||||
@@ -22470,7 +22488,7 @@ prisma-field-encryption@^1.4.0:
|
||||
object-path "^0.11.8"
|
||||
zod "^3.17.3"
|
||||
|
||||
prisma@^4.11.0, prisma@^4.8.1:
|
||||
prisma@^4.11.0:
|
||||
version "4.11.0"
|
||||
resolved "https://registry.yarnpkg.com/prisma/-/prisma-4.11.0.tgz#9695ba4129a43eab3e76b5f7a033c6c020377725"
|
||||
integrity sha512-4zZmBXssPUEiX+GeL0MUq/Yyie4ltiKmGu7jCJFnYMamNrrulTBc+D+QwAQSJ01tyzeGHlD13kOnqPwRipnlNw==
|
||||
@@ -23065,11 +23083,6 @@ react-github-btn@^1.4.0:
|
||||
dependencies:
|
||||
github-buttons "^2.22.0"
|
||||
|
||||
react-hook-form@^7.34.2:
|
||||
version "7.34.2"
|
||||
resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.34.2.tgz#9ac6d1a309a7c4aaa369d1269357a70e9e9bf4de"
|
||||
integrity sha512-1lYWbEqr0GW7HHUjMScXMidGvV0BE2RJV3ap2BL7G0EJirkqpccTaawbsvBO8GZaB3JjCeFBEbnEWI1P8ZoLRQ==
|
||||
|
||||
react-hook-form@^7.43.3:
|
||||
version "7.43.3"
|
||||
resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.43.3.tgz#780af64ea1f3c5864626a377e302bfcc7750af6f"
|
||||
@@ -23802,7 +23815,7 @@ remark@^13.0.0:
|
||||
remark-stringify "^9.0.0"
|
||||
unified "^9.1.0"
|
||||
|
||||
remark@^14.0.1, remark@^14.0.2:
|
||||
remark@^14.0.2:
|
||||
version "14.0.2"
|
||||
resolved "https://registry.yarnpkg.com/remark/-/remark-14.0.2.tgz#4a1833f7441a5c29e44b37bb1843fb820797b40f"
|
||||
integrity sha512-A3ARm2V4BgiRXaUo5K0dRvJ1lbogrbXnhkJRmD0yw092/Yl0kOCZt1k9ZeElEwkZsWGsMumz6qL5MfNJH9nOBA==
|
||||
@@ -26687,11 +26700,6 @@ typeorm@0.3.11:
|
||||
xml2js "^0.4.23"
|
||||
yargs "^17.3.1"
|
||||
|
||||
typescript@^4.7.4:
|
||||
version "4.9.5"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a"
|
||||
integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==
|
||||
|
||||
typescript@^4.9.4:
|
||||
version "4.9.4"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.4.tgz#a2a3d2756c079abda241d75f149df9d561091e78"
|
||||
|
||||
Reference in New Issue
Block a user